🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall︱vue3-element-admin︱youlai-boot︱vue-uniapp-template
🌺 仓库主页: GitCode︱ Gitee ︱ Github
💖 欢迎点赞 👍 收藏 ⭐评论 📝 如有错误敬请纠正!
目录
- 
- [📝 前言背景](#📝 前言背景)
 - [🔍 问题分析:插件停止维护,依赖过时](#🔍 问题分析:插件停止维护,依赖过时)
 - [🛠️ 解决方案:使用 `@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`
});
        与 官方配置 有两点不同:
- 
使用
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识别。 - 
优化
fill处理,支持多彩图标为了避免默认
fill="currentColor"影响多彩图标的渲染,我们仅在SVG未定义fill时才自动补充:tsif (!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-icons,unocss 已内置
✅ 通过 safelist 自动读取 src/assets/icons,支持动态菜单图标
✅ 减少额外依赖,提高项目长期可维护性
开源项目地址 :vue3-element-admin
🚀 通过这次改造,我们实现了 更灵活、现代的 SVG 图标管理方式,欢迎大家尝试并优化自己的项目!