Design Token 从设计变量到多端代码交付手册
从一个看似简单的蓝色漂移事故开始
设计师把品牌主色从旧蓝改成新蓝,Web 开发者修改了 CSS,Android 仍在使用资源文件里的旧值,iOS 则从一个 Swift 常量读取更早的颜色。两周后,深色模式新增了另一组背景色:设计稿正确,组件库 Storybook 正确,业务应用却因为覆盖顺序继续显示旧色。团队在群里传递色值、截图和变量名,每个人都完成了自己的修改,但没有人能回答三个问题:哪个文件是源,哪些平台产物来自同一次构建,旧变量何时才可以删除。
Design Token 解决的不是“少写几个颜色值”,而是让设计决策成为有类型、有名字、有引用关系、可转换、可审查和可回滚的数据。它不能替代设计评审,也不能保证组件自动正确;它把原本散落在设计文件、代码常量和文档中的决定收敛为一条可验证的交付链。
一条健康链路应当是:人维护规范化 token 源文件,构建工具解析类型与 alias,按平台规则生成 CSS、Android XML 和 Swift 等产物,组件消费生成物,CI 再证明生成物与源文件一致。Figma Variables 是设计侧的编辑和消费界面之一,不应在没有同步协议时同时成为第二个可随意修改的真源。
先把 token、变量和样式分清
一个 token 至少有名称、类型和值。生产体系通常还需要描述、弃用标记、主题或平台元数据。常见类型包括颜色、尺寸、数字、时长、字体、描边、阴影和排版组合。类型不是给文档看的标签,它决定转换器能否把 16px 变成 Web 的 1rem、Android 的 16dp,以及能否拒绝把颜色误传给间距属性。
Figma 的变量模型提供 Color、Number、String 和 Boolean 四类变量,并通过 collection、group、mode 与 alias 组织值。Figma Variables 概览明确说明,alias 只能引用同类型变量;mode 则为同一变量保存不同上下文的值。样式与变量并不等价:变量适合保存原子值和多 mode 值,样式适合表达阴影、排版等复合属性。把一个 text style 误当成单个 token,会在导出时丢失字重、行高或字族之间的组合约束。
更重要的是分层。名称里应表达决策语义,而不是只表达当前值:
primitive.color.blue.600 = #2563eb
primitive.space.4 = 16px
semantic.color.action.primary = {primitive.color.blue.600}
semantic.color.text.default = {primitive.color.gray.900}
semantic.space.page.gutter = {primitive.space.6}
component.button.primary.bg = {semantic.color.action.primary}
component.button.padding.inline = {semantic.space.control.md}Primitive 是有限的原始尺度,允许描述色阶或尺寸刻度;semantic 表达“它为什么存在”,例如默认文字、危险操作和页面间距;component token 只在组件确实需要稳定覆盖点时出现。业务组件直接引用 blue.600,品牌换色就会变成全库搜索;所有属性都创建 component token,又会让变量数量爆炸。通常让页面与通用组件优先消费 semantic token,只有组件存在独立生命周期、主题变体或兼容要求时才增加 component 层。
命名需要满足最弱目标平台。统一使用小写英文段和点分路径作为源名称,生成阶段再转为 --color-action-primary、color_action_primary 或 ColorActionPrimary。不要同时存在 gray、grey、Gray,也不要把主题写入语义名,例如 text-dark-white;主题属于 mode,语义仍是 text.default。名称一旦进入公共组件 API,就与函数名一样需要版本治理。
建立一个可以从零跑通的转换项目
Style Dictionary 是一个 token 构建系统。它读取 token 数据,按目标平台依次执行 name、value 和 attribute transform,再用 format 输出文件。安装说明建议把它作为开发依赖安装;配置文档说明 source 决定输入,platforms 定义目标,buildPath 与 files 决定输出位置。下面的配置按 Style Dictionary 5.5.0 的 ESM CLI 编写,运行时基线为 Node.js 22 或更高版本;团队若锁定其他发行线,必须让 lockfile、Node 版本和配置一起升级,不要依赖全局安装或用 --force 绕过基线。
在一个空目录中初始化项目:
node --version
npm view style-dictionary version engines --json
mkdir token-lab
cd token-lab
npm init -y
npm install -D style-dictionary
mkdir tokens先比较本机 Node 版本与 registry 返回的 engines.node。Style Dictionary 的运行时基线会随发行线升级,不满足时应先切换团队约定的 Node 版本,不能用 --force 绕过。把 Node 基线写入 .nvmrc、Volta 或 CI 运行时配置,安装成功后再用 npx style-dictionary --version 记录实际解析版本。
把 package.json 调整为 ESM,并固定可审查的命令:
{
"name": "token-lab",
"private": true,
"type": "module",
"scripts": {
"tokens:build": "style-dictionary build --config sd.config.js",
"tokens:clean": "style-dictionary clean --config sd.config.js"
},
"devDependencies": {
"style-dictionary": "5.5.0"
}
}实际仓库应提交 package-lock.json,并由依赖更新流程提出升级;构建机使用 npm ci,这样开发机与 CI 都从锁文件得到同一依赖图。升级前重新运行 npm view style-dictionary version engines --json 和 npx style-dictionary --version,把 Node、Style Dictionary 和生成物快照作为同一变更审查。
新建 tokens/core.json。这里使用 Style Dictionary 可直接处理的 token 对象,同时保留 DTCG 的 $type、$value 和花括号 alias:
{
"primitive": {
"color": {
"$type": "color",
"blue": {
"600": { "$value": { "colorSpace": "srgb", "components": [0.145, 0.388, 0.922], "hex": "#2563eb" } },
"700": { "$value": { "colorSpace": "srgb", "components": [0.114, 0.306, 0.847], "hex": "#1d4ed8" } }
},
"neutral": {
"0": { "$value": { "colorSpace": "srgb", "components": [1, 1, 1], "hex": "#ffffff" } },
"950": { "$value": { "colorSpace": "srgb", "components": [0.039, 0.039, 0.039], "hex": "#0a0a0a" } }
}
},
"space": {
"$type": "dimension",
"2": { "$value": { "value": 0.5, "unit": "rem" } },
"4": { "$value": { "value": 1, "unit": "rem" } }
}
},
"semantic": {
"color": {
"$type": "color",
"action": {
"primary": { "$value": "{primitive.color.blue.600}" },
"primaryHover": { "$value": "{primitive.color.blue.700}" }
},
"surface": {
"default": { "$value": "{primitive.color.neutral.0}" }
},
"text": {
"default": { "$value": "{primitive.color.neutral.950}" }
}
},
"space": {
"$type": "dimension",
"control": {
"inline": { "$value": "{primitive.space.4}" },
"gap": { "$value": "{primitive.space.2}" }
}
}
}
}再创建 sd.config.js:
export default {
source: ['tokens/**/*.json'],
usesDtcg: true,
platforms: {
css: {
transformGroup: 'css',
buildPath: 'build/css/',
files: [
{
destination: 'tokens.css',
format: 'css/variables',
options: { outputReferences: true, showFileHeader: false }
}
]
},
android: {
transformGroup: 'android',
buildPath: 'build/android/',
files: [
{
destination: 'colors.xml',
format: 'android/colors',
filter: { '$type': 'color' },
options: { showFileHeader: false }
},
{
destination: 'dimens.xml',
format: 'android/dimens',
filter: { '$type': 'dimension' },
options: { showFileHeader: false }
}
]
},
ios: {
transformGroup: 'ios-swift',
buildPath: 'build/ios/',
files: [
{
destination: 'DesignTokens.swift',
format: 'ios-swift/class.swift',
options: { className: 'DesignTokens', showFileHeader: false }
}
]
}
}
};运行构建:
npm run tokens:build
find build -type f -maxdepth 3 -printWindows PowerShell 可以用 Get-ChildItem build -Recurse -File 查看结果。成功时应看到 CSS、Android 和 iOS 目录下的生成文件,build/css/tokens.css 中应出现 --semantic-color-action-primary,Android 间距应以 dp 输出,Swift 间距应以点值输出。示例关闭自动文件头,是为了避免构建时间进入生成物并制造无意义 diff;来源、工具版本和摘要应由制品元数据记录。若配置文件仍按 CommonJS 编写、package.json 又启用了 ESM,常见证据是 module is not defined 或配置无法加载;若 alias 路径拼错,构建会报告引用无法解析,而不是安静地输出字符串。
这里的 Android 示例把颜色与尺寸交给不同 format,并用 DTCG 的 $type 过滤;否则新增复合 token 后可能生成非法资源。这个例子特意把规范化 dimension 写成 rem:Style Dictionary 的 Android remToDp 和 Swift remToCGFloat 会按默认基准换算,若把 { "value": 16, "unit": "px" } 直接交给它们,16 可能被当成 rem 而生成 256dp 或 CGFloat(256)。若团队以 px 为真源,应去掉会缩放的 transform,改用只附加 dp 或点值的自定义 transform,并为 px/rem、负值、小数和 alias 添加测试。Style Dictionary 的转换机制按顺序工作,并且每个平台从同一份输入开始,平台转换不会反向污染源数据。
用正反实验证明链路不是“能生成就算完成”
先做一个正向实验。把 primitive.color.blue.600 改为 #1e40af,重新运行构建并检查差异:
npm run tokens:build
git diff -- build/预期结果是三个平台中引用主色的产物都发生可解释变化,而间距、文字色和无关 token 不变。若只有 CSS 变化,说明其他平台的 filter、source 或输出路径有误;若几十个无关名称同时变化,通常是 name transform、排序或工具版本发生了漂移。不要在这种 diff 上直接点通过。
反向实验一是制造断链。临时把 semantic alias 改成不存在的 {primitive.color.blue.999}:
npm run tokens:build合格结果是命令非零退出并指出无法解析的引用。若构建成功且产物中保留花括号字符串,说明解析器没有按 DTCG token 读取该文件,或者自定义 format 绕开了引用解析。恢复名称后再次构建,确认错误消失。
反向实验二是制造非法单位:把间距改为 { "value": 16, "unit": "s" }。DTCG 版本 2025.10 的 dimension 只允许 px 或 rem,因此项目应在构建前用规范对应的 JSON Schema 或等价 lint 拒绝它;不要把 16s 当作当前 DTCG dimension 的示例。针对用途的单位白名单仍然需要额外规则,例如字体 token 才能进入 sp 变换。CI 必须让该实验非零退出,并给出 token 路径、实际单位和允许单位,而不是只打印 invalid token。
反向实验三是 alias 环。让 A 引用 B、B 又引用 A。构建必须中止并打印循环路径。alias 环如果被导出成 CSS 自引用,浏览器会把变量计算为无效值;在设计工具里则可能表现为无法设置 alias。循环检测应在提交阶段完成,而不是等待页面渲染异常。
实验结束后恢复 token 文件,执行:
npm run tokens:clean
npm run tokens:build
git status --shortclean 用于证明生成目录可完全重建。若清理后丢失了手写文件,说明源码与生成物边界设计错误;若构建后出现无法解释的未跟踪文件,说明输出清单不完整。
Figma Variables 与代码变量怎样建立稳定映射
Figma collection 更接近一组共同拥有 modes 的变量,不应机械对应源文件目录。一个易维护的设计是用 Primitives collection 存原始尺度,用 Semantic collection 存 light、dark 等 mode,用组件 collection 承载确实需要组件级覆盖的少量变量。变量组名使用 / 形成设计侧层级,代码源使用点路径;映射器负责规范化,不能让设计师和开发者各自手改两套名称。
| 源 token | Figma | Web | Android | iOS |
|---|---|---|---|---|
semantic.color.text.default | color/text/default | --color-text-default | color_text_default | ColorTextDefault |
semantic.space.control.inline | space/control/inline | --space-control-inline | space_control_inline | SpaceControlInline |
Figma 变量可为 Web、Android、iOS分别设置 code syntax,创建和管理变量说明这些名称会显示在 Dev Mode 代码片段中。Code syntax 是交付提示,不是编译期契约;真正的契约仍应由仓库 token 路径和生成器保证。否则 Figma 中改了 code syntax,代码仓库不会自动感知。
类型映射也不是一对一:Figma Number 没有自带 px、rem、dp 这样的完整跨平台单位语义;String 能存字族名,却不能证明目标平台已经安装字体;Figma 的样式能够表达复合效果,而变量类型比 DTCG 复合类型更少。因此同步层要保存类型和单位元数据,不能只导出最终数值。
Figma 已支持把符合 DTCG 的 token 文件导入 Figma Design,但支持类型和单位有限:dimension 需要 px,duration 需要 s,颜色目前只接受 HSL 或 sRGB,font family 需要单个字体名。规范真源若使用 rem,不能直接导入;应由适配器生成只读的 px 导入文件,并比较变量数量、类型、mode 和 alias 后再替换已发布库。具体限制以 Figma 的 variable mode 与 token 导入说明为准。
需要自动读写变量时,不要把“Figma 有变量”推导成“所有团队都能用 API 同步”。Variables REST API要求相应企业计划和账号席位;读取需要 file_variables:read,写入需要 file_variables:write 与文件编辑权。API 写入后的变量还需要发布,其他文件才能消费。没有这些条件时,应选择人工导入、受控插件或仓库真源,不得依赖某个第三方插件的付费导出能力作为团队标准。
DTCG 兼容不是给 JSON 换几个字段名
Design Tokens Community Group 的 Format Module 定义了 token、group、type、alias、复合类型和扩展字段。采用时要记录明确规范版本;例如 2025.10 是协议版本标识,不是文章时间。该报告由社区组发布,并非 W3C Standard,而是面向实现的 Candidate Recommendation;升级前应阅读状态与兼容变化。DTCG Format Module要求 token 类型明确,工具不能只看值猜类型;group 只负责组织,工具也不应从目录名猜用途。
一个更接近规范的数据片段如下:
{
"$schema": "https://www.designtokens.org/schemas/2025.10/format.json",
"color": {
"$type": "color",
"brand": {
"$value": {
"colorSpace": "srgb",
"components": [0.145, 0.388, 0.922]
}
},
"action": {
"$value": "{color.brand}"
}
},
"space": {
"$type": "dimension",
"control": {
"$value": { "value": 16, "unit": "px" }
}
}
}很多既有转换工具仍同时兼容旧式字符串颜色和 DTCG 结构化颜色。团队应设置一个适配层,把规范输入转换为各平台需要的中间对象;不要让每个应用自行解析 DTCG。Style Dictionary 会自动识别 DTCG,也可用 usesDtcg: true 明确输入契约;但“可解析”不等于每个内置 format 都能无损表达所有复合类型。阴影、渐变、排版和边框要逐项验证目标格式,无法表达时应让构建失败或明确拆分,不能静默丢字段。
$extensions 可以保存工具专属元数据,但键必须命名空间化。Figma ID、设计侧 collection 信息或平台提示可以放在扩展中,业务语义不能绑死在扩展里。否则换掉设计工具时,核心 token 也无法解释。alias 应引用稳定语义,禁止跨越多层形成十几跳链路;长链会增加循环风险,也让设计师在 Dev Mode 中难以追溯最终值。
单位、颜色、mode 和平台差异必须显式决策
尺寸源值使用 px 并不代表所有端最终都输出像素。Web 可以按根字号转 rem,Android 需要区分布局 dp 与字体 sp,iOS 通常输出 point 数值。转换规则必须知道 token 用途;把所有 dimension 统一除以 16,会把边框、断点或原生尺寸错误缩放。字体缩放还涉及无障碍设置,不能把设计稿像素强行固化为不可缩放数值。
颜色也不是十六进制字符串这么简单。DTCG 结构可以表达色彩空间和 alpha,目标平台可能只支持部分空间;转换到 sRGB 时要判断超出色域后的策略。生产门禁至少验证色彩空间、alpha、对比度和格式精度。DTCG 版本 2025.10 用 alpha 表示透明度,hex 只是可选的六位回退值;不要把 #ffffff00 当作规范源值,跨平台输出应使用目标 format 的明确表示。
mode 是 Figma collection 或消费端的上下文机制,不是 DTCG token 的核心属性。它应表达正交上下文:light/dark 是主题,compact/comfortable 是密度,brand-a/brand-b 是品牌;把三种维度塞进 dark-compact-brand-a 会产生组合爆炸。可组合的平台让不同 collection 或源文件分别承载主题和密度,不可组合的平台则在生成阶段计算产品支持的有限组合,并用测试证明没有漏项。默认 mode 变更属于行为变化,因为未显式指定 mode 的页面会继承新默认值。
alias 是关系,不只是解析后的最终值。CSS 可以选择保留 --semantic-color-action-primary: var(--primitive-color-blue-600),便于运行时主题覆盖;Android 只有使用支持引用的资源 format 或自定义 format 时才应保留资源引用,android/colors 与 android/dimens 不能想当然地假设支持它。某些原生输出需要把 alias 展平。两者没有绝对优劣:保留引用利于调试和主题切换,展平利于减少运行时依赖。无论选择哪一种,构建报告都应同时保留 original、解析值和引用路径,供审查与故障定位。
源码、生成物和组件消费边界
推荐仓库布局如下:
design-tokens/
tokens/ # 人工维护的规范源
primitive.json
semantic-light.json
semantic-dark.json
schemas/ # 版本化校验规则
transforms/ # 有测试的自定义转换
sd.config.js
package.json
package-lock.json
.nvmrc # 与 package.json / CI 同步的 Node 基线
build/ # 完全可重建的生成物
CHANGELOG.mdtokens/、schema、转换代码和锁文件必须评审。build/ 是否提交取决于消费模式:作为独立 npm 包发布时,CI 可构建并打包,不必让源码仓库保存重复产物;需要下游直接通过 Git 或原生工程消费时,可以提交生成物,但 PR 必须证明它们由当前源生成。任何人工修复都应回到源或 transform,禁止直接编辑 build/。
组件库消费 token 包时锁定明确版本,不应永远跟随 latest。业务应用再通过组件库版本获得稳定依赖。确需直接消费 semantic token 的应用,也要在依赖图中可见。Token 包不能反向依赖业务组件,否则会形成发布环:组件等 token,token 构建又读取组件。
本地接入完成后,用一个真实组件做端到端验证:按钮默认态、hover、disabled、深色 mode 都必须来自生成变量;浏览器计算样式、Android 资源解析或 Swift 编译结果应成为证据。删除试验项目时只移除 token 包依赖、导入语句和生成目录,再执行原有构建;若清理后仍依赖全局 CSS 或残留复制值,说明接入没有形成单一入口。
把这些对象连起来后,交付链不是“从 Figma 导出一份文件”,而是从语义定义到不可变制品再到锁定版本消费的单向编译。回滚也不逆向修改生成物,而是用已保存的源提交、工具链和制品摘要恢复旧行为,再发布一个可审计的新版本:
图中的每次前进都应留下可比较证据:定义阶段保存 token 路径和引用图,编译阶段保存工具链与目标名称,发布阶段绑定包版本和摘要,消费阶段记录实际解析版本。这样出现蓝色漂移时,团队能判断错误来自源值、转换规则、发布制品还是应用没有升级,而不是在四个平台上分别覆盖一个临时色值。
用 CI 阻断漂移、断链和未声明变化
最基本的漂移门禁是在干净工作区重新生成,再检查差异。GitHub Actions 示例可以写成:
name: design-tokens
on:
pull_request:
paths:
- 'design-tokens/**'
jobs:
verify:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version-file: 'design-tokens/.nvmrc'
cache: npm
cache-dependency-path: design-tokens/package-lock.json
- run: npm ci
working-directory: design-tokens
- run: npm run tokens:build
working-directory: design-tokens
- name: Reject drift
run: git diff --exit-code -- design-tokens/build示例用 @v4 保持可读和可运行;生产仓库应把 Action 固定到已审核的提交摘要,并由依赖更新流程维护。若生成物不入库,就把最后一步改为 schema、引用完整性、命名冲突、平台编译和快照测试,并上传构建产物供后续 job 使用。门禁至少应覆盖:JSON/schema 有效、类型明确、alias 可解析且无环、规范化后名称不冲突、每个 mode 拥有必需 token、目标平台构建成功、产物无未声明漂移。
仅比较格式化后的 JSON 不够。两个名称在源中大小写不同,转换成 Android snake_case 后可能碰撞;两个颜色源值文本不同,转换后可能等价;删除 primitive 可能不影响当前产物,却破坏下游直接引用。检查器需要同时比较源路径、目标名称、引用图和公开 API 清单。
CI 不应携带 Figma 写权限才能完成普通 PR 验证。仓库构建是纯函数,读取源并产生输出;只有明确的同步或发布 job 才能申请设计平台凭证,并且应经过人工批准环境。这样即使第三方依赖被植入恶意代码,普通 PR 也无法修改设计库。
版本、破坏性变更与可执行回滚
Token 包适合使用语义化版本,但变更级别要按消费者行为判断:新增未使用 token 通常是 minor;修正文档描述是 patch;删除或重命名公开 token、改变类型、改变单位策略、删除 mode、改变默认 mode、改变生成名称都可能是 major。颜色值变化是否 major 取决于产品契约,至少必须进入变更日志并触发视觉回归,而不能伪装成无影响的 patch。
重命名采用“新增、迁移、弃用、删除”四步。先增加新 token,让旧 token alias 到新 token,并在元数据标记弃用;扫描仓库和组件库使用量;经过约定迁移窗口后再删除。直接把旧名改掉,会让未同步发布的应用在编译期失败,或让运行时 CSS fallback 悄悄生效。
一次 token 发布应保留这些可回滚对象:源提交、工具链锁文件、生成产物摘要、包版本、Figma 库发布版本和消费方清单。回滚优先发布一个恢复旧行为的新版本,而不是重写已经发布的包。若错误只存在于 Figma,恢复设计库前还要确认代码真源是否需要同步;若代码包错误但设计正确,则回滚包并冻结自动同步,避免错误值再次覆盖设计文件。
演练时选一个非核心语义 token,发布候选版本,在示例应用验证后再恢复。证据应包括包解析版本、生成物 hash、组件截图或计算值以及回滚耗时。只会在 Git 中 revert,而不知道制品仓库、CDN 缓存和 Figma 已发布库如何恢复,不算具备回滚能力。
权限、凭证和供应链不是交付链的附注
设计文件至少区分查看、编辑与发布权限;token 仓库区分读取、提案、合并和制品发布。日常开发者不需要设计库写权限,设计师也不需要包仓库发布令牌。自动同步优先使用组织管理、可到期、可审计的 OAuth 或 plan access token,避免把个人 PAT 存入 CI。Figma API 认证说明区分 OAuth、plan access token 和个人访问令牌;具体选择要依据自动化主体和组织能力,而不是复制个人令牌到共享变量。
凭证只进入受保护的 CI secret,日志中不得输出请求头、完整响应或 file key。读与写拆分,普通校验只申请 file_variables:read;写入 job 才申请 file_variables:write,并同时满足 Enterprise、Full seat、管理员身份和目标文件编辑权,再受环境审批、目标文件 allowlist 和并发锁保护。Variables API 要求与 Figma scope 文档都强调 scope 不会越过文件自身权限,因此排障时要分别检查令牌 scope、计划、账号席位、管理员身份和文件访问权。收到 401 先判断令牌失效,收到 403 再检查这些授权条件,不能靠反复扩大权限解决。
Style Dictionary、自定义 transform、GitHub Action 和 token 校验器都属于构建供应链。提交锁文件,使用 npm ci,审查依赖脚本和许可证,定期扫描漏洞;关键 Action 固定提交摘要。自定义转换器有能力读取环境变量和写文件,评审等级应与构建脚本相同。生成包还要声明许可证与来源,不要把受限制字体、图标或第三方品牌资产误装进 token 包。
容量、成本与长期治理
Token 数量增长会直接增加 Figma 变量管理、构建时间、产物体积和认知成本。不要把每个页面的偶发值都提升为全局 token。新增时回答三个问题:是否跨组件复用,是否会随主题或品牌变化,是否需要成为稳定交付契约。三个答案都是否时,局部组件值通常更合适。
监控不只看总数,还要看未使用 token、alias 深度、每个 mode 缺失量、跨层引用、生成名称碰撞、弃用存量和下游版本分布。Figma collection 存在变量数量与 mode 数量等产品限制,且部分 API 和团队能力受计划影响;这些易变边界应在接入时通过产品文档和租户实测确认,而不是写入永久架构假设。
团队至少要有四个明确角色:设计系统 owner 决定语义和视觉演进;平台 owner 维护 schema、转换器、包和 CI;各端 owner 审核平台输出;安全或发布 owner 管理凭证与制品权限。一个 token 变更必须同时有语义 owner 和受影响平台 owner,不能让同步脚本替代责任人。
退出计划也要在接入时设计。仓库应保存开放、可解释的源数据,核心语义不依赖某个插件私有字段;转换器可以替换,组件只依赖生成契约。停用 Figma 自动同步时,撤销令牌、移除 webhook 或定时任务、导出最后一次变量快照并记录 hash;替换 Style Dictionary 时,用同一组输入对比新旧平台产物、名称和引用图,差异通过后再切换。这样工具可以退出,设计决策和版本历史仍留在团队手里。
交付前的架构师检查
源 token 有明确类型、命名层级和唯一维护入口,生成目录可以从零重建。Figma collection、mode、alias 与代码路径有确定映射,code syntax 不被误当成编译契约。DTCG 采用版本已记录,复合类型、单位和色彩空间在每个目标平台都有验证结论。
正向变化只影响预期产物;断链、非法单位、alias 环和名称碰撞会让 CI 非零退出。生成物是否入库已有决策,任何手工修改都会被漂移门禁拒绝。公共 token 的新增、弃用、删除、默认 mode 与单位策略遵守版本规则。
Figma 写权限只存在于受控同步 job,凭证可轮换、可撤销、可审计且不会进入日志。依赖锁文件、Action 摘要、许可证和自定义 transform 都进入供应链审查。发布记录能关联源提交、包版本、产物摘要、设计库版本和消费方,并完成过回滚演练。
owner、容量指标、成本复查和工具退出步骤都有可执行负责人。
