svg图标的webpack优化

前言

最近在做项目的优化升级,因为折腾了一下午的图标管理,所以就把自己的经验分享出来,希望可以帮助大家更快的解决自己的需求。

我现在的项目,都是引入iconfont的图标库,真是的好用又方便。现在有三种模式,使用方法可以在官网的 使用说明 页查看。我们今天主要讨论的主要是第三种,也就是svg图标的优化。

简单封装组件

使用说明里有提及,我们引入官方生成的库文件路径。写好css样式,页面代码引用如下:

"icon" aria-hidden="true">
    "#icon-xxx">

复制代码

我们简单的做一个组件封装如下:

// SvgIcon.vue




复制代码

将该组件注册为全局组件。新建文件夹,路径为src/icons。在其中新建一个index.js文件。

// icons/index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon.vue'

Vue.component('svg-icon', SvgIcon)
复制代码

main.js中,我们引入这个index.js

import './icons/index.js'
复制代码

这样我们就可以在文件中随意使用svg-icon组件了。

使用svg-sprite-loader

现在我们的svg文件是整体的,每当我们修改的时候,需要在iconfont上生成新的整体文件。那么是否能需要用一个icon的时候,就自己手动加一个呢?然后自动打包成一个整体文件。webpack可以帮我们实现。

首先,我们新建一个文件夹专门来放置单个svg文件。

如图,引入了多个从iconfont中下载的彩色图标svg文件。我们使用 svg-sprite-loader来把所有的单个svg合成为整体的svg雪碧文件。可以先看vue-cli3中的关于svg的默认配置(通过 vue inspect 命令查看,也可以在 vue ui的界面中点击查看):

 /* config.module.rule('svg') */
      {
        "test": /\.(svg)(\?.*)?$/,
        "use": [
          {
            "loader": "file-loader",
            "options": {
              "name": "img/[name].[hash:8].[ext]"
            }
          }
        ]
      },
复制代码

现在我们在vue.config.js文件中,来改写一下这个配置。

chainWebpack: config => {
// 我们先删除原有的svg rule。
    config.module.rules.delete('svg')
    config.module
      .rule('svg-sprite-loader')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
    // 但我们有的svg可能并不都是图标。我们的需要对icons/svg以外的svg文件做处理。我们把images的rule添加上svg格式。
    const imagesRule = config.module.rule('images')
    imagesRule.exclude.add(resolve('src/icons'))
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|webp|svg)(\?.*)?$/)
      
  }
复制代码

现在我们只要import进这个svg文件就可以使用了。

 import "@/icons/sun.svg";
 
 // 使用
 
    
  
复制代码

自动导入webpack的require.context

上面示例中我们是手动import一个图标,但一旦图标多起来,手动操作就太不优雅了。我们可以使用webpack自带的require.context功能来实现自动导入功能。

// icons/index.js

//(创建出)一个 context,其中文件来自 svg 目录,不包含子目录,request 以 `.svg` 结尾。
const req = require.context('./svg', false, /\.svg$/)

const requireAll = requireContext => requireContext.keys().map(requireContext)

requireAll(req)
复制代码

图标再多,都可以毫无烦恼啦~~~

进一步压缩 svgo-loader

其实我们引入的单个svg文件中有很多无用的信息。

svg-sprite-loader也做了相关处理,但是它只提取到 path标签整体,如果path路径内包含的无用的注释信息,如: 依旧存在。

我们可以使用 svgo-loader来进一步精简svg的内容。删除掉path 标签内的注释信息。配置如下:

// vue.config.js
chainWebpack: config => {
    config.module.rules.delete('svg')
    config.module
      .rule('svg-sprite-loader')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()
      .use('svgo-loader')
      .loader('svgo-loader')
      .end()
  }
复制代码

好了,这里就是所有关于svg图标使用和优化的全部内容了。如果有更好的方案和问题,欢迎大家指出和分享。

参考资料

  1. webpackg官网-管理依赖
  2. iconfont-使用说明
  3. 手摸手,带你优雅的使用 icon

转载于:https://juejin.im/post/5cb06532e51d456e8b07dd26

你可能感兴趣的:(svg图标的webpack优化)