egoist / svg-to-vue-component

Transform SVG files into Vue SFC (with hot reloading and SVGO support)
MIT License
235 stars 18 forks source link

SVG as background-url in SFC <style> tag #29

Open rbutera opened 5 years ago

rbutera commented 5 years ago

Context

Having the same issue, but instead of using the svgs in a .css file, I'm using them in the style tag of .vue files. Any work around that'll let me keep them in there?

Originally posted by @shmarts in https://github.com/egoist/svg-to-vue-component/issues/18#issuecomment-503520585

Explanation

This issue was closed due to hotfix pr (#50), however this specific case is still a problem.

If you have svg-to-vue-component installed then you are unable to use svgs within the <style> section of a Vue single file component.

I guess a workaround in the meantime is to just import a css/sass file with the background-image.

rbutera commented 5 years ago

Perhaps it might be an option to require a prefix for SVGs imported from a .vue file in order to

for example:

// as part of .vue file
// <script>
import Foo from 'svg@/path/to/svg.svg'; 
// </script>
// as part of .vue file
// <style>
.has-background-foo {
    background-image: url( '/path/to/svg.svg'; ) // WOULD NOT BE TOUCHED BY SVG-TO-VUE-COMPONENT
}
// </style>

I had this idea because I eventually had to remove svg-to-vue-component from my projects because we use SVGs a lot in our CSS.

franciscolourenco commented 5 years ago

@Raigasm have you tried the inline notation as a workaround? https://webpack.js.org/concepts/loaders/#inline

rbutera commented 5 years ago

@franciscolourenco

No, could you provide me a quick example of how to use this in the style tag?

franciscolourenco commented 5 years ago

This should reset any other loaders and use the file-loader without any options

background-image: url( '!file-loader!/path/to/svg.svg'; )

That being said, this is a workaround to proper configuration of the loaders.

franciscolourenco commented 5 years ago

In theory this should also work, if you remove all the configurations to webpack import ErrorIcon from '!vue-loader!svg-to-vue-component/loader!shared/icons/error.svg'

However I'm getting the following error:

 error  in ../shared/icons/error.svg?vue&type=template&id=31d24295&

Module Error (from ../node_modules/vue-loader/lib/loaders/templateLoader.js):
(Emitted value instead of an instance of Error)

  Errors compiling template:

  Component template requires a root element, rather than just text.

  1  |  module.exports = __webpack_public_path__ + "img/error.c2c6d34a.svg";
     |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

 @ ../shared/icons/error.svg?vue&type=template&id=31d24295& 1:0-315 1:0-315
 @ ../node_modules/vue-loader/lib!../node_modules/svg-to-vue-component/loader.js!../shared/icons/error.svg
 @ ../node_modules/cache-loader/dist/cjs.js??ref--14-0!../node_modules/babel-loader/lib!../node_modules/cache-loader/dist/cjs.js??ref--0-0!../node_modules/vue-loader/lib??vue-loader-options!../shared/baseComponents/BaseIcon.vue?vue&type=script&lang=js&
 @ ../shared/baseComponents/BaseIcon.vue?vue&type=script&lang=js&
 @ ../shared/baseComponents/BaseIcon.vue
 @ ../shared/baseComponents sync nonrecursive Base[\w-]+\.vue$
 @ ../shared/baseComponents/index.js
 @ ./src/main.js
 @ multi ../node_modules/webpack-dev-server/client?http://192.168.2.100:8080/sockjs-node ../node_modules/webpack/hot/dev-server.js ./src/main.js

Any idea why @egoist

franciscolourenco commented 5 years ago

@Raigasm you could also do it this way: https://vue-svg-loader.js.org/faq.html#how-to-use-both-inline-and-external-svgs

m8schmit commented 5 years ago

Like @franciscolourenco said you juste have to put

  chainWebpack(config) {
    const FILE_RE = /\.(vue|js|ts|svg)$/

    config.module.rule('svg').issuer(file => !FILE_RE.test(file)).oneOf('svg')

    config.module
      .rule('svg-component')
      .test(/\.svg$/)
      .issuer(file => FILE_RE.test(file))
      .oneOf('ignore')
      .resourceQuery(/\?ignore/)
      .use('file-loader')
      .loader('file-loader')
      .end()
      .end()
      .oneOf('normal')
      .use('vue')
      .loader('vue-loader')
      .end()
      .use('svg-to-vue-component')
      .loader('svg-to-vue-component/loader')

  }

And your css gonna look like

background-image: url("~@/assets/my-svg.svg?ignore");
mrleblanc101 commented 3 years ago

I think this plugin should only parse svg in the <script> tag. Using something like 'source.vue?vue&type=script' it should be possible, no ? This would remove the need for ?inline when using background image inside a <style> tag