教程:写一个 sag-icons 这样的图标 npm 包

这套教程讲怎么从零做一个 sag-icons——一个多色调、状态感知、Web Component 的 SVG 图标库。

整套教程以 sag-icons 实际代码为例,每一步都能在仓库里找到对应文件。你读这套教程的目的不是"复制 sag-icons",而是理解它背后那些可以搬到任何图标库的设计决策。


为什么有这个教程

sag-icons 的代码里有不少没写在注释里的决策:

  • 为什么是 Web Component 而不是 React/Vue 组件
  • 为什么用 data-tone 属性而不是 props 传色
  • 为什么 CSS 变量穿透而不是 Shadow DOM 隔离
  • 为什么放弃 1500+ 图标数量,聚焦 200+
  • 为什么 5 个语义色板里没有红色

这些决策很难从代码反推。如果你只看 sag-icon.ts 那个不到 100 行的类,会觉得"就这?我也能写"——但真正难的是这些代码没写的部分:当时考虑过哪些方案、为什么放弃、踩过哪些坑。

这套教程就是把这些代码之外的东西讲清楚。

市面上的图标库教程大多是这样的

  • ✅ 教你怎么打包成 npm 包(tsup / vite 库模式)
  • ✅ 教你怎么写 SVG(viewBox / stroke)
  • ❌ 不教为什么选 Web Component 而不是 React 包
  • ❌ 不教主题系统的 CSS 变量怎么设计
  • ❌ 不教哪些是"看起来对但实际是坑"的方案

sag-icons 的教程反过来:

  • ✅ 默认你会发包、会用 Vite、会写 TS(不重复造轮子)
  • ✅ 重头戏在设计决策、Web Component 实战、CSS 主题系统
  • ✅ 真实走过的弯路(按框架分发、Shadow DOM、巨型图标库)

这套教程不是什么

  • 不是 React 教程——我们假设你会 JSX
  • 不是 Vite 教程——vite.config.ts 只讲库模式那点配置
  • 不是 CSS 教程——只讲"用 CSS 变量做主题系统"这个具体场景
  • 不是设计教程——Figma 部分讲基础规范,够用就行

这套教程是什么

是一个决策档案——把 sag-icons 做对的事和做错的事整理出来,让你在做自己的图标库时少走两年弯路。


读完你能做什么

  • 自己做一个图标库(不一定是 sag-icons 这个样子)
  • 理解 Web Component 跨框架图标的工程取舍
  • 掌握 CSS 变量 + data-* 属性做主题系统的套路
  • 知道 npm 包的 exports 字段怎么设计才能既支持全量又支持按需

教程结构

#章节解决的问题
02图标设计·Figma一个多色图标是怎么被画出来的
03图标设计·PathFigma 的 SVG 怎么变成 TS 里的字符串
04包工程基础package.json / tsconfig / 打包工具怎么选
05Web Component 核心自定义元素怎么写才"够用"
06CSS 多色调系统一个 CSS 文件驱动所有颜色状态
07类型系统让 <sag-icon name="..." /> 有自动补全
08构建与发布从 tsc 到 npm publish 的完整流水线
09发布后迭代加一个新图标的清单 + 后续路线

sag-icons 在做什么

一句话:为"多色调 + 状态感知"UI 场景做的专项图标库。

具体来说,它解决一个非常具体的问题:

// 一个侧边栏导航
<sag-icon name="workbench" />
<sag-icon name="settings" />

默认灰色。加个类激活:

<sag-icon name="workbench" className="is-active" />
<sag-icon name="settings" />

激活的那个变成全彩色。整个状态切换不靠 props、不靠 JS 状态机、不靠 wrapper 组件——就一个 CSS 类。

这个看似简单的特性,背后其实是一整套设计决策:

  • 数据怎么存(每个图标是字符串,按需路径可独立 import)
  • 状态怎么切(CSS 变量 + data-tone 选择器,is-active 触发布尔变量)
  • 跨框架怎么搞(Web Component 一套走 React / Vue / 原生 HTML)
  • 类型怎么给(as const 派生 IconName,JSX 增强独立 .d.ts)

每一章都会围绕一个这样的设计决策展开。


sag-icons 不是什么

为了避免误会,先说清楚它不做的事:

  • ❌ 不是通用图标库(Lucide / IconPark / Tabler 那些"1500+ 图标、什么场景都能用"的路子)
  • ❌ 不是按框架分发的包(不需要 react-sag-icons / vue-sag-icons / svelte-sag-icons)
  • ❌ 不支持主题切换系统(4 套主题那种;它只做 1 套主题下的状态切换)
  • ❌ 不打算做 1500+ 图标(sag-icons 现在 78 个,目标是 200+,不是 1500+)

这些"不做的事"是有意的取舍,不是能力不够。教程每一章都会讲到取舍的理由。


阅读建议

如果你想自己做一个图标库:

  1. 先看 02-03——理解图标本身的设计与存储
  2. 再看 04-05——工程基础和核心实现
  3. 06-08 是"sag-icons 的精髓",强烈推荐精读
  4. 09 是 checklist,可以收藏

如果你只是想知道"Web Component 怎么做图标库"或者"CSS 变量主题系统怎么搭":

  • 05 是 Web Component 实战
  • 06 是 CSS 主题系统实战

可以单独读这两章,不必按顺序。


配套代码

教程所有示例都对应 sag-icons 仓库的实际文件。每个章节末尾的"对应文件"小节会给出路径和行号。

仓库地址:github.com/JujiuYey/sag-icons


准备好就往下走。下一章我们从图标本身开始——一个多色图标是怎么在 Figma 里被画出来的。