vuejs / vue-cli

🛠️ webpack-based tooling for Vue.js Development
https://cli.vuejs.org/
MIT License
29.75k stars 6.33k forks source link

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

Open techwizzdom opened 2 years ago

techwizzdom commented 2 years ago

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 commented 2 years ago

Try this solution.

dagadbm commented 2 years ago

@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 commented 2 years ago

@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 commented 2 years ago

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 commented 2 years ago
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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

This is the easiest one to fix:

https://github.com/visualfanatic/vue-svg-loader/issues/38&ved=2ahUKEwjPkcyZ9d_3AhWrR_EDHQtJB2oQFnoECA4QAQ&usg=AOvVaw2HdfuxTMdNzGTb5UtJKdX0

https://vue-svg-loader.js.org/faq.html#how-to-use-this-loader-with-typescript

On Sat, May 14, 2022, 20:43 Connor Shea @.***> wrote:

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 ***@***.***/runtime-core/dist/runtime-core.cjs.js:40:17)

  at resolveAsset ***@***.***/runtime-core/dist/runtime-core.cjs.js:5973:13)

  at resolveComponent ***@***.***/runtime-core/dist/runtime-core.cjs.js:5922:12)

  at Proxy.render (src/components/GameCard.vue:143:40)

  at renderComponentRoot ***@***.***/runtime-core/dist/runtime-core.cjs.js:889:44)

  at ReactiveEffect.componentUpdateFn [as fn] ***@***.***/runtime-core/dist/runtime-core.cjs.js:4990:57)

  at ReactiveEffect.run ***@***.***/reactivity/dist/reactivity.cjs.js:189:25)

  at setupRenderEffect ***@***.***/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 :/

— Reply to this email directly, view it on GitHub https://github.com/vuejs/vue-cli/issues/7084#issuecomment-1126801067, or unsubscribe https://github.com/notifications/unsubscribe-auth/AD7WGR5KOBO4ZL5ZPNGX7MLVJ764ZANCNFSM5SBWLKSA . You are receiving this because you were mentioned.Message ID: @.***>

anthonylebrun commented 2 years ago

For anyone facing the same issue as @connorshea with jest warnings, I figured out a fix that works here: https://github.com/visualfanatic/vue-svg-loader/issues/38#issuecomment-1135337194

ganeshkumarpolipalli-accolite commented 7 months ago

https://github.com/vuejs/vue-cli/issues/7448

any help? @dagadbm can you please help?

kubajmarek commented 7 months ago

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 commented 7 months ago

@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 commented 7 months ago

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