在一个已有多年沉淀的 Vue 2 项目上做 Vue 3 重构,传统方式往往意味着「大量搬砖 + 海量联调」。这次重构中,我们尝试用 AI 辅助开发 + SDD(Specification Driven Development)+ skills 体系 + 脚手架 的组合打法,把这件本来“又枯燥又危险”的事,拆解成一条可复制的工程化路径。
本文从工程实践视角出发,抽象和脱敏整个过程,重点分享:如何用 openspec、skills 和脚手架,把一个 Vue 2 页面在保证行为一致的前提下,稳定地迁移到 Vue 3。
一、整体思路:从「代码迁移」到「规格驱动」
传统重构的常见做法是:先搭一个 Vue 3 空壳,然后边看老页面边抄逻辑、抄样式,再靠肉眼回归。问题是:
- 行为对齐难验证:很多交互细节、边界条件容易遗漏。
- 口口相传的隐性规则很多:比如埋点、接口组合、数据结构等,文档不全,全靠「问人」。
这次我们反过来做——先收敛为规格,再用规格驱动实现:
- openspec:用一套结构化的 markdown/YAML,把「页面职责、数据流、接口约定、UI 规则」固化下来。
- SDD(Specification Driven Development):所有改动以规格为入口,先改 openspec,再改代码,并保持两边同步。
- AI + skills:通过 skills 把这些规则喂给 AI,让 AI 在生成/修改代码时自动遵循。
这样做的核心收益有三点:
- 重构不再依赖个别老同学的记忆,而是依赖规格;
- Vue 2 和 Vue 3 版本可以长期“对齐在同一份 openspec”上;
- 后续再做迭代时,AI 可以直接基于规格安全地改 Vue 3 代码。
二、openspec:把「页面」变成「规格」
2.1 规格长什么样?
以一个典型的看板页面为例,我们会在 openspec/ 目录下,为它创建一份类似的规格文档(示例结构):
- 背景与目标:页面解决的核心问题、主要用户是谁。
- 数据源与接口:
- 调用了哪些 API;
- 入参、出参字段约定;
- 多接口时的组合规则。
- 交互行为:
- 筛选条件如何影响接口调用;
- 图表/卡片 hover/click 会触发哪些联动;
- 「重置」/「暂无数据」等边界行为如何处理。
- UI 与组件拆分:
- 页面拆成哪些组件;
- 每个组件的 props / emits;
- 关键样式约定(如色盘、字号、布局 breakpoints)。
这些内容原本散落在:老 Vue 2 模块、产品文档、口头约定里。通过 openspec,把它们收敛到一处。
2.2 Vue2 → Vue3 重构流程与 openspec 的关系
一次典型的迁移会长这样:
- 阅读老页面(Vue 2)行为:确认真实线上行为,以老页面为事实来源。
- 补全/修正 openspec:把发现的行为写回规格,包括之前没记录的边角逻辑。
- 基于 openspec 设计 Vue 3 组件结构:确定拆分方式、props、数据流。
- 在 Vue 3 中实现并对齐行为:编码时所有决策优先对齐 openspec,其次对齐老页面实现。
- 回写 openspec 变更:当发现更合理的实现/边界处理方式时,先修改规格,再更新代码。
用一句话概括:页面只是规格的一种实现,Vue 2 是老实现,Vue 3 是新实现,两者共享一份 openspec。
2.3 使用 openspec 的提示词与命令
要让 AI 真正「按规格办事」,需要把 openspec 的目录约定、配置和任务清单,通过固定提示词和命令串起来。下面给出可直接复用的写法(已脱敏,路径与命令按你项目实际替换)。
目录与配置约定
-
openspec 目录结构(建议):
openspec/config.yaml:项目级上下文(技术栈、API 约定、代码风格等)和规则(spec / tasks / implementation / proposal);会注入到每次「规划类」请求。openspec/changes/<变更名>/:单次变更的规格与任务。proposal.md:变更目标、范围、技术栈替换、各组件实现细节与验收标准。tasks.md:按阶段拆分的任务清单与预估工时。
openspec/guides/:详细指南(如 SDK 使用、目录结构、API 调用、代码风格),供实现时引用。
-
config.yaml 要点:
context:一段紧凑的「项目上下文」,说明技术栈、关键约束、API 约定、代码风格、架构模式等;AI 在做任何实现前应先读这段。rules:按制品类型约束(如 spec 必须含功能概述与 API 列表,tasks 必须按功能模块拆分、每任务 2~4 小时,implementation 必须先生成 hook 再在组件中引用等),用于生成/评审 proposal 与 tasks。
常用提示词(与 AI 协作时)
| 场景 | 提示词示例 |
|---|---|
| 启动一次变更前 | 请先阅读 openspec/config.yaml 中的 context 和 rules,再阅读 openspec/changes/<变更名>/proposal.md 和 tasks.md。后续所有实现都以此规格为准,不得偏离。 |
| 按阶段实现 | 根据 openspec/changes/<变更名>/tasks.md 第 N 阶段,实现 xxx。实现时严格遵守 config.yaml 中的 implementation 规则,并参考 openspec/guides/ 下相关指南。 |
| 实现单个组件 | 根据 openspec/changes/<变更名>/proposal.md 第 3.x 节的「xxx 组件」实现细节,实现该组件;样式与交互须与规格一致;对照 sdk/rules 与 openspec/guides/code-style.md 检查命名与结构。 |
| 对齐接口与数据流 | 本页面的接口入参、出参及多接口组合方式以 proposal.md 第 2 节为准。请按该节实现 api/service 与组件的请求逻辑,并处理边界(无数据、解析失败等)。 |
| 回写规格 | 根据当前 Vue 3 实现,更新 openspec/changes/<变更名>/proposal.md 第 x 节,使规格与代码一致(仅更新描述,不改变行为约定)。 |
| 新建变更 | 在 openspec/changes/ 下新建目录 <新变更名>,按 config.yaml 中 proposal 与 tasks 的规则,编写 proposal.md(含目标、范围、技术栈替换、组件实现要点)和 tasks.md(按阶段拆分、每阶段 0.5~1.5 天)。 |
以上提示词建议在对话开头或每个新任务前使用一次,确保 AI 始终在「同一份规格」下工作。
常用命令
| 用途 | 命令示例 |
|---|---|
| 用脚手架初始化新子应用 | ai-cli init <项目名>(从模板拉取 Vue 3 子应用,自动带 openspec 目录、sdk、skills 等)。 |
| 在已有项目中更新 SDK / skills | 在子应用根目录执行 ai-cli fetch,将 sdk/ 与 AI 工具配置同步为模板最新版本。 |
| 本地开发与构建 | 进入子应用后 npm install → npm run dev;与是否使用 openspec 无关,但建议在实现前确认 openspec/config.yaml 中的技术栈与脚本一致。 |
把「读 config + 读 proposal/tasks → 按阶段实现 → 必要时回写 proposal」固化成固定提示词和命令,就能在团队内复现「用 openspec 驱动 Vue 2 → Vue 3 重构」的完整流程。
三、skills:把经验教给 AI
仅有 openspec 还不够,我们希望 AI 能主动理解并遵循这些约定,于是引入了 skills。
3.1 skills 是什么?
skill 可以理解为「给 AI 用的工程实践说明书」,例如:
- 某类页面的通用数据流规则;
- 请求封装方式(统一 request 层、错误处理);
- ECharts / FullCalendar 等组件的使用规范;
- UI 一致性约束(色值、间距、字体等)。
这些内容被拆分成多个 SKILL.md,按领域组织,比如:
vue3-format:Vue 3 代码风格、组件写法、Composition/Options API 约定等;vue3-request:接口封装、重试/超时策略、统一错误提示等;color-guide/ui-design-rules:颜色与 UI 规范;prd-abstraction:如何从需求描述抽象出稳定的规格。
3.2 skills 如何帮上忙?
在具体开发时,我们会:
- 先选定相关 skill(例如一个数据看板页面,往往会同时用到数据流、UI、图表三个 skill)。
- 把 skill 内容加载到 AI 的上下文中。
- 让 AI 在修改或生成代码时,显式引用和对照这些 skill。
效果包括但不限于:
- 代码结构更一致(模板、脚本、样式的组织方式趋同);
- 请求逻辑更可复用(统一走 SDK 中的 request 封装);
- 样式更易维护(统一使用变量、统一的布局与间距体系)。
本质上,是通过 skills 把「团队工程经验」沉淀下来,再帮你自动执行这些经验。
四、脚手架与子应用:流水线化 Vue3 开发
在重构过程中,我们还借助了脚手架和子应用模板,把 Vue 3 看板抽成可复用模版:
- 使用脚手架快速创建新的 Vue 3 子应用(如数据看板、商品看板等子项目),自动带上:
- 统一的目录结构;
- 已配置好的路由、打包、公共样式;
- 已接入的 request SDK、埋点 SDK 等。
- 每个子应用内部,再用 openspec 和 skills 指导具体页面开发。
这让我们可以:
- 对齐多个子应用的工程结构和依赖;
- 为之后更多 Vue 2 → Vue 3 迁移,提供一条开箱即用的路径;
- 让 AI 能“认得”这种脚手架生成的项目骨架,从而更高质量地生成补充代码。
六、AI 在整个过程中的角色
AI 在这次 Vue 2 → Vue 3 重构中,扮演了几个关键角色:
- 规格助手:根据现有页面代码,帮忙反向总结 openspec 的草稿,由人审核后沉淀为正式规格。
- 迁移助手:
- 根据 Vue 2 实现 + openspec,生成 Vue 3 组件初版;
- 自动对齐接口字段、tooltip 文案、边界场景等细节;
- 在多次迭代中保持与 openspec 的同步更新。
- 文档助手:在完成一部分开发后,从实际代码抽取「实践模式」,自动生成技术文档,方便团队复用。
关键点在于:AI 不是替代工程师,而是依托 openspec 和 skills,变成一个非常熟悉项目规范的“资深搬运工 + 文档生成器”。
七、经验总结与推荐做法
结合这次实践,整理出几条对未来类似迁移有参考价值的建议:
- 先规格,后代码:不要一上来就搬 Vue 2 代码,先让 openspec 准确、完善。
- 让 AI 读懂规则再写代码:把 openspec + skills 喂给 AI,再让它参与迁移,效果会好很多。
- 拆出可复用的技术文档:像 FullCalendar 集成、Echart 图表规范这类内容,抽出来单独成文,既方便 AI 使用,也方便团队新人学习。
- 脚手架优先:所有新的 Vue 3 子应用,都从脚手架模板起步,以减少工程差异。
- 保持“双向同步”:每次发现 Vue 2 和 Vue 3 的差异、或更合理的新实现时,第一步是更新 openspec,而不是只改一边的代码。
- 固化提示词与命令:和 AI 协作时使用固定提示词(见上文 2.3 使用 openspec 的提示词与命令),并配合脚手架命令,保证每次都在同一套规格下执行。
如果你也在做 Vue 2 → Vue 3 的重构,推荐尝试:
- 给每个关键页面写一份 openspec的change;
- 把团队的工程经验拆成若干 skills;
- 用脚手架统一项目骨架;
- 在这个基础上引入 AI,让它成为真正理解你项目上下文的“搭档”,而不是单纯的代码生成器。