「vue3-element-admin」告别 vite-plugin-svg-icons!用 @unocss/preset-icons 加载本地 SVG 图标

🚀 作者主页: 有来技术

🔥 开源项目: youlai-mallvue3-element-adminyoulai-bootvue-uniapp-template

🌺 仓库主页: GitCodeGiteeGithub

💖 欢迎点赞 👍 收藏 ⭐评论 📝 如有错误敬请纠正!

目录

    • [📝 前言背景](#📝 前言背景)
    • [🔍 问题分析:插件停止维护,依赖过时](#🔍 问题分析:插件停止维护,依赖过时)
    • [🛠️ 解决方案:使用 `@unocss/preset-icons`](#🛠️ 解决方案:使用 @unocss/preset-icons)
      • [1️⃣ 安装依赖](#1️⃣ 安装依赖)
      • [2️⃣ 配置 `uno.config.ts`](#2️⃣ 配置 uno.config.ts)
      • [3️⃣ 使用图标](#3️⃣ 使用图标)
    • [🏆 总结](#🏆 总结)

📝 前言背景

在此之前,开源项目 vue3-element-admin 使用 vite-plugin-svg-icons 管理和加载从iconfont 等网站下载到本地 SVG 图标。但由于该插件 已停止维护,部分依赖逐渐过时,可能影响未来兼容性,因此需要迁移到更稳定的方案。

🔍 问题分析:插件停止维护,依赖过时

在项目中执行 pnpm install 时,我们发现控制台出现了以下 废弃依赖警告

bash 复制代码
 WARN  10 deprecated subdependencies found: fstream@1.0.12, glob@7.2.3, inflight@1.0.6, lodash.isequal@4.5.0, resolve-url@0.2.1, rimraf@2.7.1, source-map-resolve@0.5.3, source-map-url@0.4.1, stable@0.1.8, urix@0.1.0

通过 pnpm why urix 追踪依赖来源,发现 这些过时依赖属于 vite-plugin-svg-icons ,而 vite-plugin-svg-icons 最近一次更新是在 2022 年 1 月 29 日 ,其被维护的概率很小。

为了确保长期稳定性,决定 @unocss/preset-icons 替代 vite-plugin-svg-icons


🛠️ 解决方案:使用 @unocss/preset-icons

@unocss/preset-icons 是 UnoCSS 提供的图标预设,支持从 本地和在线图标库 加载图标。它相比 vite-plugin-svg-icons 具有以下优势:

  • 无需额外安装unocss 自带 @unocss/preset-icons,减少额外依赖;
  • 直接支持 Iconify 图标集 ,可以同时使用 本地 SVG 和在线图标
  • 按需加载,无需手动导入,减少构建体积。

官方文档https://unocss.nodejs.cn/presets/icons

1️⃣ 安装依赖

使用 FileSystemIconLoader 从文件系统加载本地 SVG 图标,需要安装 @iconify/utils 作为开发依赖:

bash 复制代码
pnpm add -D @iconify/utils

⚠️ 注意:@unocss/preset-icons 已包含在 unocss 中,无需单独安装。

2️⃣ 配置 uno.config.ts

vue3-element-admin 项目中,应在 uno.config.ts 配置,而非 vite.config.ts

完整配置如下:

ts 复制代码
import { defineConfig, presetUno } from "unocss";
import presetIcons from "@unocss/preset-icons";
import { FileSystemIconLoader } from "@iconify/utils/lib/loader/node-loaders";
import fs from "fs";

// 本地 SVG 图标存放目录
const iconsDir = "./src/assets/icons";

// 读取本地 SVG 目录,自动生成 `safelist`
const generateSafeList = () => {
  try {
    return fs
      .readdirSync(iconsDir)
      .filter((file) => file.endsWith(".svg"))
      .map((file) => `i-svg:${file.replace(".svg", "")}`);
  } catch (error) {
    console.error("无法读取图标目录:", error);
    return [];
  }
};

export default defineConfig({
  presets: [
    presetIcons({
      // 设置全局图标默认属性
      extraProperties: {
        width: "1em",
        height: "1em",
        display: "inline-block",
      },
      // 注册本地 SVG 图标集合
      collections: {
      	// svg 是图标集合名称,使用 `i-svg:图标名` 调用  
        svg: FileSystemIconLoader(iconsDir, (svg) => {
          // 如果 SVG 文件未定义 `fill` 属性,则默认填充 `currentColor`  
          // 这样图标颜色会继承文本颜色,方便在不同场景下适配  
          return svg.includes('fill="')
            ? svg
            : svg.replace(/^<svg /, '<svg fill="currentColor" ');
        }),
      },
    }),
  ],
  safelist: generateSafeList(), // 动态生成 `safelist`
});

官方配置 有两点不同

  1. 使用 safelist 解决动态图标加载问题

    UnoCSS 采用 按需扫描 机制,仅能解析静态 类名,而 vue3-element-admin 的菜单图标是动态加载的,例如:

    html 复制代码
    <template>
      <div v-for="item in menuItems" :key="item.name">
        <div :class="`i-svg:${item.icon}`"></div>
        {{ item.name }}
      </div>
    </template>
    
    <script setup lang="ts">
    	const menuItems = [
    	  { name: "首页", icon: "home" },
    	  { name: "设置", icon: "settings" },
    	];
    </script>

    由于 unocss 无法在编译阶段解析动态绑定的 :class ,导致图标不会被正确加载。因此,我们通过 扫描 src/assets/icons 目录并动态生成 safelist ,确保所有本地 SVG 图标类名都能被 unocss 识别。

  2. 优化 fill 处理,支持多彩图标

    为了避免默认 fill="currentColor" 影响多彩图标的渲染,我们仅在 SVG 未定义 fill 时才自动补充:

    ts 复制代码
    if (!svg.includes('fill="')) {
      return svg.replace(/^<svg /, '<svg fill="currentColor" ');
    }

3️⃣ 使用图标

uno.config.ts 中,通过 collections 注册了名为 svg 的本地 SVG 图标集合,并使用 FileSystemIconLoader 读取 src/assets/icons 目录下的 SVG 文件。因此,可直接使用 i-svg:图标名称 调用。

示例:

text 复制代码
src/assets/icons/home.svg → i-svg:home
html 复制代码
<template>
  <!-- 默认尺寸 1em,颜色继承父级 text 颜色 -->
  <div class="i-svg:home"></div>

  <!-- 自定义颜色和尺寸 -->
  <div class="i-svg:home text-xl text-blue-500"></div>   
</template>

最终效果如下:

🏆 总结

由于 vite-plugin-svg-icons 停止更新 ,且部分依赖过时,我们成功迁移到 @unocss/preset-icons,并针对 vue3-element-admin 进行了优化和改造

使用 @unocss/preset-icons 统一管理本地 SVG 图标

无需手动安装 @unocss/preset-iconsunocss 已内置

通过 safelist 自动读取 src/assets/icons,支持动态菜单图标

减少额外依赖,提高项目长期可维护性

开源项目地址vue3-element-admin

🚀 通过这次改造,我们实现了 更灵活、现代的 SVG 图标管理方式,欢迎大家尝试并优化自己的项目!

相关推荐
lixww.cn3 小时前
ASP.NET Core SignalR向部分客户端发消息
javascript·websocket·vue·asp.net core·signalr
qq_3993380012 小时前
vue3+websocket+springboot、websocket消息通讯
spring boot·websocket·网络协议·vue
ttod_qzstudio19 小时前
基于Typescript,使用Vite构建融合Vue.js的Babylon.js开发环境
vue.js·typescript·babylon.js
寰宇软件21 小时前
PHP预约咨询小程序
小程序·uni-app·vue·php
_未知_开摆1 天前
运行npm install卡住不动的
前端·vue.js·vscode·elementui·npm·node.js
不想秃头i1 天前
node.js + html + Sealos容器云 搭建简易多人实时聊天室demo 带源码
前端·javascript·node.js·vue·html·html5
太阳与星辰1 天前
07vue3实战-----辨析开发环境和生产环境
前端·typescript·后台管理·vue3实战
阿珊和她的猫1 天前
ESLint 配置详细指南
前端·javascript·typescript
阿珊和她的猫1 天前
组件库选择:ElementUI 还是 Ant Design
前端·javascript·elementui