前端组件库设计学习笔记
适合目标:8 小时内建立前端组件库设计完整知识框架,覆盖组件库设计核心、目录结构、样式体系、构建产物、不同文件格式对应使用方式、工程化、发布流程与高频面试题。
学习重点:组件库不是“写几个组件”,而是“设计一套可复用、可维护、可发布、可扩展的 UI 能力系统”。
学习原则:先理解组件库解决什么问题,再学组件怎么写;先掌握设计原则,再看打包产物;先会讲架构,再讲 API 和构建细节。
目录
- 学习总览
- 组件库到底在解决什么
- 组件库设计核心
- 组件分层与目录结构
- 组件 API 设计
- 样式系统、主题与 Design Token
- 组件库构建与输出产物
- 不同文件格式对应的使用方式
package.json设计与发布字段- Tree Shaking、按需加载与包体积优化
- 文档、测试、版本管理与发布
- 实战项目设计建议
- 高频面试题
- 更好记的学习方法
- 8 小时学习节奏建议
- 一页速记总结
- 背诵口诀
1. 学习总览
1.1 什么是前端组件库设计
很多人对组件库的第一印象是:
把 Button、Input、Modal 这些组件封装起来。
这只是最表层。
更完整地说,组件库设计学的是:
如何把零散的 UI 和交互能力,沉淀成一套稳定、统一、可复用、可发布、可扩展的前端基础设施。
所以组件库设计不只是写组件,而是要同时考虑:
- 组件 API 怎么设计
- 样式如何统一
- 主题如何切换
- 构建产物如何输出
- 不同项目如何接入
- TypeScript 类型怎么暴露
- 文档、测试、版本和发布怎么做
1.2 为什么组件库设计值得单独学
因为它是前端工程能力和 UI 设计能力的结合点。
一个成熟组件库,通常会体现:
- 代码复用能力
- API 抽象能力
- 工程化能力
- 视觉一致性能力
- 维护与演进能力
1.3 学这份笔记要抓哪几条主线
主线 1:组件库解决什么问题
- 为什么要做统一组件
- 为什么要做 Token、主题和规范
主线 2:组件库怎么设计
- 组件怎么分层
- API 怎么抽象
- 样式怎么组织
主线 3:组件库怎么交付给别人用
- 输出哪些文件
ESM / CJS / UMD / d.ts / CSS分别给谁用package.json怎么配
主线 4:组件库怎么长期维护
- 文档
- 测试
- 版本
- 发布
1.4 核心记忆主线
把组件库设计记成一句话:
组件库 = 统一 UI 规则 + 稳定组件 API + 可交付构建产物 + 可持续维护机制。
再压缩成四个词:
抽象、统一、交付、演进
2. 组件库到底在解决什么
2.1 如果没有组件库,会出现什么问题
团队没有组件库时,常见问题有:
- 每个页面都在重复写按钮、弹窗、表单
- 同样的按钮在不同页面颜色、间距、行为不一致
- 不同人写出的交互细节不统一
- 修改设计规范时需要全项目手动改
- 很难沉淀 UI 规范和业务经验
2.2 组件库的核心价值
组件库的核心价值可以分成四类:
| 价值 | 说明 |
|---|---|
| 复用 | 减少重复开发 |
| 统一 | 统一视觉和交互规范 |
| 提效 | 提高开发效率和协作效率 |
| 沉淀 | 把经验沉淀为稳定基础设施 |
2.3 组件库不只是“UI 仓库”
很多人把组件库理解成“放组件代码的地方”,这不够完整。
一个成熟组件库往往包含:
- 基础组件
- 样式系统
- 主题机制
- 图标系统
- 类型定义
- 文档站点
- 测试和发布工具链
2.4 组件库和业务组件的区别
基础组件库
适合:
- Button
- Input
- Select
- Modal
- Table
特点:
- 通用性高
- 业务耦合低
- 适合多个项目复用
业务组件库
适合:
- 商品选择器
- 权限树
- 课程卡片
- 用户面板
特点:
- 更贴近业务
- 复用范围更偏业务域
- 依赖业务模型更多
一句话区分:
基础组件库解决通用 UI,业务组件库沉淀业务场景。
2.5 面试里怎么概括组件库
可以答:
组件库本质上是把 UI、交互、样式规范和工程能力沉淀成可复用基础设施,目标是提升开发效率、统一产品体验并降低长期维护成本。
3. 组件库设计核心
这一部分最重要。真正能区分“会写组件”和“会设计组件库”的,就是这里。
3.1 组件库设计的核心目标
设计组件库时,最核心的目标通常是:
- 易用
- 一致
- 可扩展
- 可维护
- 可发布
3.2 一个好组件库最重要的五个特征
特征 1:API 稳定
组件的 props、事件、插槽、暴露方法尽量清晰稳定。
特征 2:样式一致
颜色、字号、圆角、间距、动效有统一规范。
特征 3:组合灵活
既能满足常见场景,也不至于把组件写死。
特征 4:工程可交付
能输出被项目真正消费的产物,而不是只在本地 demo 能跑。
特征 5:可持续演进
支持文档、测试、版本升级和兼容策略。
3.3 设计组件库时,最容易犯的几个错误
- 过早追求“大而全”
- API 命名不统一
- 组件耦合业务过深
- 样式无 Token 体系
- 打包产物只考虑一种场景
- 没有类型和文档
3.4 组件库设计的思维顺序
推荐按这个顺序思考:
- 这类组件解决什么问题
- 最小可用能力是什么
- 哪些能力必须内置
- 哪些能力应该交给外部定制
- 这个组件如何和其他组件协作
- 最终产物要怎么提供给使用方
3.5 设计组件时,什么时候做“能力下沉”
比如多个组件都有:
- loading 状态
- disabled 状态
- size 体系
- 主题色体系
这时就应该考虑抽象:
- 基础样式变量
- 通用 hooks
- 通用工具函数
- 基础交互层
3.6 组件库不是所有东西都要做成组件
组件库里除了组件,还会有:
- hooks
- 工具函数
- 指令
- 类型工具
- 主题 Token
所以它更像:
一套 UI 基础能力平台
3.7 一句话压缩组件库设计核心
组件库设计的关键不是组件数量,而是抽象边界、API 稳定性和交付方式。
4. 组件分层与目录结构
4.1 为什么组件库需要分层
因为如果不分层,代码很快会变得:
- 相互依赖混乱
- 公共逻辑四处复制
- 样式和逻辑耦合严重
- 打包边界不清晰
4.2 一个常见组件库分层
你可以先记住这四层:
基础能力层基础组件层复合组件层入口与导出层
4.3 基础能力层
一般包含:
- hooks
- utils
- constants
- types
- token
例如:
useControlleduseNamespaceisNumberThemeToken
4.4 基础组件层
常见有:
- Button
- Input
- Icon
- Tag
- Checkbox
这些组件通常:
- 通用性强
- 依赖少
- 是其他复合组件的积木
4.5 复合组件层
例如:
- DatePicker
- Table
- Upload
- Form
- Cascader
这些组件通常:
- 内部组合多个基础组件
- 逻辑更复杂
- API 更谨慎
4.6 入口与导出层
负责:
- 统一导出组件
- 统一导出 hooks 和类型
- 定义组件库对外 API 面
4.7 一个推荐目录结构
packages/ui/
src/
components/
button/
index.ts
button.tsx
style.css
types.ts
input/
modal/
hooks/
utils/
styles/
index.css
tokens.css
reset.css
types/
index.ts
dist/
4.8 Monorepo 下的组件库目录
如果组件库较大,常见会拆成:
packages/
components/
icons/
themes/
utils/
docs/
这样做的好处:
- 职责更清晰
- 更适合多人协作
- 更利于独立版本或按包发布
4.9 一句话压缩分层
基础能力做下沉,基础组件做复用,复合组件做组合,入口层做统一导出。
5. 组件 API 设计
API 设计是组件库最容易“看起来简单、其实最难”的部分。
5.1 组件 API 设计要解决什么
本质上是在回答:
使用方要怎么最自然地使用这个组件。
5.2 API 设计的几个核心原则
- 命名一致
- 能力最小但够用
- 默认值合理
- 扩展方式清晰
- 控制与非控制模式明确
5.3 命名为什么很重要
如果一个组件库里同时出现:
sizebtnSizetypevariant
但没有统一语义,使用者会很痛苦。
所以推荐统一:
- 外观:
variant - 尺寸:
size - 状态:
disabled、loading - 值:
value - 事件:
onChange
5.4 默认值设计为什么关键
一个好组件应该:
开箱即用
也就是说,使用者尽量只传最少参数就能得到合理结果。
5.5 控制模式与非控制模式
这是组件库面试高频点。
非受控
组件内部自己管理状态。
受控
状态完全由外部传入和控制。
例如表单组件常见设计:
<Input defaultValue="hello" />
<Input value={value} onChange={setValue} />
5.6 什么时候提供插槽或 children
如果组件内部布局需要留给使用方自由组合,就应该提供插槽能力。
例如:
- Card header
- Modal footer
- Dropdown content
5.7 什么时候提供 render props
适合:
- 高度定制渲染
- 复杂内部状态对外暴露
- 虚拟列表、表格单元格等场景
5.8 什么时候暴露实例方法
例如:
focusscrollToopenclose
只有当组件存在明显 imperative 场景时再暴露。
5.9 API 设计里最常见的错误
- props 太多
- 一个 prop 兼顾太多语义
- 受控和非受控混用不清
- 事件命名不统一
- 为了灵活把所有东西都交给使用方
5.10 一句话压缩 API 设计
组件 API 要让常见场景简单,让复杂场景可扩展,但不能失控。
6. 样式系统、主题与 Design Token
6.1 为什么组件库一定会谈样式系统
因为组件库不只是逻辑复用,更重要的是:
视觉和交互规则统一。
6.2 什么是 Design Token
Design Token 可以理解成:
把颜色、字号、间距、圆角、阴影等设计值抽象成统一变量。
例如:
:root {
--ui-color-primary: #1677ff;
--ui-radius-sm: 4px;
--ui-font-size-md: 14px;
}
6.3 为什么 Token 很重要
因为它能把:
- 视觉规范
- 组件实现
- 主题切换
连接起来。
6.4 主题系统常见做法
- CSS Variables
- Less / Sass Variables
- JS Theme Object
- Design Token 编译产物
6.5 为什么现在常说 CSS Variables
因为它更适合:
- 运行时切换主题
- 动态皮肤
- 暗黑模式
- 浏览器原生支持好
6.6 组件库样式常见策略
| 方式 | 特点 | 适合场景 |
|---|---|---|
| 全局 CSS | 简单直接 | 小型组件库 |
| CSS Modules | 避免冲突 | 中小型项目 |
| CSS-in-JS | 动态能力强 | 特定技术栈 |
| Less / Sass | 变量和预处理成熟 | 传统组件库 |
| CSS Variables + 编译样式 | 平衡灵活与性能 | 现代组件库 |
6.7 为什么要做命名空间
比如:
.ui-button {}
.ui-input {}
这样做的作用:
- 避免样式冲突
- 更利于调试
- 更适合对外发布
6.8 一句话压缩样式系统
组件库样式的关键不是“能写出来”,而是“能统一、能切主题、能长期演进”。
7. 组件库构建与输出产物
这是你特别点名的重点。组件库不是只把源码发出去,而是要输出适合不同使用场景的构建产物。
7.1 为什么组件库要构建
因为源码通常包含:
- TypeScript
- JSX / TSX
- 源样式文件
- 私有目录结构
使用者真正需要的是:
- 可直接导入的 JS
- 对应的类型文件
- 可加载的样式文件
- 明确的导出入口
7.2 组件库常见输出内容
一般会输出:
ESMCJSUMD或浏览器 bundled.tsCSS- source map
7.3 一个常见的 dist 结构
dist/
es/
index.js
button/index.js
lib/
index.js
button/index.js
types/
index.d.ts
button/index.d.ts
style.css
index.umd.js
7.4 为什么同一个组件库要输出多种格式
因为消费方环境不一样:
- 有的项目用现代 bundler
- 有的项目仍依赖 CommonJS
- 有的场景直接浏览器
<script>引入 - TypeScript 项目还要类型
7.5 构建工具常见选择
常见有:
- Rollup
- Vite library mode
- tsup
- webpack
学习阶段推荐先理解:
Rollup / Vite / tsup
因为它们更常用于组件库场景。
7.6 为什么 Rollup 常用于组件库
因为它对库构建更友好:
- 输出格式丰富
- Tree Shaking 友好
- 多入口支持清晰
- 产物更适合作为库发布
7.7 样式文件构建时常见问题
要考虑:
- CSS 是合并成一个文件,还是按组件拆分
- 是否支持按需引入样式
- Less / Sass 是否也要对外暴露源码
7.8 一句话压缩构建产物
组件库构建的目标,是把源码转成不同消费场景都能稳定接入的交付物。
8. 不同文件格式对应的使用方式
这一部分非常重要。很多人知道
ESM、CJS这些词,但不知道“为什么要发它”“谁在用它”“怎么接入它”。
8.1 ESM 是什么
ESM 即 ECMAScript Modules。
常见写法:
import { Button } from "@demo/ui";
8.2 ESM 适合什么场景
适合:
- Vite 项目
- Rollup 项目
- 现代 Webpack 项目
- 现代前端库消费场景
8.3 为什么组件库通常要输出 ESM
因为它更适合现代构建工具做:
- Tree Shaking
- 按需打包
- 更细粒度依赖分析
8.4 ESM 的典型使用方式
import { Button } from "@demo/ui";
import "@demo/ui/style.css";
如果支持按组件引入:
import Button from "@demo/ui/es/button";
import "@demo/ui/es/button/style.css";
8.5 CJS 是什么
CJS 即 CommonJS。
常见写法:
const { Button } = require("@demo/ui");
8.6 CJS 适合什么场景
适合:
- 老 Node 环境
- 某些旧构建工具
- 一些历史 SSR 场景
8.7 为什么很多组件库仍会输出 CJS
因为现实项目里还存在:
- 历史工程兼容需求
- 某些工具链仍依赖
require - 部分生态仍使用 CommonJS
8.8 UMD 是什么
UMD 可以理解成:
浏览器和多种模块系统兼容的老牌通用格式。
常见用途是:
- CDN 脚本直引
- Demo 页面
- 不经过 bundler 的场景
8.9 UMD 的典型使用方式
<link rel="stylesheet" href="https://cdn.example.com/ui/style.css" />
<script src="https://cdn.example.com/ui/index.umd.js"></script>
<script>
const Button = DemoUI.Button;
</script>
8.10 d.ts 是什么
d.ts 是 TypeScript 类型声明文件。
它的作用是:
- 提示组件 props
- 提示函数参数和返回值
- 提升 IDE 自动补全体验
8.11 d.ts 对使用方有什么价值
例如:
import { Button } from "@demo/ui";
这时 IDE 能知道:
- Button 有哪些 props
- 每个 prop 的类型是什么
- 事件签名是什么
8.12 CSS 文件输出是干什么的
CSS 文件是给使用方直接加载样式的。
典型方式:
import "@demo/ui/style.css";
8.13 为什么组件库有时会同时输出 style.css 和 es/button/style.css
这是为了兼顾两类使用方式:
- 全量引入样式
- 按需引入单个组件样式
8.14 Less / Sass 源文件要不要发布
要看你的组件库定位。
如果你希望使用方深度定制主题,可能会发布:
theme.lessvariables.scss
这样使用方可以在编译阶段覆盖变量。
8.15 Source Map 有什么用
Source Map 主要用于:
- 调试源码
- 定位报错
- 帮助库开发者和接入方排查问题
8.16 不同产物格式和使用方式总表
| 产物格式 | 作用 | 常见使用方式 | 适合场景 |
|---|---|---|---|
ESM |
现代模块产物 | import { Button } from "@demo/ui" |
现代前端项目 |
CJS |
兼容旧模块系统 | const ui = require("@demo/ui") |
历史项目、旧 Node 环境 |
UMD |
浏览器全局脚本 | <script src="..."> |
CDN 直引、Demo |
d.ts |
类型声明 | 自动被 TS 识别 | TypeScript 项目 |
CSS |
样式产物 | import "@demo/ui/style.css" |
所有前端项目 |
Less/Scss |
可编译主题变量 | @use / @import |
深度定制场景 |
8.17 一句话压缩不同文件格式
ESM 给现代工程,CJS 给兼容场景,UMD 给浏览器直引,d.ts 给类型系统,CSS 给样式加载。
9. package.json 设计与发布字段
组件库能不能被别人正确使用,很大程度取决于
package.json怎么写。
9.1 为什么 package.json 对组件库很关键
因为它在告诉使用方和构建工具:
- 入口文件在哪
- 模块格式是什么
- 类型文件在哪
- 样式入口在哪
- 哪些文件要发布
9.2 组件库最常见的几个字段
| 字段 | 作用 |
|---|---|
main |
CommonJS 入口 |
module |
ESM 入口 |
types |
类型声明入口 |
exports |
精细控制导出 |
files |
控制发布哪些文件 |
sideEffects |
帮助 Tree Shaking |
peerDependencies |
声明宿主依赖 |
9.3 main 是什么
通常指向 CommonJS 入口:
{
"main": "dist/lib/index.js"
}
9.4 module 是什么
通常指向 ESM 入口:
{
"module": "dist/es/index.js"
}
9.5 types 是什么
指定类型入口:
{
"types": "dist/types/index.d.ts"
}
9.6 exports 为什么越来越重要
因为它可以更精细地控制:
import走哪个文件require走哪个文件- 子路径导出哪些可用
- 是否对外隐藏内部文件结构
9.7 一个推荐的 exports 示例
{
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"import": "./dist/es/index.js",
"require": "./dist/lib/index.js"
},
"./style.css": "./dist/style.css",
"./button": {
"types": "./dist/types/button/index.d.ts",
"import": "./dist/es/button/index.js",
"require": "./dist/lib/button/index.js"
}
}
}
9.8 files 为什么重要
它决定发布到 npm 时,哪些内容会被带上。
例如:
{
"files": ["dist"]
}
这样可以避免把源码、测试、临时文件都发出去。
9.9 peerDependencies 为什么在组件库里很常见
例如 React 组件库通常不会自己打包 React,而是声明:
{
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
}
}
原因是:
- 避免宿主项目和组件库各自带一份 React
- 避免运行时实例不一致
9.10 sideEffects 为什么很关键
它会影响 Tree Shaking。
例如:
{
"sideEffects": [
"*.css"
]
}
这表示:
- JS 模块可以尝试摇树优化
- CSS 不能被误删
9.11 一个更完整的组件库 package.json 示例
{
"name": "@demo/ui",
"version": "1.0.0",
"main": "dist/lib/index.js",
"module": "dist/es/index.js",
"types": "dist/types/index.d.ts",
"style": "dist/style.css",
"files": ["dist"],
"sideEffects": ["*.css"],
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"exports": {
".": {
"types": "./dist/types/index.d.ts",
"import": "./dist/es/index.js",
"require": "./dist/lib/index.js"
},
"./style.css": "./dist/style.css"
}
}
9.12 一句话压缩 package.json
package.json 是组件库的交付说明书,决定别人如何找到并正确使用你的产物。
10. Tree Shaking、按需加载与包体积优化
10.1 为什么组件库要特别关注包体积
因为组件库会被很多项目依赖。
如果组件库太重,会影响:
- 业务项目打包体积
- 首屏性能
- 安装和构建速度
10.2 Tree Shaking 是什么
Tree Shaking 是构建阶段移除未使用代码的能力。
组件库想让 Tree Shaking 更好生效,通常要做到:
- 输出 ESM
- 避免无必要副作用
- 合理设置
sideEffects
10.3 什么是按需加载
按需加载可以理解成:
只引入真正用到的组件和样式,而不是整个组件库。
例如:
import Button from "@demo/ui/es/button";
import "@demo/ui/es/button/style.css";
10.4 全量引入和按需引入的区别
全量引入
import { Button, Input } from "@demo/ui";
import "@demo/ui/style.css";
适合:
- 小型项目
- 快速接入
- 组件使用较多
按需引入
import Button from "@demo/ui/es/button";
import "@demo/ui/es/button/style.css";
适合:
- 更关注包体积
- 大型项目
- 组件使用相对分散
10.5 为什么样式也要支持按需
因为如果 JS 按需了,但样式还是全量加载,优化效果会打折。
10.6 包体积优化常见手段
- ESM 输出
- 按组件拆包
- 样式按需输出
- 图标单独拆分
- 避免把宿主依赖打进库里
- 抽离共享工具
10.7 一句话压缩优化
组件库优化的核心是:让使用方只拿到真正需要的代码和样式。
11. 文档、测试、版本管理与发布
11.1 为什么组件库必须重视文档
因为组件库的用户就是“开发者”。
如果没有文档,再好的组件也很难被正确使用。
11.2 组件文档至少要包含什么
- 基本介绍
- 使用示例
- props 说明
- 事件说明
- 插槽 / children 说明
- 主题定制说明
11.3 组件库测试重点测什么
常见测试:
- 渲染测试
- 交互测试
- 快照测试
- 样式类名测试
- 无障碍测试
11.4 视觉回归为什么重要
因为组件库改动经常影响:
- 样式
- 布局
- 交互状态
所以很多团队会加入视觉回归测试。
11.5 版本管理为什么关键
因为组件库是被多个项目消费的。
一旦升级不谨慎,就会影响很多业务。
11.6 什么是语义化版本
通常是:
major.minor.patch
含义:
major:破坏性变更minor:向后兼容的新功能patch:向后兼容的问题修复
11.7 发布流程一般包含什么
- lint
- test
- build
- changelog
- version bump
- publish
11.8 一句话压缩文档和发布
组件库不是写完代码就结束,而是要让别人看得懂、用得稳、升得动。
12. 实战项目设计建议
12.1 一个适合起步的组件库范围
建议先做最基础的一组:
- Button
- Input
- Icon
- Modal
- Message
- Tabs
12.2 第一阶段应该先做什么
先做:
- 命名规范
- Token 系统
- 基础目录结构
- 构建产物
- 文档基础设施
不要一开始就先冲复杂组件。
12.3 一个真实项目的设计主线
推荐按这个顺序:
- 定义设计规范
- 定义 Token
- 设计 Button / Input 等基础组件
- 设计库入口和构建方案
- 输出 ESM / CJS / d.ts / CSS
- 写文档和示例
- 发布 npm 包
12.4 如果是 React 组件库,要重点注意什么
peerDependencies中声明 React- hooks 抽象
- ref 暴露
- controlled/uncontrolled 模式
12.5 如果是 Vue 组件库,要重点注意什么
- 插槽设计
install机制- 全局注册与按需注册
- 组合式 API 与类型暴露
12.6 一句话压缩实战建议
先做规范和构建底座,再做组件;先做基础组件,再做复杂组件。
13. 高频面试题
13.1 什么是前端组件库
可以答:
组件库是把通用 UI、交互规则、样式规范和工程能力沉淀成可复用基础设施的一套系统。
13.2 为什么要做组件库
可以答:
主要是为了提升复用效率、统一视觉和交互规范、降低重复开发成本,并把团队经验沉淀下来。
13.3 组件库设计最核心的点是什么
可以答:
核心在于抽象边界、API 稳定性、样式和主题体系、构建产物设计以及长期维护能力。
13.4 组件库和业务组件有什么区别
可以答:
基础组件库偏通用、低耦合,适合多项目复用;业务组件库更贴近具体业务场景,复用范围更偏业务域。
13.5 为什么组件库通常要输出 ESM 和 CJS
可以答:
因为不同消费环境不同,现代 bundler 更适合用 ESM 做 Tree Shaking,历史项目或旧 Node 场景仍可能依赖 CommonJS。
13.6 ESM、CJS、UMD 分别适合什么场景
可以答:
- ESM:现代工程化项目
- CJS:历史兼容场景
- UMD:浏览器
<script>直引和 Demo 场景
13.7 d.ts 文件是做什么的
可以答:
它是 TypeScript 类型声明文件,用于给使用方提供 props、事件和 API 的类型提示。
13.8 main、module、types 分别是什么
可以答:
main:CommonJS 入口module:ESM 入口types:类型声明入口
13.9 exports 字段有什么用
可以答:
它用于更精细地控制包对外暴露的入口,可以分别定义 import、require、types 等不同条件下的导出路径。
13.10 为什么 peerDependencies 对组件库很重要
可以答:
因为组件库往往依赖宿主框架,比如 React/Vue,但又不希望把框架自身打进包里,否则容易产生多份实例和运行时问题。
13.11 为什么要设置 sideEffects
可以答:
它用于帮助构建工具做 Tree Shaking,并避免像 CSS 这类有副作用的文件被错误删除。
13.12 按需加载怎么实现
可以答:
通常是组件库按组件拆分产物,并暴露子路径入口,同时样式也支持按组件引入,这样业务项目只会加载实际使用的组件和样式。
13.13 组件库怎么做主题定制
可以答:
一般通过 Design Token、CSS Variables、预处理变量或 JS Theme Object 来实现统一主题和动态皮肤切换。
13.14 如果让你设计一个组件库,你会怎么做
推荐答法:
- 先梳理设计规范和 Token
- 设计基础目录和分层
- 先做基础组件
- 设计统一 API 风格
- 输出 ESM / CJS / d.ts / CSS
- 补文档、测试和发布流程
14. 更好记的学习方法
14.1 用一句话记住组件库
组件库不是几个组件,而是一套可复用的 UI 基础设施。
14.2 用“三问法”来记
每学一个点都问自己:
- 它解决什么问题
- 它对使用方有什么价值
- 它最终怎么交付出去
14.3 用“设计到交付”链路记忆
把组件库压成这条链:
设计规范 -> Token -> 组件 API -> 样式系统 -> 构建产物 -> package.json -> 发布
14.4 用对比法记
对比 1:基础组件库 vs 业务组件库
- 基础组件库:通用
- 业务组件库:业务场景化
对比 2:ESM vs CJS vs UMD
- ESM:现代工程
- CJS:兼容旧系统
- UMD:浏览器直引
对比 3:全量引入 vs 按需引入
- 全量引入:方便
- 按需引入:更省包体积
14.5 用口诀记
先统一规范,再统一组件Token 管设计,API 管使用,构建管交付ESM 给现代工程,CJS 给兼容场景,UMD 给浏览器直引types 管提示,CSS 管样式,exports 管入口
14.6 最有效的记忆方式
你最好能做到:
- 画出组件库分层结构
- 手写一个
package.json导出配置 - 说清 ESM/CJS/UMD 的使用区别
- 讲一个从 Button 到发布 npm 包的完整链路
15. 8 小时学习节奏建议
第 1 小时:建立总框架
目标:
- 理解组件库到底在解决什么
- 区分基础组件库和业务组件库
- 记住“抽象、统一、交付、演进”
第 2-3 小时:集中突破组件设计
重点:
- 分层设计
- API 设计
- 控制与非控制模式
- 样式命名和主题体系
输出目标:
能说清一个 Button 组件为什么这样设计
第 4-5 小时:集中突破构建产物和输出格式
重点:
- ESM
- CJS
- UMD
- d.ts
- CSS
- exports / main / module / types
输出目标:
能讲清不同产物格式对应的使用方式
第 6 小时:包体积与按需加载
重点:
- Tree Shaking
sideEffects- 按组件拆包
- 样式按需引入
第 7 小时:文档、测试、版本和发布
重点:
- 文档结构
- 测试策略
- 语义化版本
- 发布流程
第 8 小时:冲刺复盘
做三件事:
- 默写一页总结
- 回答面试题
- 用 5 分钟讲一遍“如何设计一个组件库”
16. 一页速记总结
16.1 组件库核心
组件库 = 统一 UI 规范 + 可复用组件 + 可交付产物 + 可持续维护机制
16.2 设计核心
- 抽象边界
- API 稳定
- 样式统一
- 主题可扩展
16.3 常见产物
ESMCJSUMDd.tsCSS
16.4 使用方式
- ESM:
import - CJS:
require - UMD:
script - d.ts:TS 自动识别
- CSS:样式直接导入
16.5 package.json 核心字段
mainmoduletypesexportsfilessideEffectspeerDependencies
16.6 优化核心
- 输出 ESM
- 正确配置
sideEffects - 支持按需引入
- 样式按需拆分
16.7 最重要的一句话
组件库真正难的不是“写组件”,而是“把组件做成稳定、统一、可交付、可演进的产品”。
17. 背诵口诀
17.1 总口诀
先做规范,再做组件;先做 API,再做构建;先能使用,再谈扩展。
17.2 产物口诀
ESM 给现代,CJS 给兼容,UMD 给浏览器,types 给提示,CSS 给样式。
17.3 设计口诀
Token 定视觉,API 定交互,exports 定入口。
17.4 工程口诀
组件要分层,样式要统一,打包要多格式,发布要可维护。
17.5 面试口诀
回答组件库问题时,尽量按这个顺序说:
- 它解决什么问题
- 组件怎么分层和抽象
- API 和主题怎么设计
- 产物怎么输出
- 如何发布和维护
只要你按这个顺序说,答案通常会比较完整。
附:你可以怎么用这份笔记
第一次学习
重点看:
- 组件库到底在解决什么
- 组件库设计核心
- 组件分层与 API 设计
第二次复习
重点看:
- 样式系统与 Token
- 构建与输出产物
package.json设计
第三次冲刺
只看:
- 不同文件格式对应的使用方式
- 一页速记总结
- 高频面试题
如果你能把这三部分不看笔记讲出来,说明你已经真正掌握了组件库设计这块内容。