110 个页面迁到 uni-app x,我只做两件事

3 阅读16分钟

先说结论:官方 FAQ 写的是「2027 年初停止 uni-app 的 App 平台和 uni-app x VDOM 平台的维护」,还专门补了一句「不再维护不是下线」。但如果你在维护 App,这事已经从「要不要迁」变成「什么时候迁」。我把一个真实开源项目的迁移分支从头翻到尾:60 个提交、110 个 .vue 全部改成 .uvue、首个提交动了 1560 个文件,而人工从头到尾没逐行改业务代码,只做了两件事——挑对组件库的兼容版本,把验收标准写死。

目录:1 读准停止维护 · 2 组件库兼容版本 · 3 AI 改造与人工验收 · 4 八个坑 · 5 真机才看得见的错 · 6 把教训写回机器 · 7 可带走清单 · 8 边界

图 1:「停止维护」停的到底是什么,以及四类项目该怎么决策(含小程序平台边界)

1. 先把「停止维护」这句话读准

网上把这事传成了「uni-app 要没了」。去翻官方文档的 FAQ,原话是这样的:

官方已于 2024 年停止 nvue 和 5+ 的维护。并将于 2027 年初停止 uni-app 的 App 平台 和 uni-app x vdom 平台 的维护。 不再维护不是下线,而是没有重大问题的话(如新手机不兼容)不会再更新了。

拆开看是三件事,别混成一件事:

对象状态对你的影响
nvue、5+2024 年已停维护早该处理了
uni-app 的 App 平台2027 年初停维护做 App 的要排期
uni-app x 的 VDOM 平台2027 年初停维护第一代 x 项目也要往蒸汽模式走
老 uni-app 的小程序平台继续可用官方:只做小程序,用 uni-app 或 uni-app x 都可以
uni-app x 的小程序平台微信、支付宝可迁,其余等适配其他小程序先别跟着一起迁
老 uni-app 的 web 平台不会升级蒸汽模式后续 web 也推荐 uni-app x

官方给的理由很直接:蒸汽模式已经兼容 js/ts 写法,老项目能方便升级,继续维护 App 平台意义不大。同一份 FAQ 里还有一句对后面很关键的话——原生组件插件在老 uni-app 和 uni-app x 蒸汽模式之间不能复用,但 uts 写的 API 插件可以复用。

所以决策树其实很短:只做微信、支付宝小程序的可以按本文路径迁;做其他小程序的先别动;发 App 的,先查两个依赖再排期;已经上了 uni-app x VDOM 的,也要往蒸汽模式挪。查哪两个依赖,是这篇文章的重点。

这里还有一条容易被忽略的小程序平台边界:uni-app x 当前能承接的小程序迁移只覆盖微信和支付宝,其他小程序平台要等适配。官方页面「跨平台多」一句点名的小程序只有这两个,抖音小程序 仍列在「uni-app x 在 2026 年会陆续完成」的路线图里,百度、QQ、快手等平台未列出。老 uni-app 的小程序平台继续可用,所以「等适配」不等于「现在必须迁」——按目标端把项目拆开评估,别一股脑排进同一批改造。

2. 第一依赖:核心组件库有没有「兼容版本」

官方那份 14 步的《uni-app升uni-app x指南》,第 10 步写得很不客气:

如果使用其他组件库,需要咨询组件作者是否有 uni-app x 版本。如果没有的话,推荐用 uni-ui x 重构。

我翻的案例项目 mcode 是个中型 App:110 个页面/组件、uview-plus 3.8 的本地 fork、Vue3 + Vite CLI 工程。它没有硬啃「用 uni-ui x 重构 110 个页面」,而是换到了 uview-ultra 4.5.50——同一个作者做的 uni-app / uni-app x 双实现版本,插件市场原文写着「已经尽可能的继续跟 uview-plus 一样保持原始 uview 的接口兼容性」。

这一步省掉的是整个迁移里最贵的一块:业务模板里的 u-* 标签统一改成 up-*,props 和事件基本不用动。前提是有人替你把组件库的平台差异吃掉了。

图 2:迁移的两条依赖——组件库吃平台差异,AI 吃重复改造,人只做验收

「兼容版本」不等于「装上新版本就完事」。这个分支后续踩的坑很能说明问题:

  • 版本要跟着同步:从 4.5.50 一路到 4.5.85,仓库用 npm run sync:uview-ultra 从组件库源码全量同步,每次同步后都把「全量单测 + HBuilderX Web 编译」再跑一遍。插件市场里这个库 2026-11-08 已经更到 4.5.86。

  • 兼容声明要自己复验:插件市场的「其他」一栏里,蒸汽模式当时标的是 ×,而组件库文档和项目实测是能跑的。表格是作者的声明,真机才是你的结论。

