自制 Vite SVG Sprites 插件

211 阅读2分钟

主要用于创建 SVG 图标精灵(SVG Sprites)并对其中的 SVG 图标进行优化。

  1. 导入所需的模块:

    • path:用于处理文件路径。
    • fs:用于文件系统操作,例如读取文件。
    • store:一个用于创建 SVG 图标精灵的库。
    • optimize:用于优化 SVG 文件的函数。
  2. 导出一个名为 svgstore 的函数,该函数接受一个名为 options 的参数,用于配置精灵生成和优化过程。

  3. 在函数内部,首先设置了一个默认的输入文件夹路径 inputFolder,如果没有传入 options.inputFolder 参数,则默认使用 'src/assets/icons'。

  4. 返回一个包含以下属性的对象:

    • name:插件的名称,为 'svgstore'。

    • resolveId 函数:用于解析模块的标识符,兼容编辑器可能找不到 svg_bundle.js 文件的情况。如果标识符为 '@svgstore',则返回 'svg_bundle.js'。

    • load 函数:用于加载模块内容。当标识符为 'svg_bundle.js' 时,执行以下操作:

      • 使用 store 创建一个 SVG 图标精灵实例 sprites
      • 获取指定文件夹中的所有文件,遍历每个文件。
      • 读取每个 SVG 文件的内容,并将其添加到 sprites 中,使用文件名作为 SVG 的标识符。
      • 使用 svgo 库对 sprites 中的 SVG 进行优化,以生成最终的 SVG 精灵代码。
      • 返回一个包含最终 SVG 精灵代码的字符串,同时在代码中也包含了一些用于将 SVG 插入到页面并进行样式处理的 JavaScript 代码。
import path from 'path'
import fs from 'fs'
import store from 'svgstore' // 用于制作 SVG Sprites
import { optimize } from 'svgo' // 用于优化 SVG 文件

export const svgstore = (options = {}) => {  //接受一个选项
    const inputFolder = options.inputFolder || 'src/assets/icons';
    return {                                 // return一个对象
        name: 'svgstore',
        resolveId(id) {            //为了兼容编辑器可能找不到svg_bundle.js文件写此方法
            if (id === '@svgstore') {
                return 'svg_bundle.js'
            }
        },
        load(id) {
            if (id === 'svg_bundle.js') {
                const sprites = store(options);
                const iconsDir = path.resolve(inputFolder);
                for (const file of fs.readdirSync(iconsDir)) {
                    const filepath = path.join(iconsDir, file);
                    const svgid = path.parse(file).name
                    let code = fs.readFileSync(filepath, { encoding: 'utf-8' });
                    sprites.add(svgid, code)
                }
                const { data: code } = optimize(sprites.toString({ inline: options.inline }), {
                    plugins: [
                        'cleanupAttrs', 'removeDoctype', 'removeComments', 'removeTitle', 'removeDesc',
                        'removeEmptyAttrs',
                        { name: "removeAttrs", params: { attrs: "(data-name|data-xxx)" } }
                    ]
                })
                return `const div = document.createElement('div')
div.innerHTML = \`${code}\`
const svg = div.getElementsByTagName('svg')[0]
if (svg) {
  svg.style.position = 'absolute'
  svg.style.width = 0
  svg.style.height = 0
  svg.style.overflow = 'hidden'
  svg.setAttribute("aria-hidden", "true")
}
// listen dom ready event
document.addEventListener('DOMContentLoaded', () => {
  if (document.body.firstChild) {
    document.body.insertBefore(div, document.body.firstChild)
  } else {
    document.body.appendChild(div)
  }
})`
            }
        }
    }
}

总之,这是一个 vite 插件,用于将一组 SVG 图标合并为一个精灵,并进行一些优化和样式处理,然后将该精灵添加到页面中。这可以帮助减少页面请求和提高性能,特别是在使用大量 SVG 图标时。