Reputation: 91
I have created a Vuejs project using @vue/cli version 3.0.0-beta.16 and in my Home.vue single file component I want to import and add inline SVG in the template but I am having trouble doing so.
The problem is vue cli is already using .svg file extension for file-loader like so:
webpackConfig.module
.rule('svg')
.test(/\.(svg)(\?.*)?$/)
.use('file-loader')
.loader('file-loader')
.options({
name: getAssetPath(options, `img/[name].[hash:8].[ext]`)
})
I have already tried using the html-loader plugin for including svg in the template and it works fine if I clear the svg default use in my vue.config.js and add my own loader like this:
// vue.config.js
chainWebpack: config => {
const svgRule = config.module.rule('svg')
// clear all existing loaders.
// if you don't do this, the loader below will be appended to
// existing loaders of the rule.
svgRule.uses.clear()
// add replacement loader(s)
svgRule
.test(/\.(svg)$/)
.use('html-loader')
.loader('html-loader')
.options({
})
}
and in my template:
// Home.vue
<div v-html="require('./../assets/inline.svg')"></div>
But the problem is it also replaces svg src in the <img />
tags with inline svg code. What I want is use file-loader for <img src="something.svg" />
and use html-loader for require('./inline.svg')
. How do I use multiple loaders for same rule in webpack? Or is it the right approach? Any help would be appreciated.
Edit I think the problem is I'm adding the both loaders the wrong way. This is how I add them in my file:
// vue.config.js
svgRule
.test(/\.(svg)$/)
.use('file-loader')
.loader('file-loader')
.options({
name: getAssetPath(options, `img/[name].[ext]`)
})
svgRule
.test(/\.(svg)$/)
.use('html-loader')
.loader('html-loader')
.options({
attrs: ['div:v-html']
})
Upvotes: 9
Views: 18683
Reputation: 4868
If you don't have html-loader
installed simply execute
yarn add -D html-loader
Then add the following object to the rules
array in your webpack config file:
{
test: /\.svg$/,
use: [{ loader: 'html-loader' }]
}
And finally, you will be able to import svg
files to your scripts with the inline loader.
require('!html-loader!./../assets/inline.svg')
// or directly in your v-html directive
<div v-html="require('!html-loader!./../assets/inline.svg')"></div>
Upvotes: 5
Reputation: 10806
You can add a leading !
in the require expression to "override" existing loaders set up by the webpack config.
<div v-html="require('!html-loader!./../assets/inline.svg')"></div>
This will work without changes to the vue.config.js
(as long as html-loader is installed)
Also, instead of using html-loader look into svg-inline-loader in can add hashes to classes and ids, so you don't need to worry about name collisions if you have multiple inline svgs on your page.
Upvotes: 6
Reputation: 166
You may want to use both webpack loaders, but also to tell your html loader to restrict to div
elements with v-html
with the following syntax in the loader options:
{
attrs: ['div:v-html']
}
Docs for the html loader are found there.
Upvotes: 0
Reputation: 3584
You're almost there, just tell Webpack which loader to use:
<div v-html="require('html-loader!./../assets/inline.svg')"/>
Upvotes: 1