vue-svg-icon-set
offers the tools necessary to create an optimized SVG icon set for Vue
🙋 Why?
- ⚡️ Optimized SVG usage Prevent SVGs from being inlined multiple times from your icon-set
- 🔥 Webpack integration Seamlessly integrate with your Webpack build
- 🦋 Light
1.27 kB
minzipped for the IconLayer and743 B
for IconRegister
🚀 Install
npm i -D vue-svg-icon-set
🚦 Quick setup
-
Update Webpack config
Add the following changes to your Webpack configuration so that
vue-svg-icon-set
can transform your SVGs and so that you can output an IconLayer.module.exports = {...,entry: {+ 'lib/icon-layer': 'vue-svg-icon-set/icon-layer.vue',...iconPaths,},module: {rules: [...,+ {+ test: /\.svg$/,+ use: [+ 'vue-loader',+ 'vue-svg-icon-set/loader',+ ],+ },],}}; -
Use IconLayer
Add the outputted
icon-layer
file to your application as a top-level wrapper.<template>+ <icon-layer><app />+ </icon-layer></template><script>+ import IconLayer from 'icon-library/lib/icon-layer';export default {components: {+ IconLayer}}</script> -
Use Icons
That's it! You should be ready to start using the icons from your library. 👍
<template><thumbsup-icon style="fill:orange" /></template><script>import ThumbsupIcon from 'icon-library/icons/thumbsup-icon';export default {components: {ThumbsupIcon}};</script>
⚙️ Options
-
svgComponentPath
<String>
The path to a custom component to use as the root of the icon component. This custom component should return a<svg>
root element and can be used to add advanced behavior to the icon. For example, this custom component makes all icons appear clickable:<template><svgclass="icon"v-on="$listeners"v-bind="$attrs"><slot /></svg></template><style scoped>.icon {cursor: pointer;}</style> -
generateId(resourcePath)
<Function>
Method to generate each icon id. By default, it uses the kebab-case of thebasename
of the file path. You can access this method viathis.kebabBaseName()
in thegenerateId
function.Since SVGs use
id
s for referencing, this method can be used to namespace the ids to minimize the possibility of collision.{test: /\.svg$/,use: ['vue-loader',- 'vue-svg-icon-set/loader',+ {+ loader: 'vue-svg-icon-set/loader',+ options: {+ generateId(resourcePath) {+ const id = this.kebabBaseName(resourcePath);+ return `namespace-${id}`;+ }+ }+ }],}
🏎 Optimizations
Externalizing icon register
The icon-register.js
component is used by every icon and can be abstracted out to reduce the size of each icon.
module.exports = { ..., entry: { 'lib/icon-layer': 'vue-svg-icon-set/icon-layer.vue',+ 'lib/icon-register': 'vue-svg-icon-set/icon-register', ...iconPaths, }, + externals: [+ (from, req, cb) => {+ if (req.endsWith('icon-register.js')) {+ return cb(null, '../lib/icon-register.js');+ }+ cb();+ },+ ], };
SVGO
I recommend using SVGO to optimize your SVGs. Use svgo-loader to pipe optimized SVGs to vue-svg-icon-set
.
{ test: /\.svg$/, use: [ 'vue-loader', 'vue-svg-icon-set/loader',+ 'svgo-loader', ],}
💁♂️ FAQ
How is this optimized?
SVGs can be referenced and reused like variables with the <use>
element. This icon-set leverages this feature to define referencable SVGs so that repeated usage of an icon isn't duplicated in the DOM.
Demo on JSFiddle
<!-- Defined SVGs aka IconLayer --> <!-- Use "plus" icon --> <!-- Use "circle" icon -->
What's the IconLayer for?
The IconLayer is a component that declares the SVG definitions so they're referenceable across the document. It injects an API so that all icons can communicate with it and register an icon to be defined.
Does this work with SSR?
Yes! However, the SVG will not be inlined in the server-rendered document. It's actually a technical limitation because each icon usages hoists up the SVG rendering to happen in the parent IconLayer, and SSR only renders once. This could work to an advantage as it keeps the server-rendered doc from including SVGs that may be large or repeated. Here's a working demo.
Is it possible to opt-out of the optimization and inline the SVG?
Yes! Pass in the inline
boolean prop on the icon component and it will render the SVG inline.
When rendering a lot of icons, it could be noticeably faster to render the icons inline. Try it when you see a performance bottleneck in icon rendering.
👪 Related
- vue-feather-icon-set - Optimized Feather icon set for Vue using SVG references