一句话:迁移预算里,先给组件库做一次「有没有同接口的 x 版本 + 双实现有没有 parity 门禁」的尽调。没有,就老老实实按官方建议估重构工时,别指望 AI 能凭空补上这部分。

3. 第二依赖:改造交给 AI,验收留给人

官方迁移指南开头两句就是这套分工:

首先需要利用优秀的 AI 工具……同时整个改造工程,应该分步骤实施、分阶段验收。

后面还有三条更像「踩过坑的人写的」经验:十几步每一步都该新起一个会话,必要信息让 AI 总结进 md 给下一个会话读;AI 很擅长从 0 到 60,再往上要靠更优秀的人力 review 或更高算力做交叉验证;自动化测试在 AI 时代几乎是必备技能。

案例项目把这套做成了工程约束。仓库根目录的 AGENTS.md 是给 AI 读的规则文件,docs/mcode-architecture-notes/ 下攒了 215 篇架构笔记(规则里明确要求「每次改动必须新增或更新一篇 md 笔记」,且要写到「AI 不读完整实现也能复刻」的程度)。这些笔记就是跨会话的记忆,也是人工把经验交回给机器的通道。

首个迁移提交 7747466 的账本长这样:

改造项数量谁做的
.vue → .uvue110 个批量重命名 + 脚本改写
upThemeVar() 调用改 import 路径449 处批量替换
主题变量 var(--up-*) 消费点2286 处组件库 up-root 承接
web 专属 CSS 规则包 #ifdef WEB126 条脚本收敛
u- 前缀组件标签 → up-全量批量替换
条件编译 H5 → H5 || WEB、APP-PLUS → APP全量批量替换
UnoCSS / :deep() / plus.*全部移除或降级人工定规则、AI 执行
Jest 单测207 套件 / 2189 用例全绿机器验收

人在这张表里做的不是「改代码」,是定边界:哪些 CSS 允许留、哪些 API 必须清、什么算完成。

图 3:14 天里真实发生的迁移节奏,每个节点都跟着一次验收

图 4:把官方 14 步压成 4 道验收门的流水线

4. 八个坑,按「现象 → 根因 → 修复 → 检查项」记

下面这些全部来自该分支的提交说明与架构笔记,环境是 HBuilderX 5.33 alpha、蒸汽模式、styleIsolationVersion: 2。

① dev 白屏,发行版却正常。 index.html 入口写成 <script type="module" src="/main.uts">,dev server 原样返回未编译的 .uts,浏览器按 module MIME 严格校验拒绝执行。改成不带扩展名的 /main 就好。检查项:dev 与发行两条路径都要跑,只测 publish web 会漏。

② web 布局整体错乱。 uni-app x 的 web framework 样式把默认值改成了 App 原生语义:uni-view 默认 display:flex; flex-direction:column; overflow:hidden; flex-shrink:0,uni-text 默认 display:block。存量 CSS 全按旧 h5 语义写的。中途试过「web 切 .vue 双实现 + 全局重置默认值」,两天后推翻,回归统一 .uvue,改成给所有 display:flex 且未声明方向的规则补 flex-direction: row(82 文件 348 处),共享 scss 另外补了 5 文件 108 条。检查项:不要依赖任何默认 display / flex-direction / overflow / white-space,新代码一律显式声明。

③ 自定义 tabbar 五个图标全空。 两个原因叠在一起:vite dev 对 .cjs 返回 application/node,浏览器拒执行;UMD 内容在 ESM 上下文里 mod.default 拿到空对象。把 vendor 复制成 .mjs、尾部追加 export default globalThis.lottie,并加契约测试禁止回退 .js。检查项:动态 import 的失败常被 void 吞掉,要单独断言资源真的渲染了。

④ 弹层被撑出屏幕。 蒸汽编译器直接剥掉 <scroll-view scroll-x>,web 的 classic 实现又只认 scroll-x、不认 App 的 direction="horizontal"。修法是 7 处横滚全部条件编译双写,web 兜底 CSS 放 index.html(.uvue 的 style 会被 scoped 化,后代选择器命中不了组件内部节点)。检查项:窄视口(375)实测,且换端口无缓存复验——同名静态资源缓存给过一次假阴性。

⑤ 会话详情页刷 ReferenceError: getThemeCardStyle is not defined。 批量注入 import 的脚本只扫了脚本区,漏掉只在模板 :style 里用的名字和多行 computed 变体。补 28 处之外,更值钱的是新增了 themeImportsContract.spec.ts:逐文件比对「用到的 theme 导出名 ⊆ import 名单」。检查项:批量改写之后,验证的是「覆盖完整」,不是「有没有那行 import」。

⑥ 文件夹图标不显示。 就是第 2 节那个组件库双实现图标表不同步。检查项:组件库升级后,比对 .js / .uts 两份资源表的 key 集合。

