企业级设计系统的 Token 治理:权限、审批与变更追溯

发布时间:2026/7/22 0:18:28
企业级设计系统的 Token 治理:权限、审批与变更追溯 企业级设计系统的 Token 治理权限、审批与变更追溯一、引言设计系统不是一张色彩表而是一面照出团队协作真相的镜子在设计系统的世界里有一个残酷的真相99% 的设计系统最终都会走向Token 腐败。那些被精心定义的颜色值、间距值、字体大小会在产品迭代的漫长岁月里被一小撮紧急需求逐一击穿——这个页面太紧急了先用硬编码的颜色吧后面再改、产品说这个按钮必须再大 2px来不及走 Token 变更流程了。我在上一家公司接手设计系统的维护工作时打开 Figma Token 面板看到的景象让我倒吸一口凉气一套本应只有 56 个颜色 Token 的设计系统蔓延出了 247 个变体。blue-6和blue-6-dark的区别只是前者透明度是 0.95 而后者是 0.92。团队里 12 个前端工程师每个人都顺手往设计系统里塞了几个自己需要的 Token而且没有任何人记得为什么需要这些 Token。这不是个别现象。在不引入治理机制的设计系统中Token 数量的增长速度与开发人员数量的平方成正比——我称之为Token 膨胀定律。每个新加入的工程师都会发现已有的 Token 满足不了我的需求然后创造出新的变体而这些变体又成为下一个工程师感到不满意的起点。Token 治理不是要限制创造力而是要保护共识。设计系统的本质是团队对什么是好的设计达成的共识而 Token 是这个共识的物化载体。当 Token 失去治理共识就开始瓦解当共识瓦解设计系统就只剩下一个漂亮的 Figma 文件和一堆仅供参考的变量名。本篇文章聚焦 Token 治理的三个核心支柱权限控制、审批流程和变更追溯。这不是一篇关于如何定义 Token的文章而是一篇关于如何保护 Token 不被腐化的文章。在一个 50 人以上的前端团队中这三者的缺失几乎必然导致设计系统的崩塌。二、底层机制与原理深度剖析Token 治理的本质是一个变更管理问题。每一次 Token 的增删改都是一次对设计共识的修改。当修改是随意的、无记录的、不可追溯的设计系统就会从单一事实源蜕变为混乱的意见集合。权限模型设计Token 治理的权限模型不能是简单的管理员-普通用户二分类。在一个成熟的设计系统中权限应该是基于角色的、可配置的多层级模型Consumer消费者只能读取和使用已发布的 Token不能做任何修改。这是最大范围的权限组覆盖全团队所有前端和设计师。Contributor贡献者可以提交 Token 变更提案但不能直接修改正式 Token。提案需要经过维护者的审批才能生效。Maintainer维护者可以审批和合并 Token 变更负责维护设计系统的一致性。通常由资深设计师或前端架构师担任。Owner管理员拥有最高权限可以修改权限配置、处理紧急情况。这一角色应严格控制在 1-2 人。审批流程的设计哲学Token 审批流程的核心挑战在于既要防止腐败又不能成为阻塞。如果每次 Token 变更都需要三天才能通过审批最终的结果是开发团队绕过流程——直接硬编码。我推荐的方案是分级审批补丁级变更PatchToken 值微调如颜色亮度±3%以内自动通过事后追溯。次要变更Minor新增一个语义 Token如新增一个警示性色彩需要 1 个 Maintainer 审批。重大变更Major修改已有全局 Token、删除 Token、重构 Token 层级结构需要 2 个 Maintainer 审批 影响面分析通过。三、生产级代码实现/** * Token 治理系统的核心数据模型 * * 设计哲学 * - 每个 Token 都有独立版本号支持渐进式升级 * - 变更提案不可修改追加而非覆盖保证审计完整性 * - 语义化命名不依赖视觉值方便深色模式等主题切换 */ /** Token 的基本单元 */ interface DesignToken { /** 唯一命名如 color.primary.500 */ name: string; /** Token 分组如 color, spacing, typography */ group: string; /** 当前生效的值 */ value: string; /** 值的类型决定 UI 编辑器的渲染方式 */ type: color | dimension | number | string | gradient | shadow; /** 语义说明帮助贡献者理解 Token 的用途 */ description: string; /** 当前版本号 */ version: number; /** 状态 */ status: active | deprecated | draft; /** 废弃时指向的替代 Token */ replacedBy?: string; } /** Token 变更提案 */ interface TokenChangeProposal { /** 提案唯一 ID */ id: string; /** 提案标题需简明描述变更意图 */ title: string; /** 变更类型 */ type: create | update | deprecate | delete; /** 目标 Token 名称 */ targetToken: string; /** 变更前的值update/deprecate/delete 时必填 */ oldValue?: string; /** 变更后的值create/update 时必填 */ newValue: string; /** 变更原因说明 */ reason: string; /** 关联需求单或设计稿链接 */ reference?: string; /** 提案人 */ proposer: string; /** 当前的审批状态 */ approvalStatus: pending | approved | rejected; /** 审批意见列表 */ approvals: ApprovalRecord[]; /** 创建时间 */ createdAt: Date; } /** 审批记录 */ interface ApprovalRecord { /** 审批人 */ reviewer: string; /** 审批意见 */ comment: string; /** 审批结果 */ decision: approve | reject; /** 审批时间 */ timestamp: Date; } /** * Token 治理引擎 * 负责权限验证、合规检查和变更追溯 */ class TokenGovernanceEngine { /** Token 存储 */ private tokens: Mapstring, DesignToken new Map(); /** 变更历史不可变日志 */ private changeLog: TokenChangeProposal[] []; /** 用户角色映射 */ private roles: Mapstring, string new Map(); /** * 提交 Token 变更提案 * * param proposal 变更提案 * param user 当前操作用户 * throws 用户没有提案权限时抛出错误 */ submitProposal(proposal: TokenChangeProposal, user: string): void { // 权限验证 const role this.roles.get(user); if (!role || role consumer) { throw new Error(用户 ${user} 无 Token 变更权限当前角色: ${role || 未分配}); } // 自动合规检查 const violations this.validateProposal(proposal); if (violations.length 0) { // 合规检查不通过自动驳回 proposal.approvalStatus rejected; proposal.approvals.push({ reviewer: system, comment: 自动合规检查未通过: ${violations.join(; )}, decision: reject, timestamp: new Date() }); this.changeLog.push(proposal); throw new Error(Token 变更合规检查失败: ${violations.join(; )}); } // 记录提案 this.changeLog.push(proposal); } /** * Token 合规验证 * * 检查项包括 * 1. 命名规范必须符合 group.category.variant 格式 * 2. 值合法性颜色值必须是有效的 hex/rgba * 3. 唯一性同组内 Token 名称不能重复 * 4. 废弃保护正在被其他 Token 引用的 Token 不可删除 */ private validateProposal(proposal: TokenChangeProposal): string[] { const violations: string[] []; // 命名格式检查 const namingPattern /^[a-z](\.[a-z])$/; if (!namingPattern.test(proposal.targetToken)) { violations.push( Token 命名 ${proposal.targetToken} 不符合规范应为 group.category.variant 格式 ); } // 颜色值合法性检查 if (proposal.targetToken.includes(color)) { const colorPattern /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/; if (proposal.newValue !colorPattern.test(proposal.newValue)) { violations.push( 颜色 Token 值 ${proposal.newValue} 不符合 hex 格式应为 #RRGGBB 或 #RRGGBBAA ); } } // 同组名称唯一性检查 if (proposal.type create) { const existingNames Array.from(this.tokens.keys()); if (existingNames.includes(proposal.targetToken)) { violations.push(Token ${proposal.targetToken} 已存在不能重复创建); } } // 废弃保护检查 if (proposal.type delete) { const dependents Array.from(this.tokens.values()) .filter(t t.replacedBy proposal.targetToken); if (dependents.length 0) { violations.push( Token ${proposal.targetToken} 被 ${dependents.length} 个 Token 引用不可删除 ); } } return violations; } /** * 影响面分析 * 扫描代码库中使用了被修改 Token 的所有文件 * * 生产环境中应接入 AST 解析工具 * 这里用简化的字符串匹配做演示 */ analyzeImpact(tokenName: string, files: string[]): ImpactReport { const affectedFiles: string[] []; const tokenVar var(--${tokenName}); for (const file of files) { // 实际项目中应使用正则匹配 CSS 变量引用 if (file.includes(tokenVar)) { affectedFiles.push(file); } } return { token: tokenName, affectedFiles, totalAffected: affectedFiles.length, // 根据影响范围决定审批级别 requiredApprovalLevel: affectedFiles.length 10 ? major : minor }; } } /** 影响面分析报告 */ interface ImpactReport { token: string; affectedFiles: string[]; totalAffected: number; requiredApprovalLevel: minor | major; }四、边界分析与架构权衡关键缺点流程成本过高。审批流程最直接的代价是延迟。在一个两周发版节奏的团队中Token 变更可能需要等待一周才能通过审批这会倒逼开发者绕过流程硬编码反而加剧问题。小型团队不适用。当团队人数低于 5 人时Token 治理的收益远低于其成本。5 人以下的团队口头沟通和 Code Review 足够覆盖 Token 的一致性需求。工具链依赖重。一个完善的 Token 治理系统需要 Figma 插件设计师端、CLI 工具开发者端、CI/CD 集成自动化检查和文档站点查找和预览这些工具链的搭建和维护成本不容小觑。Token 粒度困境。过于细致的 Token 治理会让创建新 Token变得过于困难导致设计师和开发者倾向于复用不恰当的 Token比如把成功色用在通过标签上产生语义错误。适用边界适用团队不适用团队10 人以上前端团队5 人以下小型团队多产品线的平台型产品单一产品快速迭代期有专职设计系统维护者全栈开发、设计师兼任前端对外交付的标准化产品内部工具、一次性项目五、总结设计系统的 Token 治理不是技术问题而是组织问题。技术可以帮你实现权限控制、自动化检查和变更追溯但真正的挑战在于让团队中的每一个人都认同遵守规范比方便自己更重要。我的实践建议是治理粒度从粗到细。不要一开始就设计一个完美的、细粒度的 Token 治理流程。从颜色 Token 不能硬编码这一条规则开始当团队形成习惯后再逐步扩展到间距、字体、阴影等领域。治理流程的效率也很重要——如果一个 Token 变更需要 3 天才能审批通过你就不是在治理而是在制造障碍。最后也是最重要的一点Token 治理的目的不是建立一个封闭的围墙而是构建一个安全的容器。容器让创造变得安全围墙让创造变得不可能。选择做容器不要做围墙。作者李慕杰Leo / 8limujie一个在设计系统的 Token 丛林里为秩序而战的前端匠人