Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App can't render SVGs after the latest VueCLI upgrade #7084

Open
techwizzdom opened this issue Mar 30, 2022 · 14 comments
Open

App can't render SVGs after the latest VueCLI upgrade #7084

techwizzdom opened this issue Mar 30, 2022 · 14 comments

Comments

@techwizzdom
Copy link

Version

5.0.4

Reproduction link

github.com

Environment info

➜  broken-svgs git:(main) vue info

Environment Info:

  System:
    OS: macOS 12.2.1
    CPU: (8) x64 Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
  Binaries:
    Node: 17.8.0 - ~/.nvm/versions/node/v17.8.0/bin/node
    Yarn: 1.22.18 - /usr/local/bin/yarn
    npm: 8.5.5 - ~/.nvm/versions/node/v17.8.0/bin/npm
  Browsers:
    Chrome: 99.0.4844.84
    Edge: Not Found
    Firefox: 95.0
    Safari: 15.3
  npmPackages:
    @vue/babel-helper-vue-jsx-merge-props:  1.2.1
    @vue/babel-helper-vue-transform-on:  1.0.2
    @vue/babel-plugin-jsx:  1.1.1
    @vue/babel-plugin-transform-vue-jsx:  1.2.1
    @vue/babel-preset-app:  5.0.4
    @vue/babel-preset-jsx:  1.2.4
    @vue/babel-sugar-composition-api-inject-h:  1.2.1
    @vue/babel-sugar-composition-api-render-instance:  1.2.4
    @vue/babel-sugar-functional-vue:  1.2.2
    @vue/babel-sugar-inject-h:  1.2.2
    @vue/babel-sugar-v-model:  1.2.3
    @vue/babel-sugar-v-on:  1.2.3
    @vue/cli-overlay:  5.0.4
    @vue/cli-plugin-babel: ~5.0.0 => 5.0.4
    @vue/cli-plugin-eslint: ~5.0.0 => 5.0.4
    @vue/cli-plugin-router:  5.0.4
    @vue/cli-plugin-vuex:  5.0.4
    @vue/cli-service: ~5.0.0 => 5.0.4
    @vue/cli-shared-utils:  5.0.4
    @vue/component-compiler-utils:  3.3.0
    @vue/web-component-wrapper:  1.3.0
    eslint-plugin-vue: ^8.0.3 => 8.5.0
    svg-to-vue:  0.7.0
    vue: ^2.6.14 => 2.6.14
    vue-eslint-parser:  8.3.0
    vue-hot-reload-api:  2.3.4
    vue-loader:  17.0.0 (15.9.8)
    vue-style-loader:  4.1.3
    vue-svg-loader: ^0.16.0 => 0.16.0
    vue-template-compiler: ^2.6.14 => 2.6.14
    vue-template-es2015-compiler:  1.9.1
  npmGlobalPackages:
    @vue/cli: 5.0.4

Steps to reproduce

  1. Create a Vue 2 project
  2. Install vue-svg-loader, vue-template-compiler, file-loader
  3. Update webpack config like https://github.com/orbitalwitness/broken-svgs/blob/main/vue.config.js
  4. Start the app (npm-run-serve)
  5. Import icon as a component (inline) import IconWord from './assets/icon-word.svg?inline'
  6. Try to render it as an image src (external) <img src="./assets/icon-word.svg" />

What is expected?

Icons should be rendered.

What is actually happening?

None of the icons is rendered.

Screenshot 2022-03-30 at 13 04 27