⑦ 按钮文字变黑、间距全没了。 放到下一节单说,因为它是整套迁移里最贵的一课。

⑧ 迁移 13 天后才发现 PWA 三行 meta 丢了。 重写 index.html 时把 apple-touch-icon、apple-mobile-web-app-capable、apple-mobile-web-app-title 一起弄丢了,iOS 添加主屏图标回退成页面截图,也不再 standalone 启动。图标文件一直都在,纯属入口模板被覆盖。检查项:入口文件、manifest、静态资源清单做一次「新旧逐行 diff」,这类东西编译和单测都不会报警。

图 5:uvue 样式红线速查表,建议直接存一份

5. 最贵的一课:编译不报错,真机上全错

11 月初,真机截图反馈两句话:「按钮文字颜色不对或者不显示」「教程步骤、头像与右侧内容之间的间距失效」。编译器对 gap 只给一条 WARNING,运行期没有任何报错。

作者在 1080×2408 / 480dpi 的 Android 机上做了像素级测量(1 CSS px = 3 设备 px,1rpx = 1.44 设备 px):

位置声明期望实测
空态两按钮之间gap: 8px24 设备 px0
教程卡片之间gap: 18rpx26 设备 px4(描边,真实 gap = 0)
序号圆与文字gap: 16rpx23 设备 px0
序号「1」的文字色父级 color: #fff白(0,0,0)

根因两条:gap / row-gap / column-gap 在 uvue 被静默丢弃;<view> 上的 color 不继承给子 <text>。web 有继承,所以这个写法在 H5 上一直是对的,只有 App 端会暴露。

修法不是「全局替换」,是保留 web 语义 + 条件编译补偿:

