Skip to content

图标方案

一个必须面对的冲突

组件库的硬性约束是零运行时依赖,而 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/mdi
ts
// 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

如果接受下面的代价,它可以做到宿主零配置:

  1. 引入运行时依赖,必须写入组件库 dependencies(layer 安装时会一起装上)
  2. 默认从 Iconify API 在线拉取,离线不可用且有加载闪烁
  3. 若需离线,须额外安装图标数据包,体积较大

结论

推荐「组件库内联 SVG + 宿主 unplugin-icons」组合——把 Iconify 的海量图标优势留在构建期,不污染运行时。

自用组件库 · 源码分发 · 不发布 npm