I suspect this is connected to Asset Modules in Webpack (https://webpack.js.org/guides/asset-modules/).

Currently, we have both inline and external SVGs in our project but it doesn't seem to work after the Vue CLI upgrade.

@kubajmarek
Copy link

Try this solution.

@dagadbm
Copy link

dagadbm commented Apr 19, 2022

@dromba did you manage to get it working?

I have a very hybrid solution that needs to support html-loader because of an external package I have been trying some solutions on and off what was suggested here but getting this to work has been tricky:

<img src="@/assets/svgs/logo.svg"/>

Can you share your config?

@techwizzdom
Copy link
Author

@Irevall @dagadbm I still haven't managed to make it work.

My current config is this:

@vue/cli v5.0.4
npm v8.5.5
node v17.8.0

vue.config.js:

chainWebpack: (config) => {
        const svgRule = config.module.rule('svg');
        console.log(svgRule)
        console.log('\n\n\n\n\n')
        svgRule.uses.clear();
        svgRule.delete('type');
        svgRule.delete('generator');
        svgRule
            .use('vue-loader')
            .loader('vue-loader')
            .end()
            .use('vue-svg-loader')
            .loader('vue-svg-loader');
    },

Have you managed to solve something?

When I try to import an SVG and use it as a component, it doesn't work.

@connorshea
Copy link

I've got the exact same problem, stuck on beta6 because of it 😅 I'm using html-loader since I never managed to get vue-svg-loader working in the past.

@dagadbm
Copy link

dagadbm commented May 12, 2022

const { defineConfig } = require('@vue/cli-service');
module.exports` = defineConfig({
	transpileDependencies: true,
	chainWebpack: (config) => {
		// SVG loader
		const svgRule = config.module.rule('svg');
		svgRule.uses.clear();

		// https://github.com/vuejs/vue-cli/issues/6785
		svgRule.delete('type');
		svgRule.delete('generator');

		svgRule
			// load svgs as data-urls on scss using url('/path/to/svg?dataurl')
			.oneOf('dataurl')
			.resourceQuery(/dataurl/)
			.use('svg-url-loader')
			.loader('svg-url-loader')
			.end()
			.end()
			// load svgs as vue components when importing svg files
			.oneOf('vue-component')
			.test(/.*\.svg/)
			.use('vue-svg-loader')
			.loader('vue-svg-loader')
			.end()
			.end();
	},
});

I have something similar to this. I deleted an extra set of rules I had because of an external library at work.

Let me know if it worked

@connorshea
Copy link

I converted it over to using vue-svg-loader on Vue CLI 5.0.0-beta.6, and everything works there (with just a "normal" setup from the README). Then when I upgrade Vue CLI any further and replace the SVG loading code in vue.config.js with what you suggested, it seems to error as though my SVGs are invalid 🤔

Compiled with problems:

ERROR in ./src/assets/icons/chevron-down.svg 1:0

Module parse failed: Unexpected token (1:0)
File was processed with these loaders:
 * ./node_modules/vue-svg-loader/index.js
You may need an additional loader to handle the result of these loaders.
> <template><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M207.029 381.476L12.686 187.132c-9.373-9.373-9.373-24.569 0-33.941l22.667-22.667c9.357-9.357 24.522-9.375 33.901-.04L224 284.505l154.745-154.021c9.379-9.335 24.544-9.317 33.901.04l22.667 22.667c9.373 9.373 9.373 24.569 0 33.941L240.971 381.476c-9.373 9.372-24.569 9.372-33.942 0z"/></svg></template>


ERROR in ./src/assets/icons/heart-broken.svg 1:0

Module parse failed: Unexpected token (1:0)
File was processed with these loaders:
 * ./node_modules/vue-svg-loader/index.js
You may need an additional loader to handle the result of these loaders.
> <template><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M473.7 73.8l-2.4-2.5c-46-47-118-51.7-169.6-14.8L336 159.9l-96 64 48 128-144-144 96-64-28.6-86.5C159.7 19.6 87 24 40.7 71.4l-2.4 2.4C-10.4 123.6-12.5 202.9 31 256l212.1 218.6c7.1 7.3 18.6 7.3 25.7 0L481 255.9c43.5-53 41.4-132.3-7.3-182.1z"/></svg></template>

This is my full vue.config.js with the changes to try and get it working with newer versions of Vue CLI:

module.exports = {
  lintOnSave: false,
  chainWebpack: (config) => {
    const svgRule = config.module.rule('svg');
    svgRule.uses.clear();

    // https://github.com/vuejs/vue-cli/issues/6785
    svgRule.delete('type');
    svgRule.delete('generator');

    svgRule
      // load svgs as data-urls on scss using url('/path/to/svg?dataurl')
      .oneOf('dataurl')
      .resourceQuery(/dataurl/)
      .use('svg-url-loader')
      .loader('svg-url-loader')
      .end()
      .end()
      // load svgs as vue components when importing svg files
      .oneOf('vue-component')
      .test(/.*\.svg/)
      .use('vue-svg-loader')
      .loader('vue-svg-loader')
      .end()
      .end();
  },
  // For properly setting the base path in 'production' with GitLab Pages.
  publicPath: process.env.NODE_ENV === 'production' ? '/' + process.env.CI_PROJECT_NAME + '/' : '/'
}

@connorshea
Copy link

connorshea commented May 14, 2022

Oh, if I change it to just this, it works fine:

    const svgRule = config.module.rule('svg');
    svgRule.uses.clear();

    // https://github.com/vuejs/vue-cli/issues/6785
    svgRule.delete('type');
    svgRule.delete('generator');

    svgRule
      .use('vue-loader')
      .loader('vue-loader')
      .end()
      .use('vue-svg-loader')
      .loader('vue-svg-loader');

That was simple enough...

Thank you for pointing me in the right direction :) Looks like I can upgrade Vue CLI now!

@connorshea
Copy link

connorshea commented May 14, 2022

EDIT: Fixed this immediately after posting again lol. I used the solution from this, but applied it to SVGs instead of CSS: https://stackoverflow.com/questions/46177148/how-to-exclude-css-module-files-from-jest-test-suites/46177325#46177325

I'm not sure if there are any downsides to this approach, but all my tests pass without warnings now, so 🤷‍♂️

=======

Now my only problem is that the Jest tests print warnings about all of the SVG components not being registered:

  ● Console

    console.warn
      [Vue warn]: Failed to resolve component: chevron-down-icon
      If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. 
        at <GameCard game= {
        id: 1,
        name: "Kirby's Epic Yarn",
        platforms: { nodes: [ [Object] ] },
        developers: { nodes: [ [Object] ] },
        isFavorited: true
      } ref="VTU_COMPONENT" > 
        at <VTUROOT>



      at warn (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:40:17)
      at resolveAsset (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5973:13)
      at resolveComponent (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5922:12)
      at Proxy.render (src/components/GameCard.vue:143:40)
      at renderComponentRoot (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:889:44)
      at ReactiveEffect.componentUpdateFn [as fn] (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4990:57)
      at ReactiveEffect.run (node_modules/@vue/reactivity/dist/reactivity.cjs.js:189:25)
      at setupRenderEffect (node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5116:9)

I guess I can just call them custom components? But technically they're not. Unfortunately the Jest configuration that vue-svg-loader suggests doesn't work with the most recent versions of Vue/Vue CLI/Jest :/

@dagadbm
Copy link

dagadbm commented May 14, 2022 via email

@anthonylebrun
Copy link

For anyone facing the same issue as @connorshea with jest warnings, I figured out a fix that works here: damianstasik/vue-svg-loader#38 (comment)

@ganeshkumarpolipalli-accolite
Copy link

#7448

any help? @dagadbm can you please help?

@kubajmarek
Copy link

kubajmarek commented Feb 9, 2024

#7448

any help?

vue-svg-loader is just 20 lines of unmaintained code that doesn't do a whole lot, I think the best idea is to create your own SVG loader instead.

Alternatively maybe you could use this.

@ganeshkumarpolipalli-accolite
Copy link

@kubajmarek thanks for your help.. added vue-svg-loader-2 to package json.. still did not work, same error

INFO Starting development server...
98% after emitting CopyPlugin

ERROR Failed to compile with 1 error

error in ./src/assets/icons/icons.svg?arrow-left

Syntax Error: TypeError: iconInfo.hasOwnProperty is not a function

@ ./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/Work.vue?vue&type=script&lang=js 44:0-67 443:20-29
@ ./src/views/Work.vue?vue&type=script&lang=js
@ ./src/views/Work.vue
@ ./src/router/index.js
@ ./src/main.js
@ multi (webpack)-dev-server/client?sockjs-node (webpack)/hot/dev-server.js ./src/main.js**

@kubajmarek
Copy link

@ganeshkumarpolipalli-accolite can you upload a reproduction anywhere? Something might be wrong with the icon or Work.vue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants