Iconify 的离线加载

🔑 核心原理

Iconify 的离线加载通过 @purge-icons/generated + vite-plugin-purge-icons 实现,将图标数据打包到构建产物中,运行时无需网络请求。

📦 完整流程

1. 构建时扫描 (build/vite/plugin/index.ts:62)

typescript 复制代码
vitePlugins.push(purgeIcons());

vite-plugin-purge-icons 插件在构建时:

  • 扫描所有源文件 (**/*.vue, **/*.ts, **/*.js)
  • 提取代码中使用的图标名称 (如 ant-design:user-outlined)
  • 从本地 node_modules/@iconify/json 读取对应图标的 SVG 数据
  • 如果本地没有,则从在线 API 获取

2. 代码生成 (@purge-icons/coreCodeGen 函数)

根据扫描到的图标列表,生成如下代码:

javascript 复制代码
import Module from '@iconify/iconify'
const Iconify = Module.default || Module

const collections = JSON.parse('[{"prefix":"ant-design","icons":{"user-outlined":{...},...}}]')

collections.forEach(c => Iconify.addCollection(c))

export default Iconify

这段代码会:

  • 将图标数据序列化为 JSON
  • 调用 Iconify.addCollection() 将图标数据注册到内存
  • 返回增强后的 Iconify 对象

3. 模块虚拟化 (node_modules/rollup-plugin-purge-icons/dist/index.mjs)

javascript 复制代码
function CreatePlugin(options) {
  return {
    name: "purge-icons",
    resolveId(id) {
      if (IMPORT_PATHS.includes(id)) return id;
    },
    async load(id) {
      if (IMPORT_PATHS.includes(id))
        return await PurgeIcons(options);  // 返回生成的代码
    }
  };
}

当 Vite 遇到 import Iconify from '@purge-icons/generated' 时:

  • resolveId 返回虚拟模块 ID
  • load 返回步骤2生成的代码字符串

4. 运行时使用 (src/components/Icon/src/Icon.vue:29,67)

vue 复制代码
<script>
import Iconify from '@purge-icons/generated';

const update = async () => {
  const icon = 'ant-design:user-outlined';
  const svg = Iconify.renderSVG(icon, {});  // 直接从内存渲染
  el.appendChild(svg);
}
</script>

Iconify.renderSVG() 从已注册的集合中获取图标数据:

javascript 复制代码
// @iconify/iconify 内部逻辑
function renderSVG(name, customizations) {
  const collection = collections.get(collectionName);  // 从内存获取
  const iconData = collection.icons[iconName];
  return createSvgElement(iconData);  // 生成 SVG DOM
}

🎯 关键优势

特性 实现方式 效果
离线访问 图标数据打包到 JS 中 无需网络请求
按需加载 只打包实际使用的图标 减小打包体积
动态渲染 使用 Iconify.renderSVG() 灵活控制样式
类型安全 导入自生成的模块 IDE 支持良好

🔧 项目中的配置

typescript 复制代码
// vite.config.ts:105-112
optimizeDeps: {
  include: [
    '@iconify/iconify',  // 显式声明依赖
  ],
}

这个配置是必须的,因为 @iconify/iconify@purge-icons/generated 动态虚拟加载,Vite 无法自动预构建。

📊 实际效果

  • 构建前 : 792个 Ant Design 图标定义在 icons.data.ts
  • 构建时: vite-plugin-purge-icons 扫描并提取使用到的图标
  • 运行时: Iconify 直接从内存渲染 SVG,性能极高
  • 网络需求: 零 (完全离线)

💡 与在线加载的对比

javascript 复制代码
// ❌ 在线模式: 需要网络请求
<span class="iconify" data-icon="ant-design:user-outlined"></span>
// 浏览器会自动从 iconify CDN 加载 SVG

// ✅ 离线模式: 使用 renderSVG
const svg = Iconify.renderSVG('ant-design:user-outlined', {});
el.appendChild(svg);
// 从内存中的已注册集合获取数据
相关推荐
why技术8 小时前
AI Coding开始进入第四个时代,我还没上车呢!
前端·人工智能·后端
叶小鸡8 小时前
Java 篇-项目实战-AI 天机学堂(从 0 到 1)-day1
java·开发语言
大家的林语冰9 小时前
CSS 已死?DOM 性能黑洞!Pretext 排版革命让你在文本间跳舞,没有 DOM 也能纵享丝滑~
前端·javascript·css
vipbic9 小时前
我也该升级了,陪伴了我7年的博客
前端
Lee川9 小时前
RAG 实战:从一篇掘金文章出发,拆解检索增强生成的全链路
前端·人工智能·后端
Lee川9 小时前
MCP 高德地图实战:当 AI 学会使用工具,一个协议如何重塑大模型的行动边界
前端·人工智能·后端
楼田莉子10 小时前
C++17新特性:__had_include/属性/求值顺序规则
开发语言·c++·后端
ZC跨境爬虫10 小时前
跟着 MDN 学CSS day_14:(尺寸调整技能测试与实战解析)
前端·css·ui·html·tensorflow
kyriewen10 小时前
用魔法打败魔法:我让AI替我去面试前端岗,AI面试官给我打了92分,还发了offer
前端·javascript·面试
IT_陈寒10 小时前
Redis批量删除踩了坑,原来DEL命令不是万能的
前端·人工智能·后端