分析了 Figma-to-code 场景中像素上下文(截图)与结构化上下文(类型化 IR、语义关系)的本质差异,指出结构化输入才能让 AI 生成代码与设计系统良好兼容、便于合著和比对。
上下文正在成为 AI 辅助开发的瓶颈。不是模型能力的问题——模型进步得足够快,已经不再是制约因素。真正限制 AI 生成代码质量的,是这些模型所接收的上下文的质量。
对于 Figma-to-code 工作流,上下文以两种截然不同的形式出现:像素上下文(截图、渲染图像)和结构化上下文(类型化 IR、token、语义关系)。这不仅仅是同一信息的不同格式,而是不同类别的输入,它们具有不同的特性、不同的信息损失特征,以及不同的上限——决定了 Agent 最终能产出什么样的代码。
业界目前仍在大量使用像素上下文。这是一个错误。figmascope 导出的是结构化上下文——从一开始就用正确的输入。下面我们来比较这两个类别,以及为什么这个差异决定了生成代码是否能组合、能 diff、是否能经受住真实设计系统的考验。
像素上下文是设计的任何栅格化表示:从 Figma 导出的截图、"Export frame" 导出的 PNG、设计工具的渲染图。按下 Cmd+Shift+4 截取 Figma 画布时得到的就是这种东西。
具备视觉能力的 LLM 处理像素上下文的效果令人印象深刻。它们能识别 UI 模式、定位布局区域、从视觉外观推断组件类型,并仅凭图像生成看似合理的代码。如果你用过 Claude 或 GPT-4V 做 screenshot-to-code,应该见过这种情况。输出看起来正确的时候比你想象的要多。
但"看起来正确"和"真正正确"不是一回事——而两者之间的差距,正是设计系统一致性、token 保真度、组件身份和可复现性所在的地方。
结构化上下文是一种类型化的、机器可读的表示,它保留了设计的语义:每个元素是什么,而不仅仅是它看起来像什么。它包含:
类型化节点:每个元素都有一个 kind(FRAME、TEXT、INSTANCE、VECTOR),携带关于其在布局中角色的语义信息
命名值:颜色是 token 引用而非十六进制字符串;间距是 token key 而非像素值
空间关系:布局方向、gap、padding、对齐方式——保留为属性,而非从位置推断
身份链接:组件实例携带其源组件 ID;字符串携带交叉引用 key
层级关系:完整的节点树,父子关系完整保留
结构化 IR 是设计树的显式表达:每个节点有 kind、name、absoluteBoundingBox、children、fills(尽可能解析为 token 引用)、auto-layout 属性(如果适用),以及 INSTANCE 上的 componentId。
像素上下文告诉 Agent 一个设计看起来是什么样的。结构化上下文告诉它一个设计意味着什么。编码 Agent 需要的是意义,而不是外观。外观是视觉测试要检验的东西。
像素上下文的核心失败模式是不可逆的信息损失。当 Figma 将一个 frame 渲染为 PNG 时,它丢弃的恰恰是对代码生成最重要的信息:
层级树塌缩了。 不再存在"三个项目为一组、间距 8px"。只有一片像素区域,暗示着某种分组。Agent 必须从视觉证据中重建树结构,而重建是近似的。它有一定百分比的几率会出错——而且这个百分比随着设计复杂度增加而增长。
Token 绑定消失了。 映射到 color/action/primary 的橙色背景变成了 #FF6B00。Agent 生成一个硬编码的十六进制值。如果你的颜色变了,或者你需要支持暗色模式,或者你需要审计 token 使用情况,那个硬编码值就是一个隐患。
组件身份没了。 同一个 card 组件的四个实例变成了四个看起来相似的矩形。Agent 可能生成一个可复用组件,也可能生成四个相似但不相同的代码块,取决于它推断出了多少结构相似性。你想要可预测的输出;但得到的是概率性的输出。
布局意图是模糊的。 这是一个 flex row 还是 grid?项目之间的间距是 gap、margin,还是每个项目的 padding?像素不会告诉你。Agent 来选择——而每次运行的选择都可能不同。
从 Figma 到生产级 React,这条路怎么走。
用像素上下文:导出 PNG。粘贴给 Claude。得到 JSX。检查 JSX 是否正确。发现硬编码值。发现错误的组件结构。提示修正。迭代。最终得到一个看似合理的东西。手工编辑以匹配设计系统。发布。下一个页面:从头重复,因为上一次运行的输出无法组合。
用结构化上下文:导出一个 bundle(一键,在浏览器中运行)。将 CONTEXT.md + screen IR 传给 Claude,同时附上指定框架和设计系统约定的 system prompt。得到使用你指定的 token 名称、组件名称和正确布局结构的 JSX。检查正确性。发布。下一个页面:用同样的 bundle、同样的 agent,输出可组合——因为输入是一致的。
节省的工作量是真实存在的,但它是次要的。首要的收获是可组合性。结构化上下文使跨页面和跨 Agent 的输出成为可能。像素上下文做不到——每个页面的输出都是一座孤岛,每次都是一次新的推理。
IR 中的每个节点都有一个 kind。这立刻就产生了作用。TEXT 节点生成一个文本元素。带有 auto-layout 的 FRAME 生成一个容器。INSTANCE of Button/Primary/Large 生成一个带有正确 props 的 button 组件调用。VECTOR 生成一个图标引用。
Agent 不用猜测。它将 kind 映射到代码原语——这些规则在 CONTEXT.md 中为目标框架指定:"对于 INSTANCE 节点,使用组件名来确定 React 组件。对于 layoutMode 为 HORIZONTAL 的 FRAME,使用 flex row。对于 style 为 typography/heading.lg 的 TEXT,使用 Heading 组件。"这些是编译器风格的规则,不是推理任务。
每个节点上的 absoluteBoundingBox 给出了 Figma 坐标空间中的位置和尺寸。结合 auto-layout 属性——layoutMode、itemSpacing、paddingLeft/Right/Top/Bottom、alignment——Agent 有了生成正确布局代码所需的全部信息,不需要像素计数。
边界框也让 Agent 能够验证自己的输出:如果生成的组件尺寸与 IR 指定的不同,就说明出了问题。这是结构化上下文的一个可测试属性,在像素上下文中没有等价物。
当 IR 中的四个节点共享同一个 componentId 时,Agent 知道它们是同一个组件的实例。它生成一次组件定义,从变体中推导 props,然后渲染四个调用。这是正确的输出——而从像素上下文出发,不经过大量 prompt 工程是无法达到的——而那些工程本质上是在让 Agent 重新推导设计文件本来就已经有的结构。
字符串交叉引用以相同方式工作。当多个文本节点引用 stringRef.key: "action.continue" 时,Agent 知道使用单一的 i18n 查询,而不是三个硬编码字符串。身份信息在 IR 中;Agent 只需读取它。
普通的 JSON 文件可以干净地 diff。一个改变的 padding 值在每个页面的 IR 中显示为单行变更。一个重命名的 token 在 tokens 文件中显示为 find-replace 风格的 diff。一个新的组件实例作为 children 数组中新增的对象出现。
这是对工程师真正有用的设计版本历史。不是"设计在周二更新了",而是"这是这个页面 v2 和 v3 导出之间变化的三个属性"。你可以把它放进 PR 描述里,对它运行自动化检查,审计代码变更是否与设计变更匹配。
这里正在形成的工具类别不是"更好的 Figma 导出"。而是栈中的一个新层:设计上下文基础设施。它的职责是将设计源(Figma 文件、组件库、token 系统)转换为结构化的、可被 Agent 读取的、版本可控的产物,以供给代码生成层。
这一层位于设计工具和编码 Agent 之间,承担着目前双方都不拥有的职责:快照管理、语义提取、token 解析、组件清单、跨页面字符串索引、bundle 版本控制。将其视为基础设施意味着它是自动化的、版本化的、可在 CI 中运行的、格式定义的、可审查的——就像构建系统是代码的基础设施一样:不是代码,不是二进制,而是可靠的、可复现的流水线,将前者转换为后者。
结构化上下文 bundle 包含每个导出页面的 2x PNG。不是因为 PNG 驱动代码生成,而是因为视觉确认很重要。Agent 应该能够将其生成的输出与 PNG 进行交叉验证。开发者应该能够在不打开 Figma 的情况下查看页面。PNG 是一个健全性检查,不是规格说明。
这个区别——像素用于确认,结构用于规格——是正确的思维模型。你不是消灭像素上下文;而是把它降到正确的角色。它是 QA 产物,不是构建输入。
就像你不会给编译器一张源代码的截图:你给的是源代码,然后用截图做文档。设计文件是源代码。bundle 是编译产物。PNG 是文档图片。
结构化上下文实现了一种像素上下文无法实现的工作流:一个设计,多个目标。同一个 IR 可以供给 React/Tailwind 生成器、Jetpack Compose 生成器和 SwiftUI 生成器。底层设计是相同的;目标特定的上下文(框架原语、命名约定、布局 API)存在于 CONTEXT.md 中,而 CONTEXT.md 是按目标生成的。
这是真正能扩展的多目标 codegen。你从设计中导出一个 bundle,运行三个 Agent,各自使用不同的 CONTEXT.md,得到三个在结构上等价的实现——因为它们是从同一个 IR 生成的,而不是从三张截图的三次独立推理中生成的。
这个工作流的瓶颈不是模型能力。是上下文质量。结构化上下文使其成为可能。
从 figmascope app 导出你的结构化上下文 bundle,然后用它配合 Cursor、Claude Code 或 Aider,实现多目标、可组合的 UI 生成。