bensampaio / external-svg-sprite-loader Goto Github PK
View Code? Open in Web Editor NEWA webpack loader and plugin that generate SVG sprites out of a collection of SVG files used in your JS and CSS files
License: MIT License
A webpack loader and plugin that generate SVG sprites out of a collection of SVG files used in your JS and CSS files
License: MIT License
First of all, great plugin!
However, it doesn't seem to work with webpack-dev-server because that runs on a separate domain. Is there any chance you can add an option to inject the SVG into the page via AJAX so that we can work around this?
Hi!
I'm trying to use this plugin but I'm having an issue with publicPath
. The sprite is generated correctly but the svg
output for each icon do not contain the /build/
prefix:
{ symbol: '/img/tf-svg-sprite.svg#tf-facebook-d5046',
view: '/img/tf-svg-sprite.svg#view-tf-facebook-d5046',
viewBox: '0 0 56.693 56.693',
toString: [Function: toString] }
should be:
{ symbol: '/build/img/tf-svg-sprite.svg#tf-facebook-d5046',
view: '/build/img/tf-svg-sprite.svg#view-tf-facebook-d5046',
viewBox: '0 0 56.693 56.693',
toString: [Function: toString] }
This causes img/tf-svg-sprite.svg
to be downloaded and fails with 404.
Adding the public path to getUrlToSymbol
and getUrlToView
works, but I'm not sure if this is the correct fix.
I'm generating multiple sprites with the following options:
{
name: 'sprites/global.[hash:8].svg',
iconName: '[name]',
}
{
name: 'sprites/brand-one.[hash:8].svg',
iconName: '[name]',
}
{
name: 'sprites/brand-two.[hash:8].svg',
iconName: '[name]',
}
In addition, I'm using webpack-assets-manifest
to generate a manifest.json
, which maps plain file names to generated, hashed file names. webpack-assets-manifest
creates a file like this:
{
"global.svg": "/static/sprites/global.bc0840f3.svg",
"brand.svg": "/static/sprites/brand-one.b71064f3.svg"
}
The problem is that the contents of the manifest.json
file contains only a single brand.svg
entry, which is named wrong (should be sprites/brand-one.svg
) and in addition to that, it lacks the file sprites/brand-two.svg
.
I was not able to find out what the actual problem is, but could it be that external-svg-sprite-loader
is emitting files in a not-so-optimal format or something similar?
The correct output of the manifest.json
file would be:
{
"sprites/global.svg": "/static/sprites/global.bc0840f3.svg",
"sprites/brand-one.svg": "/static/sprites/brand-one.b71064f3.svg",
"sprites/brand-two.svg": "/static/sprites/brand-one.b71064f3.svg"
}
Of course, this could also be a bug in webpack-assets-manifest
, but I thought I may ask here first to be sure it's not a problem with external-svg-sprite-loader
or my configuration or something. What is a bit confusing is the fact that the key in the manifest.json
is called brand.svg
and not brand-one.svg
, which is weird, because brand.svg
is not something I have configured anywhere at all.
I use next plugin's injections in my webpack.config
in rules:
{ test: /\.svg$/, use: [ { loader: SvgStorePlugin.loader, options: { name: 'sprite.svg', }, }, ], },
in plugins:
new SvgStorePlugin({}),
So, when I run project, I haven't got any sprite.svg
file. By the way, urls in css correctly replaces with sprite.svg#id=....
.
Where is the problem?
I've noticed you accept svgoOptions as a parameter but haven't seen any documentation. I'm currently running svgo locally before pushing to the repo with svgo --disable=removeViewBox --enable=removeTitle
but not sure how I'd pass this to external-svg-sprite-loader.
Any guidance would be appreciated.
Thanks
Hello! I ran into a problem when starting a storybook with a Сheckbox src/components/base/Checkbox
component that uses external-svg-sprite-loader.
Storybook webpack config - ./.storybook/main.js
I get in the console:
`
info => Using base config because react-scripts is not installed.
74% optimizing SvgStorePluginF:\Projects\webpack-broker\node_modules\external-svg-sprite-loader\lib\SvgStorePlugin.js:113
throw error;
^
TypeError: Cannot read property 'replace' of null
at SvgDocument.toSymbol (F:\Projects\webpack-broker\node_modules\external-svg-sprite-loader\lib\SvgDocument.js:158:36)
at SvgSprite.generate (F:\Projects\webpack-broker\node_modules\external-svg-sprite-loader\lib\SvgSprite.js:114:48)
at SvgStorePlugin.generateSprites (F:\Projects\webpack-broker\node_modules\external-svg-sprite-loader\lib\SvgStorePlugin.js:108:24)
at SyncHook.eval [as call] (eval at create (F:\Projects\webpack-broker\node_modules\tapable\lib\HookCodeFactory.js:19:10), :12:1)
at SyncHook.lazyCompileHook (F:\Projects\webpack-broker\node_modules\tapable\lib\Hook.js:154:20)
at Compilation.seal (F:\Projects\webpack-broker\node_modules\webpack\lib\Compilation.js:1322:23)
at compilation.finish.err (F:\Projects\webpack-broker\node_modules\webpack\lib\Compiler.js:675:18)
at hooks.finishModules.callAsync.err (F:\Projects\webpack-broker\node_modules\webpack\lib\Compilation.js:1261:4)
at AsyncSeriesHook.eval [as callAsync] (eval at create (F:\Projects\webpack-broker\node_modules\tapable\lib\HookCodeFactory.js:33:10), :20:1)
at AsyncSeriesHook.lazyCompileHook (F:\Projects\webpack-broker\node_modules\tapable\lib\Hook.js:154:20)
at Compilation.finish (F:\Projects\webpack-broker\node_modules\webpack\lib\Compilation.js:1253:28)
at hooks.make.callAsync.err (F:\Projects\webpack-broker\node_modules\webpack\lib\Compiler.js:672:17)
at _done (eval at create (F:\Projects\webpack-broker\node_modules\tapable\lib\HookCodeFactory.js:33:10), :9:1)
at _err1 (eval at create (F:\Projects\webpack-broker\node_modules\tapable\lib\HookCodeFactory.js:33:10), :32:22)
at _addModuleChain (F:\Projects\webpack-broker\node_modules\webpack\lib\Compilation.js:1185:12)
at processModuleDependencies.err (F:\Projects\webpack-broker\node_modules\webpack\lib\Compilation.js:1097:9)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] storybook: start-storybook
npm ERR! Exit status 1
`
The error is reproduced on - https://github.com/maximryabov22011988/webpack-broker
Branch - preparation_before_merge
Is it possible to fix it?
I used this plugin to generate svg sprite when it appeared, the following question. Some values can not be generated and become NaN. I can not find what is the reason, can you solve this problem?
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="icon-loading-7726d"></symbol>
<symbol id="icon-error-b67ed"></symbol>
<symbol id="icon-logo-b2031"></symbol>
<symbol id="icon-chat-e3544"></symbol>
<symbol id="icon-check-circle-o-71bb6"></symbol>
<symbol id="icon-check-circle-25051"></symbol>
</defs>
<view id="view-icon-loading-7726d" viewBox="0 0 NaN 50"></view>
<view id="view-icon-error-b67ed" viewBox="NaN 0 NaN 50"></view>
<view id="view-icon-logo-b2031" viewBox="NaN 0 NaN 50"></view>
<view id="view-icon-chat-e3544" viewBox="NaN 0 NaN 50"></view>
<view id="view-icon-check-circle-o-71bb6" viewBox="NaN 0 NaN 50"></view>
<view id="view-icon-check-circle-25051" viewBox="NaN 0 NaN 50"></view>
<use id="icon-loading-7726d" xlink:href="#icon-loading-7726d" width="NaN" height="50" x="0" y="0"></use>
<use id="icon-error-b67ed" xlink:href="#icon-error-b67ed" width="NaN" height="50" x="NaN" y="0"></use>
<use id="icon-logo-b2031" xlink:href="#icon-logo-b2031" width="NaN" height="50" x="NaN" y="0"></use>
<use id="icon-chat-e3544" xlink:href="#icon-chat-e3544" width="NaN" height="50" x="NaN" y="0"></use>
<use id="icon-check-circle-o-71bb6" xlink:href="#icon-check-circle-o-71bb6" width="NaN" height="50" x="NaN" y="0"></use>
<use id="icon-check-circle-25051" xlink:href="#icon-check-circle-25051" width="NaN" height="50" x="NaN" y="0"></use>
</svg>
It appears that webpack changed since you published.
Error: Cannot find module 'webpack/lib/OriginalSource'
at Function.Module._resolveFilename (module.js:469:15)
at Function.Module._load (module.js:417:25)
at Module.require (module.js:497:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/tauren/repos/exp/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:4:24)
I believe you need to import webpack-sources/lib/OriginalSource
in SvgStorePlugin.js.
However, after change this, I'm getting another error:
/Users/tauren/repos/exp/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:40
constructor({
^
TypeError: Cannot match against 'undefined' or 'null'.
at new SvgStorePlugin (/Users/tauren/repos/exp/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:40:16)
at module.exports (/Users/tauren/repos/exp/internals/webpack/webpack.base.babel.js:87:5)
This is resolved by explicitly passing true
in the webpack plugins config:
new SvgStorePlugin(true)
I ran into a frustrating issue that might be particular to my SVG files (exported by Sketch); the bug was caused by putting them all together as a single sprite file. I looked at SVGO options but wasn't able to solve it. Would like to figure out if there's a better/permanent fix so others don't have this issue...
The symptom was that my icons were coming out all duplicated — the first one loaded seemed to be repeating for every image instance.
The cause was that the <path>
elements inside each <symbol>
had repeating IDs — see below how id="a"
repeats (with the corresponding <use>
reference to #a
). The original Sketch exports, before the SVGO parsing, had IDs of id="path-1"
instead of all id="a"
, but that still would have broken when combined into one XML file.
<symbol id="icon-play-a6b2d" viewBox="0 0 24 24">
<defs>
<path d="..." id="a"/>
</defs>
<use xlink:href="#a" transform="translate(2)" fill-rule="evenodd"/>
</symbol>
<symbol id="icon-pause-c28a5" viewBox="0 0 24 24">
<defs>
<path d="..." id="a"/>
</defs>
<use xlink:href="#a" transform="translate(4 1)" fill-rule="evenodd"/>
</symbol>
... repetition continues
I was able to fix my particular issue by going through the individual symbols in createDefs
within SvgDocument.js
and doing a simple .replace
to create unique IDs based on the index (see below). This worked with my SVG, but I'd be nervous it might mess up more complicated SVG documents?
static createDefs(...contents) {
contents = contents.map( (symbol, index) => {
const id = `a-${index}`
return symbol.replace('xlink:href="#a"', `xlink:href="#${id}"`).replace('id="a"/>', `id="${id}"/>`)
})
return `<defs>${contents.join('')}</defs>`;
}
I'm trying to define Rule.use
as a function instead of an array, so that I can gain access to the issuer
string and use that information to generate my sprite names:
{
test: /\.svg$/,
issuer: {
include: /sprite\.js$/
},
use: (info) => ([
{
loader: "file-loader",
options: { name: "[name].[contenthash].[ext]" }
},
{
loader: SvgStorePlugin.loader,
options: {
name: `sprites/${info.issuer.split("/").pop()}.sprite.svg`,
iconName: "[name]"
}
}
])
}
Unfortunately, this results in the following error:
Module build failed (from ./node_modules/external-svg-sprite-loader/lib/loader.js):
TypeError: Cannot read property 'addIcon' of undefined
I tried hacking the SvgStorePlugin.js
file to add support for the function syntax:
injectSpritesIntoRules(rules) {
for (const rule of rules) {
const { oneOf: oneOfRules, rules: subRules, use: ruleUse } = rule;
let loaders = ruleUse || [rule];
// Check to see if ruleUse is a function
if (ruleUse && {}.toString.call(ruleUse) === '[object Function]') {
loaders = ruleUse();
}
But sprite
still ends up being undefined
in loader.js
:
function loader(content) {
const { addDependency, resource, resourcePath } = this;
// Get callback because the SVG is going to be optimized and that is an async operation
const callback = this.async();
// Parse the loader query and apply the default values in case no values are provided
const { iconName, publicPath, sprite, svgoOptions } = Object.assign({}, DEFAULT_LOADER_OPTIONS, loaderUtils.getOptions(this));
console.log(sprite); // undefined :(
I'd be willing to submit a pull request if I can figure this out, but I'm stuck. Any ideas?
As I described here, there's problems when we use a output.publicPath with different scheme/host/port (CDN).
It would be useful to have a publicPath
option that, if defined it would be used instead of output.publicPath
.
I will be doing a PR adding this feature if you agree!
Getting error as below
_`module.js:549
throw err;
^
Error: Cannot find module 'webpack/lib/Chunk'
at Function.Module._resolveFilename (module.js:547:15)
at Function.Module._load (module.js:474:25)
at Module.require (module.js:596:17)
at require (internal/module.js:11:18)
at Object. (/Library/WebServer/Documents/external-svg-sprite-loader/lib/SvgStorePlugin.js:3:15)
at Module._compile (module.js:652:30)
at Object.Module._extensions..js (module.js:663:10)
at Module.load (module.js:565:32)
at tryModuleLoad (module.js:505:12)
at Function.Module.load (module.js:497:3)`
am i missing something. i couldn't find Chunk in my webpack installation in node_modules
The sprite wraps the linearGradient of an svg inside the symbol which does not work on Firefox. It should set it inside the svg tags and reference inside the symbol.
Hey! I've run into an issue when there's some sort of error in my build (for example, an eslint error that comes via eslint-loader), then SvgStorePlugin fails. That's probably because webpack does not emit if there are any errors.
Versions (ask if anything else may be of importance):
"webpack": "^5.16.0"
"external-svg-sprite-loader": "^7.1.1"
Stack trace:
/home/mihkel/dev/garage/wordpress-base/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:223
if (typeof source._name === 'string') {
^
TypeError: Cannot read property '_name' of null
at SvgStorePlugin.replaceSpritePathsInModuleWithInterpolatedPaths (/home/mihkel/dev/garage/wordpress-base/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:223:39)
at SvgStorePlugin.fixSpritePathsInModules (/home/mihkel/dev/garage/wordpress-base/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:97:22)
at Hook.eval [as call] (eval at create (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:19:10), <anonymous>:5:16)
at Hook.CALL_DELEGATE [as _call] (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/tapable/lib/Hook.js:14:14)
at Compilation.seal (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/Compilation.js:2096:37)
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/Compiler.js:1054:20
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/Compilation.js:1925:4
at _next4 (eval at create (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:23:1)
at eval (eval at create (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:68:1)
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/FlagDependencyExportsPlugin.js:332:11
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/neo-async/async.js:2830:7
at Object.each (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/neo-async/async.js:2850:39)
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/FlagDependencyExportsPlugin.js:311:18
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/neo-async/async.js:2830:7
at Object.each (/home/mihkel/dev/garage/wordpress-base/node_modules/webpack/node_modules/neo-async/async.js:2850:39)
at /home/mihkel/dev/garage/wordpress-base/node_modules/webpack/lib/FlagDependencyExportsPlugin.js:46:16
Hello,
I am setting up a Vue.js project using Vue CLI 3.8.4. Therefore I have to use webpack-chain
to configure this plugin. Because oneOf
in webpack-chain
sets an options
prop on the rule, (as undefined
) SvgStorePlugin#injectSpriteIntoRule
errors:
ypeError: Cannot read property 'name' of undefined
at SvgStorePlugin.injectSpriteIntoRule (/node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:151:43)
Basically this check:
if (!('options' in rule)) {
rule.options = {};
}
Isn't enough.
I'm able to work around it by setting my own name in my config like this:
webpackChainConfig.module
.rule('svg')
.uses.clear()
.end()
...
.oneOf('sprite')
.test(/sprite/)
.use('external-svg-sprite-loader')
.loader(SvgStorePlugin.loader)
.options({
name: 'img/sprite.svg',
})
.end()
After upgrading to external-svg-sprite-loader
version 4, my app is now throwing the follow error when I run Webpack (version 4.25.1
):
TypeError: loaders is not iterable
at SvgStorePlugin.injectSpritesIntoRules (.../node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:177:35)
at SvgStorePlugin.apply (.../node_modules/external-svg-sprite-loader/lib/SvgStorePlugin.js:51:14)
at webpack (.../node_modules/webpack/lib/webpack.js:47:13)
...
I followed the external-svg-sprite-loader
version 4 upgrade instructions but I must be missing something because I haven't been able to figure this out.
My webpack.config.js
now looks like this (abbreviated):
const SvgStorePlugin = require("external-svg-sprite-loader");
module.exports = (env, argv) => {
return {
module: {
rules: [
{
test: /\.svg$/,
include: path.resolve(__dirname, "node_modules/foo-bar/images"),
use: {
loader: SvgStorePlugin.loader,
options: {
name: "foo/bar-sprite.svg",
iconName: argv.mode === "development" ? "[name]" : "[name]-[hash:5]"
}
}
},
{
test: /\.svg$/,
include: path.resolve(__dirname, "src/images"),
use: {
loader: SvgStorePlugin.loader,
options: {
name: "svgs/sprite.svg",
iconName: argv.mode === "development" ? "[name]" : "[name]-[hash:5]"
}
}
}
]
},
plugins: [
new SvgStorePlugin()
]
}
}
<use id="strelka" xlink:href="#strelka" width="78.75" height="50" x="NaN" y="0">
<use id="test_stand" xlink:href="#test_stand" width="33.25" height="50" x="NaN" y="0">
<use id="tractor" xlink:href="#tractor" width="33.25" height="50" x="NaN" y="0">
<use id="tractor_car" xlink:href="#tractor_car" width="33.25" height="50" x="NaN" y="0">
<use id="train" xlink:href="#train" width="33.25" height="50" x="NaN" y="0">
"external-svg-sprite-loader": "^3.3.0"
When using multiple plugin instances when compiling, e.g.: doing a client & server build, there's some unexpected behavior. The reason is that my last PR added state to the SvgSprite class which is shared among the different plugin instances. This causes the updated
flag to be out-of-sync, which in turn causes the replacements to be skipped.
To solve this issue, we need to move all this "stateful" flags to the SvgStorePlugin instead. I will be making a PR soon.
I would like to be able to do this:
{
loader: 'external-svg-sprite-loader',
options: {
name: 'img/svg-sprite.[hash].svg',
prefix: '',
svgo: {
plugins: [
{ removeTitle: true },
// Remove stuff related to colors because they are unecessary
{ removeStyleElement: true },
{ removeAttrs: { attrs: '(fill|stroke|class)' } },
],
}
},
},
I think that changing https://github.com/Karify/external-svg-sprite-loader/blob/master/index.js#L52 to account for query.svgo
would do it. Thoughts?
You've given us an option to specify the output sprite name, but is there any chance you can run it through interpolateName
so that we can use a hash? This is important for cache-busting.
First off, thanks for taking ownership of the package, maintaining and upgrading it for webpack 5. Thank a lot!
We ran into problems with external-svg-sprite-loader@6
and [email protected]
when running it wih webpack@4
. I've noticed there was a fix for the latest major version 7.x
, but it seems this fix was not implemented in the 6.x
branch; which seems to me as if 6.x
is not maintained anymore.
/node_modules/external-svg-sprite-loader/lib/SvgSprite.js:191
source = source.replace(originalResourcePathRegExp, resourcePath);
^
TypeError: source.replace is not a function
I understand that maintaining two separate versions is a lot of work but I hope you are considering adding the fix to the v6
version too, as [email protected]
supports webpack@4
as well afaik.
Thanks for your input on this issue!
Please read moxystudio/react-with-moxy#6
Would you be interested in implementing this strategy behind an option flag or is it outside of the scope of this module? Also, feedback welcome!
I have a use-case where I need to get access to produced sprites after a webpack build, that is, every sprite metadata.
At the moment, there's getSpritesWithInterpolateName
that accomplishes what I want except that it returns []
in DEV because I'm not using [hash]
in development.
I will make a PR that adds this new method.
I've setup hot module reload on a project and it's working nicely, except when adding/removing/editing svgs that go through this loader.
Maybe that's something that we could improve? See style-loader for an example: https://github.com/webpack-contrib/style-loader/blob/master/index.js#L21
I've run into an issue with the usage of [hash]
. It's not stable, i.e. it does not produce consistent results. Multiple builds -> different hashes. This breaks long term caching.
I'm also running into a problem where client and server compilation passes are running in different processes and produce different hashes for the exact same code.
The results in the SSR pass emitting incorrect asset paths that then break client hydration (React).
I'm going to suggest a fix for this.
The .svg file is exists, fine and works with other loaders (for example https://www.npmjs.com/package/svg-sprite-loader).
ERROR in ./src/assets/svg/anchor.svg Module build failed: TypeError: Cannot match against 'undefined' or 'null'. at Object.loader (/Users/macbookpro/Projects/ulmart-mobile.mobile/node_modules/external-svg-sprite-loader/index.js:37:39) @ ./src/app/app.module.js 13:10-45 @ ./src/main.js @ multi (webpack)-dev-server/client?http://0.0.0.0:9008 main.js
In external-svg-sprite-loader/index.js
on line 37 you've got this:
const { addDependency, cacheable, resourcePath, options: { output: { publicPath } } } = this;
,
but there is no options
in webpack object, there is _compilation.outputOptions.publicPush
, so you need to replace this line with this one
const { addDependency, cacheable, resourcePath, _compilation.outputOptions: { outputOptions: { publicPath } } } = this;
and everything will work.
Please, tell me if i`am not right.
The colors of my icons are missing as the styles not seem to be interpreted for the icons with classNames.
<symbol>
definition in the sprite:
<symbol xmlns="http://www.w3.org/2000/svg" id="icon-logo-d32ed" viewBox="0 0 957.31 481.44">
<defs>
<style>.cls-1{fill:#7cd6df}</style>
</defs>
<path class="cls-1" d="OMITTED"/>
<!-- More paths -->
</symbol>
<view>
definition in the sprite:
<view xmlns="http://www.w3.org/2000/svg" id="view-icon-logo-d32ed" viewBox="0 0 99.48 50"/>
<use>
definition in the sprite:
<use xmlns="http://www.w3.org/2000/svg" id="icon-logo-d32ed" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icon-logo-d32ed" width="99.48" height="50" x="0" y="0"/>
<svg>
in the page:
<svg><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/static/img/sprite.svg#icon-logo-d32ed"></use></svg>
Is there a way to not lose the styles in the page?
Hi!
I just spent quite a while trying to debug the errors that were thrown when trying to use this loader. When using emit: true
, it wouldn't compile due to .tap
not being found as a property of undefined
.
I wasn't sure what was happening, but I saw that the line that was causing the error was wrapped in if (options.emit)
, so I tried setting emit: false
, which gave me all sorts of non-explicit errors about stuff not being found in the icons' objects themselves, such as getOptions
.
I was about to give up when I had the idea to check the old release notes to discover that Webpack 4 stopped being supported in 7.0.0.
Since Vue 2 & Vue CLI 4 force me to use Webpack 4 for the moment, I downgraded to version 6 and everything worked out of the box, to my relief... and slight frustration at having spent so long for something that could've been so obvious.
It would be really nice if that was clear in the docs that Webpack <5 is unsupported, and also if, before anything else, there was an error message that explicitly mentioned the Webpack incompatibility and suggested the version to use if unable to update Webpack.
For example:
This version of external-svg-sprite-loader (7.x.x) requires at least Webpack version 5.x.x or later. You are using Webpack 4.x.x. Please update Webpack. If unable to update Webpack, please use external-svg-sprite-loader version 6.x.x, the latest version that supported your version of Webpack.
That's really long-winded though. There would probably be a smarter and more concise way to do this.
It would especially help Vue users who, through their use of Vue 2 and Vue CLI 4, may not be able to update to Webpack 5, and might even not be aware that their Webpack version is outdated due to it being obfuscated by Webpack CLI and it not being upgradable (AFAIK) unless the project is ported to Vue 3.
Edit: Also wanted to compliment you on the code. It's easy to read, well-organized, and there are helpful comments. You don't see that kind of quality often, and I really appreciated it while looking for the problem.
This line triggers a deprecation warning in webpack 5:
[DEP_WEBPACK_DEPRECATION_ARRAY_TO_SET_PUSH] DeprecationWarning: chunk.files was changed from Array to Set (using Array method 'push' is deprecated)
Hello! I am developing a webpack config for my project and encountered a Build problem. Dev work correctly.
Icons from the sprite downloaded through the CSS, work out as expected. But the icons in the component using the tag use
don't work. The sprite status is blocked: origin
My repo - https://github.com/maximryabov22011988/webpack-broker
I'm add you to Collaborators.
Thanks in advance for your reply.
Some svg documents don't have viewbox property
C:\projects\...\node_modules\external-svg-sprite-loader\lib\SvgDocument.js:94
const parts = viewBox.split(' ');
^
TypeError: Cannot read property 'split' of undefined
It passed some time since 2.2 final release was published. Currently, this plugin does not work on 2.2:
Error: Cannot find module 'webpack/lib/OriginalSource'
A bugreport here:
Due to this explicit whitelist of attributes,
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" ...>
becomes
<symbol id="..." viewBox="0 0 16 16">
I.e. fill="none" is removed and thus the image changes.
Maybe we can just copy all attributes (or blacklist some) instead of whitelisting? Because fill
may not be the only one attribute...
Webpack build fails when using both [email protected] and external-svg-sprite-loader.
I created a repo with repro: https://github.com/mihkeleidast/webpack-css-svg-issue
I originally reported this to mini-css-extract-plugin but I was told this should be fixed here: webpack-contrib/mini-css-extract-plugin#653
The external-svg-sprite-loader module addresses the individual images by doing math and resizing for the images. This (among other things) also distorts the image proportion when the image is rendered without width/height attributes of e.g. <img src="...#view-xyz"/>
.
FYI, there is an alternative (and probably simpler) approach used by svg-sprite-loader:
<svg ...>
<defs>
<style>
.sprite-symbol-usage {display: none;}
.sprite-symbol-usage:target {display: inline;}
</style>
<symbol viewBox="0 0 100 114" id="img1">...</symbol>
<symbol viewBox="0 0 50 50" id="img2">...</symbol>
</defs>
<use id="view-img1" xlink:href="#img1" class="sprite-symbol-usage" />
<use id="view-img2" xlink:href="#img2" class="sprite-symbol-usage" />
</svg>
There is no math/resizing here, and also we can see that all the images render at (0, 0) with their native width and height; the images are invisible due to .sprite-symbol-usage class.
But when the sprite file is addressed as e.g. <img src="sprite.svg#view-img2"/>
, then, due to :target pseudo-class, the selected <use/>
becomes visible.
P.S.
The full demo:
a.svg:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<style>
.sprite-symbol-usage {display: none;}
.sprite-symbol-usage:target {display: inline;}
</style>
<symbol viewBox="0 0 16 16" id="img1" fill="none">
<path d="M15 8C15 8 11.9 11.5 8 11.5C4.1 11.5 1 8 1 8C1 8 4.1 4.5 8 4.5C11.9 4.5 15 8 15 8Z" stroke="black" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
<symbol viewBox="0 0 16 16" id="img2" fill="none">
<path d="M15.5 6.5V13.5C15.5 14.6 14.6 15.5 13.5 15.5H3.5C2.4 15.5 1.5 14.6 1.5 13.5V6.5" stroke="black" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</symbol>
</defs>
<use id="view-img1" xlink:href="#img1" class="sprite-symbol-usage" />
<use id="view-img2" xlink:href="#img2" class="sprite-symbol-usage" />
</svg>
a.html:
<img src="a.svg#view-img2" />
This loader looks great and I can get it to build the SVG files just fine.
However, I'm unsure how to use this within my HTML / Pug files? I can't see an example showing this at all.
Because the ID's are generated from their original file names and then made unique, I'm unable to reference them. e.g. If I have an SVG like 'mark.svg', I'm unable to do:
<svg class="c-splash__mark">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="svg/sprite.svg#mark"></use>
</svg>
...because the resulting ID is something like '-mark-97878'.
I can see how to use this in JS, but would be great to see an example with just straight HTML. I'm actually using Pug templates though.
Or, is there an option to keep the ID's the same as the original filenames? That way I already know how to link to it.
Apologies if this is not an 'issue' per se, but thought it might help give some more thought to the documentation in the process?
Thank you!
external-svg-sprite-loader helps me save a good clean sprite.[hash:8].svg file!
I've tried to use it with webpack-manifest-plugin and webpack-assets-manifest to generate a manifest.json, used to find the corresponding compiled /path/to/sprite.svg -> /path/to/sprite.[hash:8].svg
But I can not obtain the good filename and path to my sprite.svg file. Note that webpack-manifest-plugin and webpack-assets-manifest generate the good filenames when used with other loaders.
my config:
loader: ExternalSvgSprite.loader,
options: {
name: 'img/sprite.[hash:8].svg',
}
what I would like to see in my manifest.json file:
{
"img/sprite.svg": "img/sprite.8ef417c3.svg",
}
what I get with webpack-manifest-plugin, left part should not have the hash part. :
{
"img/sprite.8ef417c3.svg": "img/sprite.8ef417c3.svg",
}
what I get with webpack-assets-manifest, left part should be img/sprite.svg :
{
"sprite.svg": "img/sprite.8ef417c3.svg",
}
I'm not able to know if it's really a problem with external-svg-sprite-loader, but as the results are not consistent I ask here.
.foo {
background: url("data:image/svg+xml,module.exports = %7B symbol: './sprite.260eb415c771c8a967d00f1e5992e300.bundle.svg%23icon-logo-c2a81', view: './sprite.260eb415c771c8a967d00f1e5992e300.bundle.svg%23view-icon-logo-c2a81', viewBox: '0 0 111.9 57.29', toString: function () %7B return this.view; %7D %7D;");
}
My svg sprite is getting generated, but when I require svgs (in both css and js), I get back a string (see above). Any idea why?
I get the following error:
TypeError: Right-hand side of 'instanceof' is not an object
at chunk.modules.forEach (node_modules\external-svg-sprite-loader\lib\SvgStorePlugin.js:118)
I the extract-text-webpack-plugin
must have change because it does not appear to export ExtractedModule
any longer.
Adding an additional statement like this, at the top of the file, would solve this issue.
if (!ExtractedModule) {
try {
ExtractedModule = require('extract-text-webpack-plugin/dist/lib/ExtractedModule').default;
}
catch (e) {
ExtractedModule = null;
}
}
It doesn't work with webpack 5 cache=filesystem. It works on first run, but after webpack restarted it doesn't work. (just serves index.html instead of sprite.svg)
Hi everyone,
i have a problem with duplicated ids inside the icon sprite. So, for example in the icon sprite there is following symbol:
<symbol id="arrow-down" viewBox="0 0 42 24"><path d="M0 3.1L2 .9 21.1 19 40 .9l2 2.2-20.9 20L0 3.1z"/>
Scrolling down the icon sprite, there is a <use>
-Tag with the same id:
<use id="icon-arrow-down" xlink:href="#icon-arrow-down" width="35" height="20" x="10" y="10"></use>
.
Having duplicated ids is invalid html and therefore validators will complain...
Is it possible to create an icon sprite without the <use>
-Tags, means just an icon sprite with symbols?
Or to remove the id
attribute from the <use>
-Tags?
Looking forward to some help! Thanks!
When using this loader / plugin with webpack 5 we get the following warning:
[DEP_WEBPACK_CHUNK_MODULES_ITERABLE] DeprecationWarning: Chunk.modulesIterable: Use new ChunkGraph API
The build passes but this should be fixed in order to use this loader / plugin with future webpack versions.
sometime get 404 error, then rebuid is ok
Is there a way to exclude the view tags from being built? We're not really using it and would like to save the space if possible. Thanks
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.