- Notifications
You must be signed in to change notification settings - Fork24
Embed svg inline when using the html webpack plugin
License
theGC/html-webpack-inline-svg-plugin
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Converts SVG files referenced by<img>
elements into inlined<svg>
elements within the output HTML of templates used byhtml-webpack-plugin.
html-webpack-inline-svg-plugin
does not support yet webpack v5.
When SVGs files are inlined into HTML the embedded SVGs can be customised with CSS and thefill
rule, and they can also be combined in sprites. Check the css-tricks.com articleIcon System with SVG Sprites for an extended explanation.
html-webpack-inline-svg-plugin
implements the below features:
- Optimises and minimizes the inlined SVG withSVGO.
- Supportswebpack aliases for file paths (only when loaders are used).
- Supports the
webpack-dev-server
. - Can load image files locally andfrom an online URL with the
allowFromUrl
config option. - Allows fordeep nested SVGs.
- Ignores broken tags (in case you are outputting templates for various parts of the page).
- Performs no-HTML decoding (supports language tags, i.e.
<?php echo 'foo bar'; ?>
).
Add and install thehtml-webpack-inline-svg-plugin
dependency topackage.json
. At this point you should already have installed in your project other required dependencies likewebpack andhtml-webpack-plugin:
npm i -D html-webpack-inline-svg-plugin
or withYarn:
yarn add -D html-webpack-inline-svg-plugin
Given the below reference folder structure:
my-project├─ package.json├─ webpack.config.js├─ node_modules├─ src│ ├─ entry.html│ └─ imagesSource│ ├─ icon1.svg│ └─ image1.png├─ assets│ └─ bar.svg└─ output ├─ index.html └─ imagesOutput ├─ icon2.svg └─ image2.png
On your webpack config file add:
// webpack.config.jsconstHtmlWebpackInlineSVGPlugin=require('html-webpack-inline-svg-plugin');// ...plugins:[newHtmlWebpackPlugin(),newHtmlWebpackInlineSVGPlugin({/* ... */}// ...Object with config options, if any. Pass nothing otherwise (not even empty object))]
Then, add<img>
elements with theinline
attribute to the templates that html-webpack-plugin will be processing. CheckPaths to SVG files to know what is the correct path to SVG files in<img>
elements.
<!-- ✅ Inlined: SVG file relative to OUTPUT --><imginlinesrc="imagesOutput/icon2.svg"><!-- ✅ Inlined: SVG file relative to SOURCE. webpack alias used. Loaders are required --><imginlinesrc="~a/bar.svg"><!-- ✅ Inlined: online URL. 'allowFromUrl' config option must be set to true --><imginlinesrc="https://someserver.com/images/icon.svg"><!-- ⭕ Ignored: the <img> element does not have the 'inline' attribute --><imgsrc="imagesOutput/icon2.svg"><!-- ✅ Inlined: the 'inlineAll' config option has been set to true --><imgsrc="imagesOutput/icon2.svg"><!-- ⭕ Ignored: it is not a SVG image --><imginlinesrc="imagesOutput/image2.png">
There are three ways of referencing SVG files from<img>
elements in your templates:
Ifloaders for the entry template are not used SVG file paths must be relative to the HTML template that is referencing the SVG files within the webpackoutput folder:
<!-- src/entry.html --><imginlinesrc="imagesOutput/icon2.svg"><imginlinesrc="../src/imagesSource/icon1.svg"><imginlinesrc="../assets/bar.svg"><imginlinesrc="~a/bar.svg"><!-- Will give an error because aliases are not supported without loaders -->
You have to make sure SVG files have been moved to the output directory by some mean.
In this way SVG files are inlined after all template and image files have been written to theoutput directory, that is it, on html-webpack-plugin'safterEmit
event.
Ifloaders for the entry template are still not used, therunPreEmit
config option can be used. Then, SVG file paths must be relative to theproject root (wherepackage.json
is):
<!-- src/entry.html --><imginlinesrc="src/imagesSource/icon1.svg"><imginlinesrc="output/imagesOutput/icon2.svg"><imginlinesrc="assets/bar.svg"><imginlinesrc="~a/bar.svg"><!-- Will give an error because aliases are not supported without loaders -->
In this way the plugin run prior to the output of templates, that is it, on html-webpack-plugin'sbeforeEmit
event. This allows to reference image files from the project root which can help with getting to certain files, like for example within thenode_modules
directory.
Ifloaders are used SVG file paths in<img>
elements must be relative to thesource entry template (thetemplate
config option in html-webpack-plugin).
The usual loader's combo is thehtml-loader
with thefile-loader
(html-webpack-inline-svg-plugin
does not support yet webpack v5asset modules). By default html-webpack-plugin uses anejs
loader if no loader is provided for the entry template. This default loader does not handle file imports. That is why we need thehtml-loader
to parse the entry HTML template, loader that will fire an import event every time it parses a JavaScript, CSS or image import. Then, thefile-loader
will handle SVG image imports,webpack aliases, and finally copy the SVG files to theoutput
folder.
Although SVG file paths are relative to the source template the files still need to be copied/emitted to the output folder (which will be done automatically by thefile-loader
):
// webpack.config.jsconstpath=require('path')resolve:{alias:{a:path.join(__dirname,'assets')// With paths relative to SOURCE aliases can be used}},module:{rules:[{test:/\.svg$/,loader:'file-loader',options:{name:'itCanBeWhatever/[name].[ext]'// It does not have to follow same path or file name than files in 'src'},},{test:/\.html$/,loader:'html-loader'}]},
<!-- src/entry.html --><imginlinesrc="imagesSource/icon1.svg"><imginlinesrc="../output/imagesOutput/icon2.svg"><imginlinesrc="../assets/bar.svg"><imginlinesrc="~a/bar.svg">
If for any reason the path to a local SVG file is incorrect, or the file fails to be read, or an image retrieved with an URL fails to download, the webpack build process will fail with anENOENT
error.
All the attributes of a<img/>
element exceptingsrc
andinline
will be copied to the inlined<svg/>
element. Attributes likeid
orclass
will be copied to the resulting root of the<svg/>
element and if the original SVG file already had these attributes they will be duplicated (and not replaced) on the resulting<svg/>
element, though the attributes coming from the<img/>
will appear first andany subsequent duplicated attribute from the original SVG will be ignored by the browser.
For example:
<!-- src/entry.html --><imginlinesrc="imagesSource/icon1.svg"id="myImageIMG"class="square">
<!-- src/imagesSource/icon1.svg --><svgid="myImageSVG">...</svg>
will result in:
<!-- output/index.html --><svgid="myImageIMG"class="square"id="myImageSVG">...</svg>
The broswer will useid="myImageIMG"
and notid="myImageSVG"
. It's however a better approach if you avoid having any duplicated attribute at all and only putting the required ones on the<img>
element.
Paths relative to SOURCE is the simpler method forwebpack-dev-server
to work withhtml-webpack-inline-svg-plugin
because source files, files that are not in the output folder, are the ones referenced. Still, thefile-loader
'semitFile
option cannot ever befalse
.
Paths relative to OUTPUT orPaths relative to ROOT can also be used forwebpack-dev-server
as long as they point to SVG files that already exist without the need of a webpack run, that is it, files that are outside the output folder. However using long relative paths to point to such files –since aliases are only available with paths relative to SOURCE– could be a bit tedious.
Checkthis issue in case you do not get thewebpack-dev-server
working.
The plugin accepts the below options:
Defaults tofalse
.
Ifloaders are not used to resolve file locations, and you would prefer to reference SVG file paths relative to the projectroot (wherepackage.json
is) then setrunPreEmit
config option totrue
:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackInlineSVGPlugin({runPreEmit:true,})]
The plugin will now run prior to html-webpack-plugin saving templates to the output directory. Therefore, inlining SVG files would look like:
<!-- src/entry.html --><imginlinesrc="src/imagesSource/icon1.svg">
Defaults tofalse
.
It will inline all SVG images on the template without the need of theinline
attribute on every image:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackInlineSVGPlugin({inlineAll:true})]
IfinlineAll
option is enabled you can use theinline-exclude
attribute to exclude a particular image from being inlined:
<!-- src/entry.html --><div><imgsrc="src/images/icon1.svg"><!-- it will be inlined --><imginline-excludesrc="src/images/icon2.svg"><!-- it won't be inlined --></div>
Defaults tofalse
.
It allows to use SVG images coming from an URL in addition to local files:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackInlineSVGPlugin({allowFromUrl:true})]
For example:
<!-- src/entry.html --><div><imginlinesrc="https://badge.fury.io/js/html-webpack-inline-svg-plugin.svg"><!-- it will be inlined from the online SVG --></div>
Defaults to[]
.
SVGO is used to optimise the SVGs inlined. You can configure SVGO by setting thissvgoConfig
array with theSVGO plugins you need in the same way it's done in thisSVGO official Node.js example.
NotesvgoConfig
is an array ofObject
s that will be assigned to the.plugins
SVGO config variable byhtml-webpack-inline-svg-plugin
. You don't need to pass anObject
with aplugins
property assigned an array of SVGO plugins, just pass the array:
plugins:[newHtmlWebpackPlugin(),newHtmlWebpackInlineSVGPlugin({svgoConfig:[{removeViewBox:false},{inlineStyles:{onlyMatchedOnce:false}}]})]
html-webpack-inline-svg-plugin
modifies one SVGO default:cleanupIDs
, fromtrue
tofalse
, since IDs allow to reference individual symbols. You can still override this or any other SVGO plugin default configuration with thissvgoConfig
option.
The latest version of this package supports webpack 4. All versions marked v2.x.x will target webpack 4 and html-webpack-plugin v4.
For webpack 3 and html-webpack-plugin v3 support use v1.3.0 of this package.
- Support webpack v4.
- Support html-webpack-plugin v4.
- Support webpack v3.
- Support html-webpack-plugin v3.
You're free to contribute to this project by submitting issues and/or pull requests. This project is test-driven, so keep in mind that every change and new feature must be covered by tests.
I'm happy for someone to take over the project as I don't find myself using it any longer due to changes in workflow. Therefore others are likely to be in a better position to support this project and roll out the right enhancements.
About
Embed svg inline when using the html webpack plugin
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors3
Uh oh!
There was an error while loading.Please reload this page.