damianstasik / vue-svg-loader

🔨 webpack loader that lets you use SVG files as Vue components
https://vue-svg-loader.js.org
MIT License
645 stars 86 forks source link

Loading svg in css files #141

Open jan-thoma opened 3 years ago

jan-thoma commented 3 years ago

This is my webpack config for my Vue3 project:

const svgRule = config.module.rule('svg')

        svgRule.uses.clear()

        svgRule
            .use('vue-loader')
            .loader('vue-loader-v16')
            .end()

            .oneOf('inline')
            .resourceQuery(/inline/)
            .use('vue-svg-loader')
            .loader('vue-svg-loader')
            .options({
                svgo: false
            })
            .end()
            .end()

            .oneOf('external')
            .use('file-loader')
            .loader('file-loader')
            .options({
                name: 'assets/[name].[hash:8].[ext]'
            })

        config.module
            .rule('graphql')
            .test(/\.gql$/)
            .use('webpack-graphql-loader')
            .loader('webpack-graphql-loader')
            .options({ removeUnusedFragments: true })
            .end()
    }

When i try to use a svg as background image in my css files like this:

.appWrapper {
    background-image: url('~@/asset/bg.svg');
}

The image in compiled stylesheet in the inspector looks like this:

.appWrapper {
    background-image: url('[Object,Object]');
}

Is this a bug or is my config wrong?

rickson-simoes commented 3 years ago

Check the 'Vue Cli' tab. May help you, just the way it helped me. 😉

How to use both inline and external svgs

jan-thoma commented 3 years ago

This example doesn't work with Vue3. It looks like the file-loader in my config returns an object instead of a path which looks like this:

{ __file: '/path/to/file' }

This is maybe more related to webpack instead this plugin.

serializedowen commented 3 years ago

Any follow ups? I'm experiencing same issue here.

zefman commented 3 years ago

Yeah same problem here with Vue3

andreasvirkus commented 3 years ago

Same problem with Vue2 as well.

Seems related to https://github.com/visualfanatic/vue-svg-loader/issues/64 and the updated docs: https://vue-svg-loader.js.org/faq.html#how-to-use-both-inline-and-external-svgs

Edit: This might be better, but i currently got neither solutions to work. Will update when I manage to https://github.com/visualfanatic/vue-svg-loader/issues/62#issuecomment-456782895

oscars17 commented 3 years ago

Any updates? Have the same problem, cant find a proper solution

drewbaker commented 3 years ago

I'm also very confused with how we are supposed to use SVG's in CSS with this?

varave commented 3 years ago

It works for me with the config from the docs (vue cli tab): https://vue-svg-loader.js.org/faq.html#how-to-use-both-inline-and-external-svgs

"vue-svg-loader": "^0.16.0"

chrisb-c01 commented 3 years ago

Using vue-cli 3 config, it is working for me using the config from the docs as mentioned by @varave, however replacing babel-loader by vue-loader (I took that from the dev branch).

Config in vue.config.js:

module.exports = {
  chainWebpack: config => {
    const svgRule = config.module.rule('svg');

    svgRule.uses.clear();

    svgRule
      .oneOf('inline')
      .resourceQuery(/inline/)
      .use('vue-loader')
      .loader('vue-loader')
      .end()
      .use('vue-svg-loader')
      .loader('vue-svg-loader')
      .end()
      .end()
      .oneOf('external')
      .use('file-loader')
      .loader('file-loader')
      .options({
        name: 'assets/[name].[hash:8].[ext]',
      });
  }
};
n4ks commented 3 years ago

If someone encountered a similar problem with Nuxt, then I was able to fix it by changing: this url('~/static/images/fileName.svg) to this url('/images/fileName.svg)

Anatolie commented 3 years ago

For anyone using Vue2, here is how I got it working with Webpack 5:

"vue": "^2.6.14"
"vue-svg-loader": "^0.17.0-beta.2"
"webpack": "^5.41.0"

My rule in webpack.common.js:

{
  test: /\.svg$/,
  oneOf: [
    // SVGs within .scss files: add ?inline to the end to load them: url('example.svg?inline')
    {
      resourceQuery: /inline/,
      type: 'asset/resource',
    },
    {
      use: [
        'vue-loader',
        {
          loader: 'vue-svg-loader',
          options: {
            svgo: {
              plugins: [{ removeDimensions: true }]
            }
          }
        }
      ],
    },
  ],
},

I opted to have the ?inline rule on any non-imported components.

In my SCSS (or CSS) files, I can use SVG backgrounds like so: background-image: url('../images/breadcrumb-chevron.svg?inline'); <-- note the ?inline will have to be added to any SVG URLs in CSS.

And I can still import SVGs as components like normal: import Logo from "../assets/images/logo-black.svg"; in my .vue files!

Webpack 5 discontinued use of file-loader, once I finally figured this out and replaced it with asset/resource, worked like a charm. Hope this helps save someone some time!

cc @andreasvirkus