🔑 核心原理
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/core 的 CodeGen 函数)
根据扫描到的图标列表,生成如下代码:
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返回虚拟模块 IDload返回步骤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);
// 从内存中的已注册集合获取数据