/* 原有 gap 不动,H5 继续走 */
/* #ifdef APP */
.connections-tutorial__index { margin-right: 16rpx; }  /* row → margin-right */
.connections-tutorial__step  { margin-bottom: 18rpx; } /* column → margin-bottom */
.connections-tutorial__text  { color: #ffffff; }        /* 颜色下沉到 text 自己 */
/* #endif */

同一轮还修了另外两类:min-height: 100vh 被编译器直接判 ERROR(只收 number / pixel),26 文件 32 处改成 flex: 1;<up-button>前往添加</up-button> 这种裸文本在 uvue 里不生成文本节点,插槽拿到空内容、按钮塌缩成色块,55 处(33 文件)改成 text="前往添加" 属性。

合计 444 条 gap 规则、126 处 color 下沉、32 处高度、55 处按钮,涉及 79 个 .uvue 文件。真机复测:按钮间隙 0 → 24 设备 px,教程卡片 4 → 25,序号「1」(0,0,0) → (255,255,255),编译无 Duplicate attribute(同一个子元素缺 gap 又缺 color 时必须复用同一个生成类,否则一个标签挂两个 class 属性直接报错)。

还有 61 条 gap 没自动处理:40 条父 class 只出现在 :class 动态绑定里、19 条子元素只有 :class、2 条已有同名 margin 怕覆盖。这些留在人工清单里逐条确认。

图 6:真机像素复测,编译通过不等于渲染正确

6. 人真正该交付的:把教训写回机器能执行的地方

真机验收完,如果只改完这 79 个文件就收工,下一个 AI 会话照样会写出 gap。这个分支最有价值的一步,是把结论固化成了三层:

  1. 规则层:AGENTS.md 新增「uvue 样式红线(蒸汽模式,2026-10-30 实测)」——禁用 gap、颜色写进 text 自身类、只支持纯 class 选择器、@media 不支持、以及一串实测无效属性(:deep()、伪元素、后代选择器、grid-template-columns、filter、backdrop-filter、color-mix()、translate3d、min-height: 100vh……)。最后一句是「新代码请直接写 margin,不要再加 gap」。

  2. 测试层:themeImportsContract.spec.ts 这类契约测试,专门盯批量改写的漏网之鱼;Lottie 契约断言 .mjs 存在且禁止 .js 回退。用例数从迁移时的 2189 涨到 2349。

  3. 记忆层:每次改动必须落一篇带时间戳的架构笔记,写清根因、修法、验证数据、给原生端的复刻提示。215 篇笔记里,光这次迁移就留了「Web 白屏」「布局默认值」「gap 与颜色继承」「iOS 图标恢复」好几篇。

于是闭环变成:AI 批量改 → 单测 + 编译 → 真机像素验收 → 人写一句红线 → 下轮 AI 自动遵守。人工的产出不是代码行数,是约束条件和验收口径。

图 7:验收闭环——人只需要在两个节点上做判断

7. 可以直接带走的清单

迁移前 5 问(有一问答不上来就别开工):

  1. 要发哪些端?只做微信、支付宝小程序的可以按本文路径迁;其他小程序平台还在等适配(抖音小程序仍在官方 2026 路线图里,百度、QQ、快手等未列出),先留在老 uni-app;发 App 的进排期。
  2. 核心组件库有没有同接口的 uni-app x 版本?有没有 .vue / .uvue 双实现的 parity 门禁?
  3. App 原生插件、原生组件插件、plus API、wxs / renderjs 各有多少处?(官方明确:原生组件插件不能复用、plus 不支持)
  4. 现有自动化测试覆盖到什么程度?没有就先在老工程补齐——官方说两边的测试例是兼容的。
  5. 谁来做真机验收?Web 编译通过不能代表 App 渲染正确。

四道验收门:单测全绿 → HBuilderX Web 编译/发行 → Web 窄视口实机(无缓存环境)→ App 真机像素复测。每道门单独跑,别合并成一句「构建通过」。

给 AI 的规则模板(照着 AGENTS.md 抄就行):

## uvue 样式红线(蒸汽模式,实测日期 + 机型)
- 不要用 gap / row-gap / column-gap:间距只能用子元素 margin,
  row → margin-right,column → margin-bottom。
- <view> 上的 color 不继承给子 <text>,文字颜色写在 text 自己的类上。
- 只支持纯类选择器;#id / 标签 / [attr] / 后代 / :nth-child / :deep() 全部无效。
- @media 不支持,响应式靠条件编译或运行时算 class。
- 不要依赖任何默认 display / flex-direction / overflow / white-space。
- 每次改动必须更新一篇架构笔记:现象、根因、修法、验证数据。

图 8:迁移检查清单,逐条打勾再进下一阶段

8. 边界:这套做法没覆盖什么

别把上面的数字当成通用结论。它们是一个项目、一个版本窗口里的实测:HBuilderX 5.33 alpha、uview-ultra 4.5.50 → 4.5.85、Android 标准基座,web 走的仍是 VDOM 管道。

案例自己也留了一串没做完的事:Android 蒸汽端冒烟没跑起来(CLI 只编译不部署,无 GUI 环境建不起回连通道,得在 HBuilderX 里手动点一次「运行到模拟器」);App 端 SQLite 与外链跳转还没接 uts 插件;CSS 变量继承穿透 styleIsolation: 'app-and-page' 未在真机验证;61 条动态 class 的 gap 待人工确认;桌宠组件因为 uni-app x 没有 App.vue 根组件机制,暂缓挂载。

还有一条容易被忽略的官方边界:老 uni-app 和 uni-app x 蒸汽模式之间,原生组件插件不能复用,API 插件(uts 开发)可以。如果你的 App 深度依赖某个原生视图插件,迁移成本主要在那儿,不在 CSS。

还有一条平台适配边界:本文实测发生在 App、web 与微信小程序、支付宝小程序这一组目标端上。第 5 节那套 CSS 红线只针对 App 原生渲染——官方写的是「uni-app x 在 web 和小程序,支持完整的浏览器 CSS,在 app 平台,由于是原生渲染,支持的是 CSS 的子集」,所以 gap 被丢、颜色不继承这些坑不会在小程序端复现,别照着改一遍小程序代码。

另外,官方页面的 2026 路线图里仍列着「抖音小程序」「web 平台蒸汽模式」,百度、QQ、快手等小程序平台未列出;这些端要等适配,别把它们和微信/支付宝排进同一批迁移。老 uni-app 的小程序平台继续可用,等适配期间留在原框架是官方允许的选择。

小结

三句话收尾:

  • 「停止维护」有明确对象和时间点,先读准官方 FAQ,别按「框架要没了」做决策。
  • 迁移能不能低成本,第一决定因素是核心组件库有没有兼容版本;第二才是 AI 能改多少。没有前者,后者省下来的工时会被重构吃回去。
  • AI 负责从 0 到 99,人负责 99 之后:定红线、跑真机、把每一次教训写回规则与契约测试。验收指导不是收尾工作,是迁移的主线。

第 5 节那张样式红线表建议存一份,第 7 节的 5 问可以直接贴到立项文档里。

你们项目里卡住迁移的是哪一层——目标小程序平台还没适配、组件库没有 x 版本、原生插件替换,还是根本没自动化测试兜底?贴一下你的目标端和依赖清单,我可以按这份 5 问帮你估一下改造面。


资料来源:uni-app x 官方文档「uni-app x 是什么?」页(FAQ「老 uni-app 还维护吗?」、跨平台列表与 2026 路线图)、官方《uni-app升uni-app x指南》(上次更新 2026-10-30)、uview-ultra 插件市场页(4.5.86,2026-11-08)、ijry/mcode 仓库 task/uniappx-vapor-migration 分支的提交说明与 docs/mcode-architecture-notes/ 架构笔记。仓库与文档链接发布时按平台规范补充。