Meta Description:本文从真实企业项目角度,分析组件库为什么容易失控,以及如何从 Button、Design Token、主题系统、按需加载、Monorepo 和 Design System 等方面设计可长期维护的企业级组件库。
Slug:enterprise-component-library-design-system
前言
很多团队在项目发展到一定阶段后,都会开始思考一个问题:
要不要做自己的组件库?
刚开始,这个想法通常很简单。
项目里有很多重复的 Button、Input、Table、Modal,每个业务线都在重复造轮子。于是团队决定把这些公共组件抽出来,做成一个内部组件库。
听起来非常合理。
但真实情况往往是:
组件库刚开始很好用,半年后开始变重,一年后开始没人敢改,两年后业务团队宁愿自己重新写,也不愿意使用组件库。
为什么?
因为很多团队做的不是组件库,而是“公共代码仓库”。
真正的企业级组件库,不只是把几个组件放在一起,而是一套围绕设计规范、交互规范、工程规范和长期维护机制构建的系统。
它最终应该演进成 Design System,而不是停留在 Button、Input、Table 的集合。
为什么很多公司的组件库最后都会失控?
最常见的情况是:
项目 A 需要一个红色按钮,于是写了 RedButton。
项目 B 需要一个带图标的按钮,于是写了 IconButton。
项目 C 需要一个提交按钮,于是写了 SubmitButton。
项目 D 觉得原来的按钮不好用,又写了 NewButton。
几年后,项目里可能出现:
Button
BaseButton
CommonButton
PrimaryButton
SubmitButton
IconButton
ButtonNew
ButtonV2
这些组件看起来都是按钮,但 API 不统一,样式不统一,交互不统一,维护者也不知道哪个还在使用。
这就是组件库失控的开始。
失控的根本原因不是组件太多,而是缺少统一抽象。
一个企业级组件库应该回答的问题不是:
我要不要写一个 Button?
而是:
按钮在整个产品体系中应该有哪些状态、哪些尺寸、哪些主题、哪些交互规则、哪些可扩展能力?
Button 不是简单的按钮
很多人低估了 Button 的复杂度。
一个真正可用的 Button,通常至少要考虑:
类型:primary、secondary、danger、text、link
尺寸:small、medium、large
状态:normal、hover、active、focus、disabled、loading
图标:左图标、右图标、纯图标按钮
行为:submit、reset、button
无障碍:键盘访问、aria 属性、focus 样式
主题:亮色模式、暗色模式、品牌主题
如果这些能力一开始没有规划好,后期就会不断通过新增组件来补丁式扩展。
例如,最开始只有 PrimaryButton。
后来需要危险操作按钮,就加 DangerButton。
后来需要 loading,又写 LoadingButton。
这看似解决了问题,实际上是在制造长期债务。
更好的方式是通过统一 API 设计:
Button 组件本身支持 type、size、loading、disabled、icon、block 等属性。
这样业务方只需要组合能力,而不是不断请求新增组件。
组件库的核心不是组件,而是规则
一个成熟的组件库,不应该只是 packages/button、packages/input、packages/table。
它更重要的是统一规则。
例如:
颜色怎么定义?
间距怎么定义?
圆角怎么定义?
字号怎么定义?
阴影怎么定义?
按钮高度为什么是 32px、40px、48px?
表单错误提示应该出现在哪里?
Modal 点击遮罩是否关闭?
这些规则如果不统一,组件再多也只是表面统一。
真正让组件库长期可维护的是规则,而不是组件数量。
这也是为什么很多成熟团队会从 Component Library 逐渐走向 Design System。
Design Token 为什么重要?
Design Token 可以理解为设计系统中的“变量”。
例如:
color-primary
color-danger
font-size-sm
font-size-md
radius-md
spacing-lg
shadow-card
以前很多项目会直接写:
颜色:#1677ff
字号:14px
间距:16px
圆角:6px
这样写的问题是,一旦品牌色变化,或者要支持暗黑模式,就需要全局搜索替换,非常危险。
使用 Design Token 后,组件不直接依赖具体值,而是依赖语义变量。
例如:
按钮主色使用 color-primary。
错误状态使用 color-danger。
卡片圆角使用 radius-md。
未来无论品牌升级还是暗黑模式,都只需要修改 Token,而不是修改每个组件。
这也是企业级组件库从“可用”走向“可维护”的关键一步。
API 设计比组件实现更重要
很多团队做组件库时,太关注组件内部实现,忽略了 API 设计。
但对于业务开发者来说,组件库好不好用,第一感受来自 API。
一个好的组件 API 应该满足几个特点:
直观
稳定
可组合
不暴露内部细节
例如 Button:
不要设计成:
isPrimary
isDanger
isSmall
isLarge
isLoading
更推荐设计成:
type
size
loading
disabled
icon
这样随着能力扩展,API 仍然保持清晰。
组件库最怕的是为了满足某个业务临时增加一个很具体的属性。
例如:
showSpecialMarketingStyle
enableNewYearTheme
这些属性一旦进入组件库,就会污染公共组件。
更好的做法是通过主题、插槽、扩展样式或业务层封装解决,而不是把业务规则写进基础组件。
什么时候应该做组件库?
不是所有团队都应该一开始就做组件库。
如果项目只有三五个页面,团队只有一两个人,业务还没有稳定,过早抽象组件库反而会拖慢开发。
更适合开始建设组件库的时机是:
多个项目开始重复实现相同组件
多个团队开始出现视觉和交互不一致
业务已经相对稳定
设计规范已经初步成型
有专人或固定团队维护
如果没有维护人,组件库很快会变成没人负责的公共仓库。
组件库不是一次性项目,而是长期工程。
Monorepo 为什么适合组件库?
组件库通常包含多个包:
button
input
table
form
theme
icons
utils
docs
如果全部放在一个普通项目里,版本管理和依赖管理会越来越复杂。
Monorepo 可以把多个包放在同一个仓库中统一管理。
常见结构:
packages/button
packages/input
packages/theme
packages/icons
packages/utils
docs
这样既可以统一开发,又可以独立发布。
例如只修改 Button,不一定要发布整个组件库。
对于企业级组件库,Monorepo 几乎是更合理的组织方式。
按需加载与 Tree Shaking
组件库如果全部打包进业务项目,会导致体积过大。
一个后台系统可能只用到了 Button、Input、Table,却把整个组件库都打进去了。
这对性能非常不友好。
因此组件库需要支持:
按需加载
Tree Shaking
ES Module 输出
样式按需引入
自动导入
这也是为什么现代组件库通常会提供多种构建产物。
例如:
ESM 给现代构建工具使用。
CJS 给部分 Node 环境使用。
类型声明给 TypeScript 使用。
样式文件支持按需引入。
组件库的工程化能力,决定了它能否真正服务大型项目。
暗黑模式不是换一套颜色
很多团队以为暗黑模式就是把白色换成黑色。
实际上远不止如此。
暗黑模式需要考虑:
文字对比度
边框颜色
阴影是否仍然有效
禁用状态是否清晰
危险色是否过亮
hover 和 active 是否可见
如果组件库一开始没有 Token 系统,后期支持暗黑模式会非常痛苦。
因此,暗黑模式最好从 Design Token 层设计,而不是组件层硬改。
文档是组件库的一部分
很多内部组件库失败,不是因为组件不好,而是因为没人知道怎么用。
文档应该包含:
组件说明
基础用法
不同状态
API 表格
最佳实践
不推荐用法
设计规范说明
更新日志
文档不是附属品,而是组件库产品体验的一部分。
如果业务开发者每次使用组件都要问维护者,这个组件库就还不成熟。
组件测试不能省略
企业级组件库必须有测试。
至少应该包含:
单元测试
交互测试
视觉回归测试
构建测试
类型测试
尤其是基础组件,一旦出现问题,会影响大量业务项目。
例如 Button 的 disabled 行为异常,可能影响所有提交表单。
组件库越底层,测试越重要。
从组件库到 Design System
组件库解决的是开发效率问题。
Design System 解决的是产品一致性问题。
组件库关注:
组件如何实现
组件如何使用
组件如何发布
Design System 还要关注:
品牌规范
设计语言
交互规则
内容规范
无障碍体验
跨平台一致性
所以,企业最终真正需要的不是一个组件仓库,而是一套 Design System。
组件只是 Design System 的代码表达。
总结
企业级组件库不是把 Button、Input、Table 抽出来这么简单。
它涉及设计规范、API 设计、Token 系统、主题能力、工程构建、文档、测试、版本管理和团队协作。
很多组件库失败,不是技术不够,而是缺少长期维护思维。
如果只是为了减少重复代码,可以先做公共组件。
如果希望支撑多个项目、多个团队、多个产品线,就必须从一开始按照 Design System 的方向设计。
一个好的组件库,最终不只是让开发更快,而是让整个产品体系更加统一、稳定和可持续。
X记录空间