1. 两条路线的本质分歧:从需求倒推方案
1.1 为什么这个问题现在才被频繁讨论
AI 生成 UI 这件事,放在两年前,大家讨论的还是“能不能生成”。现在讨论的是“生成出来的东西能不能用、好不好维护”。这个转变本身就说明了一件事:Demo 阶段已经过去了,落地阶段来了。
我最早接触 AI 生成界面是在做一些内部工具的时候。当时用大模型直接吐 HTML 和 CSS,确实快,一个下午能出三四个页面。但问题很快就暴露了——改一个按钮颜色,模型可能把整个布局都给你重写一遍;同一个设计语言,今天生成的圆角和明天生成的圆角能差出 4px;更别提多人协作的时候,每个人手里的“生成结果”都不一样,代码评审根本没法做。
后来我开始接触另一类方案:配置模板渲染。简单说就是不让模型直接写界面代码,而是让模型输出一份结构化的配置(JSON 或者类似 DSL 的东西),再由一套固定的渲染引擎把配置翻译成最终的 UI。这个思路一下子把“生成”和“渲染”解耦了。
所以现在摆在面前的就是两条路:
- 自由生成路线:LLM 直接输出 HTML/CSS/JSX/Vue 模板等界面代码,所见即所得。
- 配置模板渲染路线:LLM 输出结构化配置,渲染引擎负责把配置变成界面。
这两条路没有绝对的优劣,选错了场景,后面全是坑。下面我把这两条路拆开揉碎,从原理、实操、踩坑三个维度讲清楚。
1.2 自由生成路线的核心逻辑
自由生成路线的本质是让模型承担“设计师 + 前端工程师”的双重角色。你给它一段自然语言描述,它直接给你一段可运行的界面代码。
这条路线之所以能跑通,依赖的是大模型在代码生成上的能力。现在主流的大模型在 HTML、CSS、React、Vue 这些技术栈上的训练数据非常充足,生成一个结构合理的页面并不难。尤其是当你在提示词里把设计规范、组件库、布局要求写清楚之后,生成质量会有明显提升。
我实测下来,自由生成路线在以下几种情况下表现最好:
- 一次性页面:活动页、落地页、临时看板,做完就扔,不需要长期维护。
- 原型验证:产品经理要快速看一个交互效果,不需要代码有多规范。
- 个人项目:自己用的工具,怎么快怎么来,不讲究工程化。
但它的短板也很明显。生成结果的一致性完全靠提示词约束,而提示词约束是“软约束”,模型心情不好(其实是概率分布的问题)就可能不遵守。你让它用 8px 的圆角,它可能给你 6px,也可能给你 12px。单次看没问题,放在一起就露馅了。
还有一个容易被忽略的问题:生成代码的可维护性。模型生成的代码往往没有清晰的组件边界,样式和结构混在一起,命名也随缘。如果这个页面后续要交给团队维护,接手的人会很痛苦。
1.3 配置模板渲染路线的核心逻辑
配置模板渲染的思路完全不同。它把整个流程拆成了两段:
第一段:LLM 负责“理解意图,输出配置”。模型不需要写任何界面代码,只需要输出一份结构化的数据。比如:
{ "type": "page", "layout": "flex-column", "children": [ { "type": "card", "props": { "title": "用户信息", "padding": "16px", "borderRadius": "8px" }, "children": [ { "type": "text", "props": { "content": "张三", "fontSize": "18px", "fontWeight": "600" } } ] } ] }第二段:渲染引擎负责“把配置翻译成界面”。这部分是纯工程代码,不涉及 AI。渲染引擎根据配置里的type字段找到对应的组件,把props传进去,递归渲染子节点。
这条路线的好处是约束是硬约束。模型只能在配置的框架内发挥,它能选的组件类型、能设的属性值都是预先定义好的。圆角只有 4px、8px、12px 三档,模型只能从这三档里选,不可能给你生成一个 7px。这就保证了输出的一致性。
代价是灵活性受限。如果配置 schema 里没有定义某种布局方式,模型就做不出来。你需要提前把可能用到的组件和属性都设计好,这对 schema 的设计能力要求很高。
1.4 两条路线的关键差异对比
| 维度 | 自由生成 | 配置模板渲染 |
|---|---|---|
| 输出物 | HTML/CSS/JSX 代码 | 结构化配置(JSON/DSL) |
| 一致性 | 靠提示词约束,不稳定 | 靠 schema 约束,稳定 |
| 灵活性 | 高,几乎无限制 | 受 schema 限制 |
| 可维护性 | 差,代码风格随机 | 好,渲染逻辑统一 |
| 上手速度 | 快,直接出结果 | 慢,需要先搭渲染引擎 |
| 适合场景 | 一次性页面、原型 | 长期维护的产品、多页面系统 |
| 对模型能力要求 | 高,需要代码生成能力 | 中,只需要结构化输出能力 |
| 调试难度 | 高,问题可能在模型也可能在代码 | 低,问题定位清晰 |
这张表是我自己在选型时最常用的判断依据。但光看表还不够,实际选型的时候还要考虑团队情况、项目周期、后续迭代频率这些因素。
2. 自由生成路线的实操细节与避坑指南
2.1 提示词工程是核心生产力
自由生成路线里,提示词的质量直接决定生成结果的质量。我踩过的坑是:一开始提示词写得太随意,生成出来的页面能用但不好看,后来花了两天时间专门打磨提示词模板,效果提升非常明显。
一个经过验证的提示词结构是这样的:
你是一个资深前端工程师,请根据以下要求生成一个页面。 技术栈:React + Tailwind CSS 设计规范: - 主色 #2563EB,辅助色 #64748B - 圆角统一使用 rounded-lg(8px) - 间距使用 4 的倍数(4px/8px/12px/16px/24px/32px) - 字体大小:标题 24px,正文 14px,辅助文字 12px 页面要求: [这里写具体的页面描述] 输出要求: - 只输出 JSX 代码,不要输出解释 - 使用函数组件 - 样式全部用 Tailwind 类名,不要写内联样式这个模板的关键在于把设计规范显式地写进提示词。模型不会读心术,你不告诉它圆角用多少,它就随机发挥。你告诉它了,它大概率会遵守。
还有一个技巧:给示例。在提示词里放一个符合规范的代码片段作为参考,模型会模仿这个风格。这比纯文字描述有效得多。
2.2 生成结果的校验与修正
自由生成路线不能“生成完就直接用”,中间必须加一道校验。我的做法是:
第一步,结构校验。检查生成的代码是否包含必要的标签闭合、是否有明显的语法错误。这一步可以用简单的正则或者 AST 解析来做。
第二步,规范校验。检查颜色值、圆角值、间距值是否在允许的范围内。比如我定义了一个颜色白名单,生成结果里出现了白名单之外的颜色,就标记出来。
第三步,视觉校验。把生成的页面渲染出来,截图,和设计稿做对比。这一步比较重,一般只在关键页面上做。
校验发现问题之后,有两种处理方式:一是把问题反馈给模型,让它重新生成;二是用规则引擎自动修正。比如颜色不在白名单里,就替换成最接近的白名单颜色。
注意:不要指望模型一次生成就完美。把“生成-校验-修正”做成一个自动化流程,比反复手动调提示词效率高得多。
2.3 自由生成路线的典型翻车场景
我遇到过几次比较典型的翻车,这里列出来供参考:
场景一:多页面风格不一致。同一个项目里生成了五个页面,每个页面的按钮样式都不一样。原因是每次生成都是独立的会话,模型没有上下文记忆。解决办法是把设计规范固化到提示词模板里,每次生成都带上。
场景二:响应式布局失效。模型生成的页面在桌面端看起来没问题,到了移动端就乱套了。原因是提示词里没有强调响应式要求。后来我在提示词里加了“必须使用 Tailwind 的响应式前缀(sm: md: lg:)”,情况好转了很多。
场景三:交互逻辑缺失。模型生成的页面只有静态结构,点击按钮没有反应。原因是提示词里只描述了视觉,没有描述交互。后来我养成了一个习惯:在提示词里单独列一个“交互要求”段落,把点击、悬停、展开收起这些行为写清楚。
场景四:代码体积失控。模型生成的代码里有很多重复的样式定义,导致文件体积很大。这个问题在页面复杂度上升之后特别明显。解决办法是生成之后做一次代码压缩和去重,或者干脆接受这个代价,毕竟自由生成路线本来就不适合大型项目。
3. 配置模板渲染路线的工程化实践
3.1 Schema 设计:约束与自由的平衡点
配置模板渲染路线的核心是 schema。schema 设计得好不好,直接决定了这条路线能不能走通。
schema 设计的第一原则是:约束要足够强,但不能强到让模型无法表达。
举个例子。假设你要做一个卡片组件。如果 schema 里只允许borderRadius取"small" | "medium" | "large"三个值,那模型的选择空间就很小,但输出一定一致。如果你允许borderRadius取任意数值,那模型可能给你生成7px、13px这种不在设计规范里的值。
我的经验是:枚举值优先,数值范围次之,自由数值最后。能用枚举就用枚举,实在需要连续值就限定范围(比如 0-24px),并且只允许 4 的倍数。
一个实际用过的 schema 片段:
{ "component": "Card", "props": { "padding": { "type": "enum", "values": ["8px", "12px", "16px", "24px"], "default": "16px" }, "borderRadius": { "type": "enum", "values": ["4px", "8px", "12px"], "default": "8px" }, "shadow": { "type": "enum", "values": ["none", "sm", "md", "lg"], "default": "sm" } } }这个 schema 把卡片的样式属性全部枚举化了。模型在生成配置的时候,只能从这些枚举值里选,不可能出现规范之外的值。
3.2 渲染引擎的实现要点
渲染引擎的工作是:读取配置,递归渲染组件树。听起来简单,但有几个细节需要注意。
第一,组件的注册机制。渲染引擎需要知道配置里的type对应哪个实际组件。我一般用一个注册表来做映射:
const componentRegistry = { page: PageComponent, card: CardComponent, text: TextComponent, button: ButtonComponent, image: ImageComponent, // ... }; function renderNode(node) { const Component = componentRegistry[node.type]; if (!Component) { console.warn(`Unknown component type: ${node.type}`); return null; } const children = node.children?.map(renderNode); return <Component {...node.props}>{children}</Component>; }这个注册表是渲染引擎的核心。新增组件只需要在注册表里加一行,不需要改渲染逻辑。
第二,属性校验。渲染引擎不能盲目信任配置里的属性值。我一般会在渲染之前做一次校验,把不合法的属性值过滤掉或者替换成默认值。这一步很重要,因为模型输出的配置不一定完全符合 schema,有时候会多出一些字段,有时候会漏掉必填字段。
第三,错误边界。如果某个组件的配置有问题导致渲染失败,不能让整个页面白屏。我一般会在每个组件外面包一层错误边界,渲染失败的时候显示一个占位符,同时把错误信息上报。
第四,性能优化。配置树的递归渲染在节点数量多的时候会有性能问题。我试过用虚拟列表来优化长列表的渲染,效果不错。另外,配置树的 diff 和增量更新也值得做,避免每次配置变化都全量重渲染。
3.3 让 LLM 稳定输出配置的技巧
配置模板渲染路线对模型的代码生成能力要求不高,但对结构化输出能力要求很高。模型需要理解 schema,并且按照 schema 的格式输出配置。
我试过几种方式来提升输出的稳定性:
方式一:在提示词里嵌入 schema。把 schema 的 JSON 定义直接放在提示词里,让模型参考。这种方式简单直接,但 schema 比较大的时候会占用很多 token。
方式二:用 few-shot 示例。在提示词里放两三个输入输出的例子,让模型模仿。这种方式对格式的约束效果很好,但示例需要精心设计,覆盖常见的场景。
方式三:用 function calling 或者 structured output。如果模型支持这些能力,直接用它来约束输出格式,稳定性最高。我实测下来,支持 structured output 的模型在配置生成上的准确率比纯提示词方式高出不少。
方式四:输出后校验和重试。不管用哪种方式,输出之后都要做一次 schema 校验。校验不通过就把错误信息反馈给模型,让它重新生成。一般重试一两次就能得到合法配置。
提示:schema 校验建议用成熟的库来做,比如 Ajv(JSON Schema 校验)或者 Zod(TypeScript 优先的 schema 校验)。自己手写校验逻辑容易漏掉边界情况。
3.4 配置模板渲染路线的扩展性设计
这条路线最大的优势是扩展性。因为渲染逻辑和生成逻辑是解耦的,你可以:
- 换模型不影响渲染:今天用这个模型,明天换那个模型,只要输出的配置格式不变,渲染引擎不用改。
- 换渲染目标不影响生成:同一份配置可以渲染成 Web 页面、移动端页面、甚至 PDF。只需要写不同的渲染器。
- 增量更新:配置树可以做 diff,只更新变化的部分,不用全量重渲染。
- 版本管理:配置可以存数据库,可以做版本对比,可以回滚。
我在一个项目里把配置存到了数据库,每次用户调整界面,实际上是修改配置记录。这样做的结果是:界面调整不需要发版,改完配置即时生效。这个能力在自由生成路线里是很难做到的。
4. 选型决策:什么场景选什么路线
4.1 决策框架:四个关键问题
选型的时候,我一般会问四个问题:
问题一:这个界面需要长期维护吗?如果是一次性的,自由生成更划算。如果是长期维护的产品界面,配置模板渲染更合适。
问题二:界面的一致性要求高吗?如果多个页面需要保持统一的设计语言,配置模板渲染的硬约束更有优势。如果每个页面都是独立的,自由生成也能接受。
问题三:团队里有前端工程师吗?配置模板渲染需要有人搭渲染引擎、维护 schema。如果没有前端资源,自由生成的上手门槛更低。
问题四:后续迭代频率高吗?如果界面经常调整,配置模板渲染的“改配置不改代码”能力会省很多事。如果做完就不动了,自由生成的快速出活更有价值。
这四个问题的答案组合起来,基本就能确定选哪条路线了。
4.2 混合方案:两条路线不是互斥的
实际项目中,我很少纯用一条路线。更常见的做法是混合:
- 框架层用配置模板渲染:页面的整体布局、导航结构、通用组件用配置驱动,保证一致性。
- 内容层用自由生成:页面内的具体内容区域,比如营销文案、数据展示,用自由生成快速填充。
这样做的好处是兼顾了一致性和灵活性。框架层稳定,内容层灵活。
还有一种混合方式是分阶段:项目初期用自由生成快速验证,验证通过之后把关键页面迁移到配置模板渲染。这样既享受了前期的速度,又保证了后期的可维护性。
4.3 一个真实的选型案例
我之前参与过一个内部管理系统的建设。需求是:快速搭建 20 多个管理页面,页面结构类似(都是表格 + 表单 + 筛选),但字段和操作各不相同。
一开始尝试自由生成,确实快,两天生成了十几个页面。但问题很快来了:每个页面的表格样式不一样,筛选器的交互逻辑也不统一。用户反馈说“感觉像用了好几个不同的系统”。
后来切换到配置模板渲染。我们先定义了页面级的 schema:一个页面由“筛选区 + 表格区 + 操作区”三部分组成,每部分的组件类型和属性都是枚举化的。然后让模型根据需求描述生成配置。生成出来的配置交给渲染引擎,渲染出来的页面风格完全一致。
迁移过程花了大概一周,但后续新增页面的速度反而更快了。因为模型只需要输出配置,不需要写代码,生成速度更快,而且生成结果不需要人工调整样式。
这个案例给我的启发是:当页面数量多、结构相似、一致性要求高的时候,配置模板渲染的优势非常明显。反过来,如果页面数量少、每个页面都独一无二,自由生成更合适。
5. 常见问题与排查技巧实录
5.1 自由生成路线的常见问题
问题:生成的代码在浏览器里报错。
排查思路:先看控制台报错信息,定位到具体的行。常见原因有:标签未闭合、属性名拼写错误、引用了不存在的变量。如果是模型生成的代码,大概率是语法层面的问题,把报错信息反馈给模型让它重新生成即可。
问题:生成的页面在移动端显示异常。
排查思路:检查是否使用了响应式单位(rem、vw)和响应式布局(flex、grid)。如果用的是固定像素宽度,在移动端肯定会溢出。解决办法是在提示词里明确要求使用响应式布局,或者生成之后手动加一层媒体查询。
问题:同一个提示词,两次生成的结果差异很大。
排查思路:这是模型的随机性导致的。可以通过设置 temperature 参数来降低随机性(比如设为 0.2)。另外,在提示词里把约束写得越具体,生成结果的方差越小。
问题:生成的代码里有安全风险。
排查思路:模型可能会生成包含innerHTML或者eval的代码。生成之后需要做一次安全扫描,把有风险的代码替换掉。这个步骤不能省,尤其是面向用户的页面。
5.2 配置模板渲染路线的常见问题
问题:模型输出的配置不符合 schema。
排查思路:先检查提示词里是否包含了完整的 schema 定义。如果 schema 太大,考虑拆分成多个小 schema,分步生成。另外,开启 structured output 或者 function calling 可以大幅降低格式错误率。
问题:渲染出来的界面和预期不符。
排查思路:先检查配置是否正确,再检查渲染引擎的逻辑。我一般会在渲染引擎里加一个 debug 模式,把配置树和渲染结果并排显示,方便对比。
问题:新增组件类型之后,模型不会用。
排查思路:新增组件之后,需要在提示词里补充该组件的说明和示例。模型不会自动知道新组件的存在,必须显式告知。
问题:配置树太大导致渲染性能下降。
排查思路:对配置树做扁平化处理,只渲染可视区域内的节点。另外,组件的 memo 化也可以减少不必要的重渲染。
5.3 两条路线共通的避坑经验
经验一:不要跳过校验环节。不管是自由生成还是配置模板渲染,生成结果都需要校验。校验的成本远低于修复线上问题的成本。
经验二:保留生成记录。每次生成的输入和输出都存下来,方便回溯和对比。我在项目里用了一个简单的日志表,记录提示词、生成结果、校验状态。后来排查问题的时候,这些记录帮了大忙。
经验三:设计规范要前置。不要等生成了一堆页面之后才想起来统一设计规范。在开始生成之前,先把颜色、字体、间距、圆角这些基础规范定下来,写进提示词或者 schema 里。
经验四:人工兜底不能省。AI 生成的东西再好,也需要人工过一遍。尤其是面向用户的页面,视觉和交互的细节必须人工确认。把 AI 当成“高级助手”而不是“完全替代者”,心态会好很多。
经验五:从小范围开始试点。不要一上来就把整个项目交给 AI 生成。先选一两个页面做试点,跑通流程、积累经验之后再扩大范围。这样风险可控,出了问题也好回退。
5.4 问题速查表
| 问题现象 | 可能原因 | 解决方向 |
|---|---|---|
| 生成代码报错 | 语法错误、标签未闭合 | 反馈给模型重新生成 |
| 多页面风格不一致 | 提示词缺少设计规范 | 固化设计规范到提示词模板 |
| 移动端显示异常 | 缺少响应式布局 | 提示词中强调响应式要求 |
| 配置不符合 schema | 提示词缺少 schema 定义 | 补充 schema 或开启 structured output |
| 渲染结果与预期不符 | 配置错误或渲染逻辑问题 | 开启 debug 模式对比配置树 |
| 新增组件模型不会用 | 提示词未更新 | 补充组件说明和示例 |
| 渲染性能下降 | 配置树过大 | 虚拟列表、memo 化、增量更新 |
| 生成结果随机性大 | temperature 过高 | 降低 temperature,细化提示词 |
这张表是我在实际项目中慢慢积累出来的,基本上覆盖了八成以上的常见问题。遇到新问题的时候,先查表,查不到再深入排查。
6. 我个人的选型建议与实操体会
6.1 从项目阶段出发的选择策略
如果让我给一个简单的选择策略,我会这么说:
项目初期、需求不确定、需要快速验证:选自由生成。这个阶段最重要的是速度,代码质量可以后面再优化。
项目中期、需求稳定、开始考虑维护:逐步迁移到配置模板渲染。把稳定的部分用配置驱动,不稳定的部分继续用自由生成。
项目后期、需求明确、多人协作:全面使用配置模板渲染。一致性、可维护性、协作效率都是这个阶段的关键。
这个策略的核心逻辑是:让约束随着项目的成熟度逐步增强。早期约束少,灵活度高;后期约束多,稳定性好。
6.2 团队能力与路线匹配
选型还要考虑团队的能力结构。
如果团队里前端工程师多,配置模板渲染的落地会更顺,因为渲染引擎的搭建和维护需要前端能力。如果团队里主要是产品经理和设计师,自由生成的上手门槛更低,不需要写太多工程代码。
如果团队里有全栈工程师,两条路线都可以尝试。我建议先从自由生成开始,快速积累对 AI 生成能力的认知,然后再决定要不要投入资源做配置模板渲染。
6.3 一个容易被忽略的维度:调试成本
选型的时候,大家往往关注生成速度和质量,容易忽略调试成本。
自由生成路线的调试成本很高。因为生成结果是代码,代码里的问题可能来自模型的理解偏差,也可能来自代码本身的 bug,定位起来比较麻烦。
配置模板渲染路线的调试成本低很多。配置和渲染是分离的,配置有问题就改配置,渲染有问题就改渲染引擎,问题边界清晰。
如果项目对调试效率有要求,配置模板渲染的优势会更明显。
6.4 最后的实操建议
如果你现在正准备开始一个 AI 生成 UI 的项目,我的建议是:
第一步,明确需求边界。想清楚这个项目是一次性的还是长期维护的,一致性要求高不高,团队有没有前端资源。
第二步,做一个小范围试点。选两三个页面,分别用两条路线各做一遍,对比生成速度、生成质量、调试成本。
第三步,根据试点结果做决策。不要凭感觉选,用实际数据说话。
第四步,留好退路。不管选哪条路线,都要保证后续可以切换。配置模板渲染的配置可以导出成代码,自由生成的代码也可以逐步抽象成配置。保持灵活性,比一次性选对更重要。
我在实际项目里最大的体会是:没有最好的路线,只有最适合当前场景的路线。今天选了自由生成,不代表明天不能换成配置模板渲染。关键是理解两条路线的本质差异,知道什么场景下该用什么工具。
另外分享一个小技巧:如果你不确定选哪条路线,可以先做一个“最小可行渲染引擎”——只支持三五个基础组件,跑通“配置生成-渲染”的完整流程。这个引擎可能只需要一两天就能搭出来,但能帮你快速验证配置模板渲染路线是否适合你的项目。试过之后再做决定,比空想靠谱得多。