当前位置:   article > 正文

Vite插件自动编译svg图标为字体_vite svg字体图标

vite svg字体图标

前言

今天来点儿6的.本文或许需要花费点时间才能理解.
目前是草稿阶段,比较凌乱,许多部分没有详细说明,日后有空更新补充.

本文主要提供解决思路,请按需调整.

很多时候我们在开发阶段是不能确定使用哪些图标的,它会随着开发不停的新增或调整.
所以我一般会从iconfont直接下载svg图标保存起来.

注意本段为废话可以跳过
一开始我是直接将svg代码直接插入dom中,但总觉得这么干会浪费内存影响效率之类的…后来我就好奇平时常见的图标字库是怎么构建的…

查着查着就发现了svgtofont这件神器.
它可以自动寻找某个目录下的svg文件,随后一键生成.less .css .ttf .woff这一堆你要的文件,岂不美哉…
关于它的用法及原理本文不着重介绍,小伙伴可以自行查询,一抓一大把…

开始

本文目的主要解决两大痛点

  1. 使用vite自动更新构建svg图标库到项目中
  2. 还是使用vite自动更新构建svg图标库到项目中

解决

我写了一个vite.plugin.svgtofont.ts插件,以实现自动重编译.
它目前在我的UI库中工作的很好,很大程度提高了我编写该库的效率.

根目录下创建一个文件 vite.plugin.svgtofont.ts

//vite.plugin.svgtofont.ts
import { PluginOption } from "vite";
import path from 'path'
import chokidar from 'chokidar';
import svgtofont from 'svgtofont';
import fs from 'fs';

/* 注意 svg文件名不能存在空格 */
const plugin: PluginOption = {
    name: 'svgtofont',
    configureServer(server) {
        // 监视 SVG 目录
        const fontName = "mpui-icon"
        const src = path.resolve(__dirname, 'svg');
        const dist = path.resolve(__dirname, 'src/Components/Icon/font');
        const watcher = chokidar.watch(src, { ignoreInitial: true });
        console.log(`[vite.plugin.svgtofont]开始监视SVG目录文件变化:${src}`);

        const rebuild = async () => {
            // 当 SVG 文件变化时,使用 svgtofont 重新编译字体
            await svgtofont({
                fontName, src, dist,
                css: {
                    fontSize: "1em",
                },
                // 其他 svgtofont 配置项...
            });

            //生成TS引用文件
            console.log(`[vite.plugin.svgtofont]SVG图标重编译->生成TS引用文件...`);
            const cssFilePath = path.resolve(dist, `${fontName}.css`);
            const cssContent = fs.readFileSync(cssFilePath, 'utf-8');
            // console.log("=>cssContent:", cssContent);

            // 使用正则表达式匹配所有的图标名称
            const iconNames = cssContent.match(/\.mpui-icon-(\w+):before/g) || [];
            // 生成 TypeScript 文件的内容
            let tsContent = `import "./${fontName}.less"\nexport type IconName =\n`;
            iconNames.forEach((iconName, index) => {
                iconName = iconName.replace(`.${fontName}-`, '').replace(':before', '');
                tsContent += `  | '${iconName}'\n`;
            });
            //console.log("=>tsContent:", tsContent);
            fs.writeFileSync(path.resolve(dist, `${fontName}.ts`), tsContent);


            console.log(`[vite.plugin.svgtofont]SVG图标->重编译完成,重加载页面...`);

            // 通知 Vite 重新加载页面
            server.ws.send({ type: 'full-reload', });
            console.log(`[vite.plugin.svgtofont]SVG图标->重载完成!`);

        }
        watcher.on("ready", async () => {
            console.log(`[vite.plugin.svgtofont]SVG图标重编译->初始化...`);
            await rebuild();
        });
        watcher.on('add', async (path) => {
            console.log(`[vite.plugin.svgtofont]SVG图标重编译-新增文件:${path}`);
            await rebuild();
        });
        watcher.on('unlink', async (path) => {
            console.log(`[vite.plugin.svgtofont]SVG图标重编译-移除文件:${path}`);
            await rebuild();
        });
    }
}


export default plugin

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

使用

修改vite配置文件,新增我们刚才写的插件.

//vite.config.ts
import svgtofont from "./vite.plugin.svgtofont"
import { defineConfig } from "vite"
export default defineConfig({

   ...
    plugins: [
        svgtofont,
    ],
    optimizeDeps: {
        /* 设置不被Vite打包的包 */
        exclude: ["fs", "path", "chokidar", "svgtofont"],
    }
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

然后你需要制作一个Icon类负责实例化元素
这里使用到了CustomElements 没用过的话可以去补课一下

import { IconName } from '你插件上配置的输出路径';

export class Icon extends HTMLElement{
constructor(name: IconName ) {
  super()
  this.classList.add( `mpui-icon-${nameOrSVG}`)
  
  }
}

export defalut Icon 
if(!customElements.get("mpui-icon"))customElements.define("mpui-icon",Icon)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

然后用起来就很简单了

import Icon from "./Icon"
document.body.appendChild(new Icon("MiragePulse"))
  • 1
  • 2

随后你会在dom中看到一个名为mpui-icon的元素
神奇吧.你可以在上面提到的Icon.ts结尾部分更改它叫啥
在这里插入图片描述

这个元素被渲染出来以后是这样的
在这里插入图片描述
这是我用Illustrator画的一个小图标,转存为了SVG文件生成的.
(Illustrator生成的SVG大多数情况不能直接使用,还需要进一步压缩处理,下次更新说明)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/481796
推荐阅读
相关标签
  

闽ICP备14008679号