SoFunction
Updated on 2025-04-06

Automatically import svg in vue project and use it happily

Several ways to introduce icons

Ancient times

  • Small icons png images are introduced, and the code is referenced one by one
  • Spirit picture, place multiple icons on a png picture, and display the corresponding icons through background attribute

iconfont era

  • Package all the icons used in the entire project to generate font files, and introduce them globally in the code. They can be used as long as they are tagged and class.

shortcoming:

  • When adding icons, you need to regenerate the font file. When team develops, adding icons will be particularly troublesome.

SVG era

Advantages:

  • svg can be introduced separately and does not need to be packaged together like iconfont
  • Encapsulate a global component, just like iconfont, and pass the class name to display the corresponding svg icon

Note: SVG has compatibility issues. When using it, first talk to the product to clearly understand whether the requirements need compatibility.

Process loader, process svg files on the specified directory

Install loader

npm i svg-sprite-loader -D

Configuration

Here is a vue directive that can easily query the loader rules of the hidden configuration files of vue

vue inspect --rule svg

Next, go to the configuration file

If not, create a new one

const path = require("path");
// Introduce path moduleconst resolve = dir => (__dirname, dir);

 = {
  ...,
  //Configure path alias  chainWebpack: config => {
    // vue inspect --rule svg  // Use the above directive to get the loader rules configured by vue    // svg loader Cancel the processing in the src/icons directory    ("svg").(resolve("src/icons"));
    // Add custom loader rules icons, only handle src/icons directory    
      .rule("icons")
      .test(/\.svg$/)
      .(resolve("src/icons")) // Context changes      .end() // Return to context      .use("svg-sprite-loader")
      .loader("svg-sprite-loader")
      .options({ symbolId: "icon-[name]" });
  },
  ...
};

There are mainly the following points:

  • Bypass the svg default rules from our custom directory src/icons
  • Create custom rules icons, including our custom directory src/icons
  • Configure the svg name rule, icon-[filename]

Next, use vue inspect to see the current configuration

vue inspect --rule svg

/* The following are our modified svg loader rules */
/* ('svg') */
{
  test: /\.(svg)(\?.*)?$/,
  exclude: [
    '/Users/{UserName}/project/src/icons' /* This is not included directory */
  ],
  use: [
    /* ('svg').use('file-loader') */
    {
      loader: '/Users/{UserName}/project/node_modules/file-loader/dist/',
      options: {
        name: 'img/[name].[hash:8].[ext]'
      }
    }
  ]
}

vue inspect --rule icons

// The following are the icons loader rules we added/* ('icons') */
{
  test: /\.svg$/,
  include: [
    '/Users/{UserName}/project/src/icons' /* This is the included directory */
  ],
  use: [
    /* ('icons').use('svg-sprite-loader') */
    {
      loader: 'svg-sprite-loader',
      options: {
        symbolId: 'icon-[name]'
      }
    }
  ]
}

Write a custom component

<template>
  <svg v-on="$listeners" :class="svgClass">
    <use :xlink:href="iconName" rel="external nofollow" ></use>
  </svg>
</template>
<script>
export default {
  name: "SvgIcon",
  props: {
    iconClass: {
      type: String,
      default: ""
    },
    className: {
      type: String,
      default: ""
    }
  },
  computed: {
    iconName() {
      return `#icon-${}`;
    },
    svgClass() {
      if () {
        return "svg-icon " + ;
      } else {
        return "svg-icon";
      }
    }
  }
};
</script>
<style scoped>
.svg-icon {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>

There are 2 parameters, iconClass (the name of the icon) and className (custom style name)

iconClass is the svg file name of the directory under src/icon

Write a JS to implement svg automation

import Vue from "vue";
import SvgIcon from "@/components/";
const isEnv = .NODE_ENV === "development";
// Automatically load all svgs in the icons directoryconst req = ("./svg", true, /\.svg$/);
const svgNameSet = new Set();
().map(url =&gt; {
  const pathSplit = ("/");
  const fileName = pathSplit[ - 1];
  isEnv &amp;&amp; (fileName);
  if ((fileName)) {
    isEnv &amp;&amp; ("Icon name is repeated, please check");
  } else {
    (fileName);
    return req(url); // Can be used for asynchronous require  }
});

// Global registration of components("svg-icon", SvgIcon);

This script mainly contains the following contents:

  • Global Register Components
  • Use ("./svg", true, /\.svg$/);, recursively traverse the src/icons directory to get all files
  • Make repeated reminders for the development environment (because the icon-[name] used here is unique, so when svg with the same file name will be overwritten)

So far, you can use svg happily

How to use it is as follows:

  • Copy the svg file to the src/icons directory, for example
  • Use <svg-icon iconClass="diamond"></svg-icon> directly in vue's template

Isn't it very simple? Go and try it now

Compression optimization

SVG usually has some redundant information (such as fill="red", which may also cause the color to be unable to be modified) and affect the volume. Here we can use svgo-loader to further compress it.

// install
npm i svgo-loader -D

// 
//Connect the above svg configuration...
.end()
.use('svgo-loader')
.loader('svgo-loader')
.end()

The above is personal experience. I hope you can give you a reference and I hope you can support me more.