-
-
Save Excalibaard/5ec706565788ed9c118e08794b28149c to your computer and use it in GitHub Desktop.
const { optimize, loadConfig } = require('svgo'); | |
const { getOptions } = require('loader-utils'); | |
async function loader(svg) { | |
const { configFile, ...options } = getOptions(this) || {}; | |
let config; | |
if (typeof configFile === 'string') { | |
config = await loadConfig(configFile, this.context); | |
} else if (configFile !== false) { | |
config = await loadConfig(null, this.context); | |
} | |
const result = optimize(svg, { | |
path: this.resourcePath, | |
...config, | |
...options, | |
}); | |
if (result.error) throw Error(result.error); | |
return `<template>${result.data}</template>`; | |
} | |
module.exports = function(svg) { | |
const callback = this.async(); | |
loader | |
.call(this, svg) | |
.then(result => callback(null, result)) | |
.catch(error => callback(error)); | |
}; |
@dschrul Not yet, I used this in enterprise code for a company I don't work at anymore. I'll see when I have the time to make a sample project. but won't make any promises.
I made this gist before I realized it could be a lot simpler though. This gist replaces the entire vue-svg-loader
functionality, which is two steps:
- Optimizing your SVG with SVGO
- Wrapping it in
<template>
tags (sovue-loader
in the next step will interpret the input as a Vue component)
But, Webpack loaders are made to be chained. Instead of this gist, I suggest you use two loaders, one for each process.
The first step can use svgo-loader which is actively maintained by the svgo team. The second step is one line of code (see line 22 of this gist), which is too small to have as a dependency IMO (remember leftpad). Instead, you can add your own loader. I described the process of adding your own loader in this post below.
damianstasik/vue-svg-loader#156 (comment)
Here's an example of what it could look like in your project (modified from the comment above). It avoids resolveLoader
, though I only recommend this if you're not expecting to use more custom loaders.
// /webpack.config.js
const path = require('path');
module.exports = {
// ...,
module: {
rules: [
{
test: /\.svg$/,
resourceQuery: /inline/, // forces explicitly importing SVG as 'inline', so normal behavior is an image file as expected.
use: [
{
loader: 'vue-loader'
},
{
loader: path.resolve('utils/vue-template-wrap-loader.js')
},
{
loader: 'svgo-loader',
options: {
// configFile: false // uncomment if not using a svgo.config.js file in your project root
.... // add svgo options for inlined SVG here
}
}
]
},
{
test: /\.svg$/,
use: [
{
loader: 'file-loader'
},
{
loader: 'svgo-loader',
options: {
.... // maybe some different svgo options
}
},
]
}
]
}
}
// /utils/vue-template-wrap-loader.js
module.exports = function vueTemplateWrapLoader(svg) {
return `<template>${svg}</template>`;
};
Then import SVGs like:
import SVGIcon1 from 'Icon.svg?inline' // SVG as Vue component
import SVGIcon2 from 'Icon.svg' // SVG as image
thanks a lot @Excalibaard
Hi, do you have a complete sample project using this? I'm struggling to understand and need to replace vue-svg-loader. Thanks a lot