图标方案
一个必须面对的冲突
组件库的硬性约束是零运行时依赖,而 Iconify 有两种用法,性质完全不同:
| 用法 | 性质 | 与零依赖的关系 |
|---|---|---|
@iconify/vue 运行时组件 | 运行时渲染,默认从 Iconify API 在线拉取 | ✗ 冲突,且离线不可用、有加载闪烁 |
unplugin-icons + @iconify-json/* | 构建期编译为静态 SVG | ✓ 不冲突,产物中零运行时 |
分层方案
第 1 层:组件库自身的图标 —— 内联 SVG
弹窗关闭按钮、确认框类型图标、Toast 状态图标、选择器箭头等,全部以 内联 SVG 源码内置。不依赖 Iconify,不受宿主环境影响。
第 2 层:SrIcon 容器 —— 零依赖
SrIcon 只负责尺寸、颜色继承(currentColor)、旋转与文字对齐,图标内容由插槽传入。它不绑定任何图标数据源:
vue
<SrIcon :size="18">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
<path d="M12 5v14M5 12h14" />
</svg>
</SrIcon>第 3 层:业务图标 —— 由宿主接入 Iconify(构建期)
bash
pnpm add -D unplugin-icons @iconify-json/mdits
// vite.config.ts
import Icons from 'unplugin-icons/vite'
export default defineConfig({
plugins: [vue(), Icons({ compiler: 'vue3' })]
})之后在模板中直接使用,构建期即编译为静态 SVG:
vue
<template>
<SrButton>
<SrIcon><i-mdi-home /></SrIcon>
首页
</SrButton>
</template>优点:零运行时依赖、无网络请求、可 tree-shaking。 代价:宿主需一次性配置两个 devDependency。
为什么不用 @iconify/vue
如果接受下面的代价,它可以做到宿主零配置:
- 引入运行时依赖,必须写入组件库
dependencies(layer 安装时会一起装上) - 默认从 Iconify API 在线拉取,离线不可用且有加载闪烁
- 若需离线,须额外安装图标数据包,体积较大
结论
推荐「组件库内联 SVG + 宿主 unplugin-icons」组合——把 Iconify 的海量图标优势留在构建期,不污染运行时。