vue-cli 最新版本使用 SvgIcon 不生效

785 阅读1分钟

vue-cli 最新版本使用 SvgIcon 不生效

背景

用 vue-cli 创建的项目,在借助 svg-sprite-loader 使用 SvgIcon 时,一般的做法是在 vue.config.js 里加如下的配置

const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
  .test(/\.svg$/)
  .include.add(resolve('src/svgIcon/svg'))
  .end()
  .use('svg-sprite-loader')
  .loader('svg-sprite-loader')
  .options({
    symbolId: 'icon-[name]',
  })

对于 .svg 文件,我们只希望使用 svg-sprite-loader 来处理,所以,在之前,我们会使用 clear 方法来清掉应用到 .svg 文件上的 loader。这个操作在 vue-cli 之前的版本都是可以的。然而在最新版本的 vue-cli 创建的项目中,不生效

分析原因

我的第一想法是打印出 svgRule ,看看和之前的有什么不同,这里我起了之前的 vue-cli 版本创建的项目,所有的配置都一样,且 SvgIcon 是可以正常显示的。下面让我们来来看看新旧 vue-cli 版本下的 svgRule。

旧的 vue-cli 版本

1.png

新的 vue-cli 版本

2.png

通过上面两张图可以发现,新版的 vue-cli 对于 .svg 文件,不仅使用了 svg-sprite-loader,还多了点什么东西,下面我们就进一步分析多出来的究竟是什么东西。

我把 vue.config.js 中配置做了如下修改

const svgRule = config.module.rule('svg')
// svgRule.uses.clear()
svgRule
  .test(/\.svg$/)
  .include.add(resolve('src/svgIcon/svg'))
  .end()
  .use('svg-sprite-loader')
  .loader('svg-sprite-loader')
  .options({
  symbolId: 'icon-[name]',
})

把之前适用 .svg 文件上的 loader 清除语句删掉,然后接着打印 svgRule,看看新旧 vue-cli 版本下的差异。

旧的 vue-cli 版本

3.png

新的 vue-cli 版本

4.png

观察上面两张图,我发现,在旧版的 vue-cli 中,是使用 file-loader 来处理 .svg 文件的,而新的 vue-cli 版本使用的是 type: 'asset/resource',这个其实就是 webpack5 的用法,它的作用就等同于 webpack4 中的 file-loader。

接下来我们使用 vue inspect --rule svg 来查看 rule 的配置

旧的 vue-cli 版本

5.png

新的 vue-cli 版本

6.png

上面两张图进一步证实了上面所说的 vue-cli 新旧版本的差异

解决问题

根据上面打印的 svgRule 的结构,我们发现它其实是多了 type 和 generator 两个属性,我尝试把这两个属性删掉

const svgRule = config.module.rule('svg');
svgRule.uses.clear();
svgRule.delete('type');
svgRule.delete('generator');
svgRule
  .test(/\.svg$/)
  .include.add(resolve('src/svgIcon/svg'))
  .end()
  .use('svg-sprite-loader')
  .loader('svg-sprite-loader')
  .options({
    symbolId: 'icon-[name]',
});

页面确实是可以正常展示 svgIcon 了,但这只是我们的尝试做法,我想知道 vue-cli 是否有暴露出方法来处理。于是我去查找了 vue-cli 的官方文档,并没有找到。我又去了 vue-cli 的 github 上的 issues,大家的写法也是这个。​​ github issue 地址​