Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inline SVG in vuejs component

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']
})
like image 892
Atta ur Rehman Avatar asked Jun 13 '18 10:06

Atta ur Rehman


2 Answers

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.

like image 70
Igonato Avatar answered Sep 29 '22 15:09

Igonato


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>
like image 37
Orlandster Avatar answered Sep 29 '22 16:09

Orlandster