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

Please create a new version to support svgo 2.x #156

Open
dong111777 opened this issue Apr 8, 2021 · 7 comments
Open

Please create a new version to support svgo 2.x #156

dong111777 opened this issue Apr 8, 2021 · 7 comments

Comments

@dong111777
Copy link

The dev branch seems to support svgo 2.x now, could you please help build a new package to npm?

@Keavon
Copy link

Keavon commented Nov 1, 2021

Please @visualfanatic

@Excalibaard
Copy link

What I did for SVGO 2.x support is just chaining svgo-loader, before passing to vue-svg-loader, and set svgo: false for vue-svg-loader.


At that point the only thing this package does is wrap the SVG in <template></template>tags though, so you could write your own loader instead of relying on this unmaintained package. If you ignore all the vue checking, all you need is below.

module.exports = function vueSvgLoader(svg) {
  return `<template>${svg}</template>`;
};

@rightaway
Copy link

@Excalibaard Can you please show exactly how you did it? Would like to do it your way so I can get rid of this package since @visualfanatic has stopped maintaining or responding for a long time3.

@darrinmn9
Copy link

@Excalibaard is your solution for Vue2 or Vue3? Because looking at the latest dev branch for commit WIP SVGO 2.x, it seems that if you are supporting Vue2 you need to add:

  if (semverMajor(version) === 2) {
    svg = svg.replace('<svg', '<svg v-on="$listeners"');
  }

  return `<template>${svg}</template>`;

https://github.com/visualfanatic/vue-svg-loader/blob/dev/index.js#L16-L18

@Excalibaard
Copy link

Excalibaard commented May 23, 2022

@rightaway Easiest solution is to pick a different package that's actively maintained, though it has a different way to use it:

https://github.com/oliverfindl/vue-svg-inline-loader

EDIT: This package also relies on SVGO 1.x.

Otherwise, you can still use this package, but without the svgo part. The below example shows importing SVG as component using the 'inline' query, for example import SVGIcon from '@/assets/SVGIcon.svg?inline'. This allows you to still use svg as an image when necessary.

// webpack.config.js

module.exports = {
  ...,
  module: {
    rules: [
      {
        test: /\.svg$/,
        resourceQuery: /inline/,
        use: [
          {
            loader: 'vue-loader'
          },
          {
            loader: 'vue-svg-loader',
            options: { 
              svgo: false,
            }
          },
          {
            loader: 'svgo-loader',
            options: {
              // configFile: false // uncomment if not using a svgo.config.js file in your project root
              .... // add your svgo options here
            }
          }
        ]
      },
      {
        test: /\.svg$/,
        use: [
          {
            loader: 'file-loader'
          },
          {
            loader: 'svgo-loader'
          },
        ]
      }
    ]
  }
}

or with VueCLI:

// vue.config.js

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

    svgRule.uses.clear();

    svgRule
      .test(/\.svg$/)
        .oneOf('inline')
          .resourceQuery(/inline/)
          .use('vue-loader')
            .loader('vue-loader')
            .end()
          .end()
          .use('vue-svg-loader')
            .loader('vue-svg-loader')
            .options({
              svgo: false
            })
            .end()
          .end()
          .use('svgo-loader')
            .loader('svgo-loader')
            .options({
              // configFile: false // uncomment when you have no svgo.config.js at project root
              .....
            })
            .end()
          .end()
        .oneOf('normal')
          .use('file-loader')
            .loader('file-loader')
            .end()
          .end()
          .use('svgo-loader')
            .loader('svgo-loader')
            .end()
          .end()
  }
}

The solution I ended up using in that codebase was to make a folder specifically for my custom loaders, and making sure it's added to webpack's resolveLoader option.

// webpack.config.js

module.exports = {
  //...
  resolveLoader: {
    modules: [
      'node_modules',
      path.resolve(__dirname, 'loaders')  // [workspaceRoot]/loaders
    ]
  }
};

Then, create the file [workspaceRoot]/loaders/vue-svg-loader.js.

// loaders/vue-svg-loader.js

const { version } = require('vue');
const semverMajor = require('semver/functions/major')

module.exports = function vueSvgLoader(svg) {
  if (semverMajor(version) === 2) {
    svg = svg.replace('<svg', '<svg v-on="$listeners"');
  }

  return `<template>${svg}</template>`;
};

Then, add the vue-svg-loader rule as normal (without options). Because webpack now looks in your [root]/loaders folder as well as node-modules, it will find a match with your own loader. Make sure you have removed the vue-svg-loader package from your dependencies, so it doesn't find one in node-modules.

Here's a gist of the loader I used that replaces both svgo-loader and vue-svg-loader..

@darrinmn9 You're correct, if you use Vue 2 you may need to add v-on="$listeners"to make sure any events within your SVG component are emitted to the parent. However, since there components are created within the webpack tool chain, I'm not quite sure what kind of events those may be, Clicking specific elements perhaps. Anyhow, my SVGs work fine without it, in both Vue 2 and Vue 3 (where v-on="$listeners" is deprecated, as listeners are automatically included in $attrs). I've included the version checker in my example above for completeness.

@ChrisRoss5
Copy link

@Excalibaard vue-svg-inline-loader is not actively maintained.

@Excalibaard
Copy link

@ChrisRoss5 You're correct. It has been updated more recently, but also uses SVGO 1.x. I'll remove that recommendation.

cpsoinos added a commit to cpsoinos/nuxt-svgo that referenced this issue Jun 23, 2022
As discussed in
damianstasik/vue-svg-loader#156,
'vue-svg-loader' uses svgo v1. That project looks to be unmaintained,
with the latest beta release more than 2 years old. This PR disables the
svgo functionality of vue-svg-loader, instead relying on svg/svgo-loader
to perform optimizations, essentially making vue-svg-loader wrap the svg
content in template tags.

✅ Closes: #37
cpsoinos added a commit to cpsoinos/nuxt-svgo that referenced this issue Jun 23, 2022
* refactor: 💡 change nuxt config key from 'svgoOptions' to 'svgo'

BREAKING CHANGE: 🧨 Nuxt config key is now 'svgo', instead of 'svgoOptions'

* chore: 🤖 changeset

* chore: 🤖 update playground to use new 'svgo' config key

* fix: 🐛 use svgo-loader to run svgo with options with webpack

As discussed in
damianstasik/vue-svg-loader#156,
'vue-svg-loader' uses svgo v1. That project looks to be unmaintained,
with the latest beta release more than 2 years old. This PR disables the
svgo functionality of vue-svg-loader, instead relying on svg/svgo-loader
to perform optimizations, essentially making vue-svg-loader wrap the svg
content in template tags.

✅ Closes: #37

* docs: ✏️ update README with webpack-based tooling info

* docs(changeset): fix webpack SVG optimization with svgo-loader
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