一套代码,五个战场:uni-app 多端项目全栈工作笔记
选型 · 架构 · 发版 · 踩坑 · AI 辅助开发实录
------ 一名被五端发版毒打过的前端全栈
写在前面
技术博客很容易写成操作手册------第一步点哪里、第二步勾什么。但我想记录的其实是另外三件事:
- 为什么这样选(选型的边界在哪里,哪些能力不能硬扛);
- 哪里会塌(哪些坑是结构性的、躲不掉的,而不是手滑);
- 怎么让团队不重复踩坑(流程和纪律怎么落地,而不是靠个人记忆)。
以及,作为这个时代的前端,绕不开的一个话题:AI 辅助开发。这篇笔记里我会穿插记录 AI 在我真实工作流里的位置------它确实帮我省了大量时间,但也确实给过我几回"看似正确、实则致命"的建议。怎么用、怎么防,都会写到。
说明:文中版本号与平台政策以写作时的官方文档为准,各平台迭代很快,落地前请自查;文中项目数据为作者团队实际复盘内容,供参考替换。
第一章 选型决策记录:为什么是 uni-app,边界在哪
1.1 业务需求与约束盘点
选型的第一步不是打开技术社区,而是把需求和团队摊在桌面上。我习惯先填两张表。
表 1|目标端清单
| 端 | 用户占比(约) | 核心场景 | 特别关注 |
|---|---|---|---|
| 微信小程序 | 55% | 获客、轻量使用、社交裂变 | 包体积 2M/30M、微信审核、隐私接口声明 |
| H5 | 25% | 外部链接、公众号跳转、SEO 补充 | 部署路径、浏览器兼容、跨域 |
| Android App | 12% | 重度用户、消息推送、离线 | 证书/签名、渠道包、厂商推送、低端机 |
| iOS App | 6% | 重度用户、支付习惯好 | 上架审核、ATT 隐私、描述文件有效期 |
| 鸿蒙 App | 2%(增长快) | 政策方向、华为生态 | 发布证书手动申请、AGC、审核规范 |
占比不用精确到小数,但它决定了一件事:哪端的体验崩了最疼。对我们来说是小程序,所以性能预算和发版节奏都要向它倾斜。
表 2|硬约束盘点
- 是否必须上架应用商店:是(iOS App Store / 华为 AGC / 安卓各商店);
- 是否接受热更新限制:接受(原生级改动必须走审核,JS 级改动可热更);
- 是否有原生硬件能力需求:有------蓝牙(智能硬件)、NFC(门禁模拟)、推流(直播预览);
- 是否有后台保活 / 推送需求:有(厂商推送通道)。
两张表填完,结论其实已经出来了:我们需要一个以 Vue 为中心、能覆盖五端、发版链路短的技术方案,且不能依赖原生人力。对当时的我们来说,uni-app 几乎是唯一解。
1.2 框架对比的关键结论
选型会上我们认真比过四个候选:uni-app、Taro、Flutter、React Native。网上对比文章一大把,我只讲两个后来被验证为关键的认知。
第一,uni-app 的本质是"编译器"而不是"运行时"。
这决定了它的能力和边界:它不是让一份 JS 在五端解释执行,而是把 Vue 代码编译成各端的原生产物 ------H5 走 DOM,小程序走 WXML/WXSS,App 走 WebView 渲染 + JS 引擎逻辑(部分页面可用 NVUE 原生渲染),鸿蒙方向有 uni-app x 直接编译为 ArkTS 原生。这句话看着像概念,实际上决定了后面所有坑的分布:凡是你依赖了"运行时行为"的地方(DOM API、动态模板、平台私有 API),编译不过或行为漂移是必然的。理解了"编译期"思维,第四章的坑你基本能提前预判一半。
第二,"不选 Flutter / RN / Taro"的理由要白纸黑字记下来。
| 对比项 | uni-app | Taro | Flutter | RN |
|---|---|---|---|---|
| 团队语言栈 | Vue 零成本 | React(可迁 Vue3) | Dart(需学习) | React/JS(可上手) |
| 小程序支持 | 微信/支付宝/抖音等多端原生 | 多端 | 需第三方桥 | 不原生支持 |
| App 端 | WebView / NVUE / uni-app x | WebView/H5 | 自绘引擎,性能强 | 原生组件 |
| 鸿蒙支持 | uni-app x 原生编译 | 有限 | 有限 | 有限 |
| 国内发行链路 | HBuilderX 云打包 + 多商店上传 | 一般 | 需自行搭建 | 需自行搭建 |
| 团队维护成本 | 低(Vue 生态 + 官方封装) | 中 | 中高 | 中高 |
| 原生能力 | 插件市场 + 原生模块扩展 | 插件生态一般 | 强(但需 Dart 写) | 强(但需原生配合) |
选型结论一句话:业务页面、表单、列表、状态管理 → uni-app 完全覆盖;推送、支付、音视频采集、后台保活 → 评估原生插件或原生模块,不强行桥接。我们最终的做法是:核心业务全在 uni-app,蓝牙 / NFC / 推流三个能力走原生插件(插件市场选型 + 一个外包原生开发兜底),把"桥接面"压到最小------桥接面越小,跨端维护成本越低。
选型会最后一条决议也值得记:"不选 X"的理由和"选 Y"的理由同等重要。三个月后若有人质疑"当初为啥不用 Flutter",直接把这张表拍出来,能省一场争论。
1.3 版本锁定策略
多端项目的头号隐藏风险是工具链漂移:HBuilderX 升个版本,编译器行为变了,五端产物集体变化,回归成本直接翻五倍。
我们的基线锁定:
- Vue 3 + Vite + Pinia(2024 年后 uni-app 官方 Vue3 已是默认);
- uni-app 编译器版本随 HBuilderX 锁定(不追新,除非有必须的功能);
- 每次大版本升级必须过"回归清单"(见第五章附录),升级日排在发版窗口外单独执行。
血的教训:有次我们顺手升级了 HBuilderX,第二天小程序包多了 40KB、某个 H5 页面白屏------查了一下午,根因是编译器对静态资源处理的变更。从那以后,"编译器版本"和"运行依赖版本"一样进锁文件,不随手下。
1.4 AI 辅助选型:让 AI 发散,让人收敛
选型期 AI 帮了我不少忙,但方式可能和很多人想的不一样------我没有让 AI 替我做决定,而是让它干三件事:
- 生成对比表初稿 :把对比维度丢给 AI,让它填"uni-app vs Flutter vs Taro vs RN"的优缺点,作为讨论素材。AI 的初稿覆盖度不错,但我发现它有幻觉------某个框架"支持 XX 功能"其实是两年前的旧闻,甚至是不存在的 API。每一条都回官方文档核过才进表。
- 反向挑刺:让 AI 扮演"反对派",列出"不选 uni-app 的十个理由"。这比直接问"选什么"更有用,逼我们提前想清楚反驳与兜底。
- 把约束清单翻译成问题:把硬约束(上架、蓝牙、推送)贴给 AI,问"如果这些是硬约束,哪些端差异会在开发中致命"。AI 给出的清单里有几条我们确实没想到(比如鸿蒙的证书配额、iOS 的 ATT 合规),直接进了第二章的风险清单。
总结:AI 是很好的发散引擎,但收敛(决策)必须由人来做。这个原则贯穿了我后面所有 AI 辅助开发的实践,后面还会反复出现。
第二章 架构设计与工程约束:把"一套代码"控制在可维护范围
2.1 目录结构与分层
"一套代码"不等于"一个文件里塞五端逻辑"。我们的目录长这样:
text
src/
├── pages/ # 页面(按业务模块分目录)
│ ├── home/
│ ├── order/
│ └── mine/
├── components/ # 全局组件(easycom 自动注册)
├── platform/ # 平台适配层(登录、支付、存储的差异封装)
│ ├── auth.js
│ ├── pay.js
│ ├── storage.js
│ └── device.js
├── api/ # 接口层(按业务模块拆分)
├── store/ # Pinia(用户、配置、业务状态)
├── utils/ # 请求封装、校验、格式化
└── uni.scss # 全局样式变量
核心原则一句话:平台差异不散落在页面里,统一收口到 platform/ 目录,页面只调用统一接口。
这条纪律是整个架构的地基。它意味着:登录接口三端实现不同?那是 platform/auth.js 的事,页面里永远只调 login()。微信和小程序的 storage API 不同?那是 platform/storage.js 的事。页面代码保持"平台无关",跨端 bug 才能从"全项目排查"缩小到"一个文件排查"。
2.2 条件编译的使用纪律
uni-app 的条件编译(#ifdef)是双刃剑:用得好是优雅的适配,用得烂是灾难。
允许:
- 在
platform/层使用#ifdef MP-WEIXIN / APP-PLUS / H5处理 API 差异(登录、支付、文件操作)。
禁止:
- 在业务页面中出现大段条件编译------一旦出现,说明该能力应下沉到适配层。
样式限制:
- 样式中的条件编译仅限安全区、导航栏高度等系统级差异。
反面教材(页面里的平台代码,Review 会被打回):
vue
<template>
<!-- 反面教材:业务页面里出现平台分支 -->
<view v-if="isWeixin">...</view>
</template>
<script setup>
// 反面教材:页面里直接判断平台
const isWeixin = typeof wx !== 'undefined'
if (isWeixin) {
uni.login({ ... })
} else {
// H5 走公众号 OAuth
}
</script>
正面例子(下沉到 platform/auth.js):
js
// platform/auth.js ------ 三端登录差异收口
import { loginByWeixin, loginByApp, loginByH5 } from './auth.impl'
export async function login() {
// #ifdef MP-WEIXIN
return loginByWeixin()
// #endif
// #ifdef APP-PLUS
return loginByApp()
// #endif
// #ifdef H5
return loginByH5()
// #endif
}
Review 时我们对条件编译有一个硬指标:业务代码里出现 #ifdef 的次数应趋近于零 。每次出现都追问一句"为什么不收口到 platform/?"------追问几次,纪律就建立了。
2.3 状态管理与持久化
状态管理我们选 Pinia,但持久化没有用第三方插件,而是手动封装。原因很实际:第三方存储插件在小程序端的兼容性坑(同步/异步、序列化、命名空间)我们踩过,不值得省那几行代码。
js
// utils/persist.js ------ 统一的持久化封装
export function getStorage(key, def = null) {
try {
const raw = uni.getStorageSync(key)
return raw === '' || raw === undefined ? def : raw
} catch (e) {
return def
}
}
export function setStorage(key, val) {
uni.setStorageSync(key, val)
}
Token 存储策略:小程序 / App 用 uni.setStorageSync,H5 同步走 localStorage,封装统一入口 (就是上面的 persist.js)。业务侧一律 setStorage('token', ...),谁也不需要知道背后是哪个 API。
2.4 请求层设计
请求层是跨端坑最密集的地方之一。我们用统一拦截器把差异全挡住:
js
// utils/request.js ------ 统一请求封装(节选)
import { getStorage } from './persist'
const BASE_URL = {
// #ifdef H5
'/api': '/api',
// #endif
// #ifndef H5
'https://api.example.com': 'https://api.example.com',
// #endif
}[0]
export function request(options) {
return new Promise((resolve, reject) => {
uni.request({
url: BASE_URL + options.url,
method: options.method || 'GET',
data: options.data,
header: {
'Content-Type': 'application/json',
Authorization: getStorage('token')
? `Bearer ${getStorage('token')}`
: '',
...options.header,
},
success: (res) => {
if (res.statusCode === 401) {
// 统一 401 处理:清 token,跳登录
uni.removeStorageSync('token')
uni.navigateTo({ url: '/pages/login/index' })
return
}
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data)
} else {
uni.showToast({ title: res.data?.message || '请求失败', icon: 'none' })
reject(res)
}
},
fail: (err) => {
uni.showToast({ title: '网络异常', icon: 'none' })
reject(err)
},
})
})
}
各端差异要单独记:
- 小程序端:部分方法(如 PUT/DELETE)在不同基础库版本的兼容要做兜底;请求域名必须配白名单,否则开发环境都报"不在以下 request 合法域名列表中";
- H5 端:跨域凭证(cookie/credentials)、CORS 配置;本地开发要配代理;
- App 端:SSL 证书校验策略、自签名证书在安卓低版本的兼容。
2.5 平台适配层实战
适配层最经典的案例是登录。三端登录机制完全不同:
| 端 | 登录方式 | 要点 |
|---|---|---|
| 微信小程序 | uni.login() 拿 code → 后端换 openid |
code 一次性、需在 onLoad 后调用 |
| App(iOS/安卓) | 微信 SDK / 手机号一键登录 | 需配置 SDK 回调、universal link |
| H5 | 公众号 OAuth / 手机号验证码 | 需授权域名、回调页 |
适配层把这一切收口成 login(),页面只关心"用户有没有登录"。支付同理:小程序微信支付、App 微信/支付宝 SDK、H5 微信 JSAPI/支付宝,全部收口到 platform/pay.js。
2.6 AI 辅助架构实践
架构阶段 AI 干了三件实事:
- 生成适配层骨架 :把接口契约(
login() / pay() / storage)丢给 AI,让它按platform/模式生成三端实现骨架。提示词示例:
text
我在做 uni-app 多端项目,需要 platform/storage.js 适配层:
- 小程序/App 用 uni.setStorageSync,H5 用 localStorage
- 对外只暴露 get / set / remove 三个函数
- 请生成完整实现,并标注每个 #ifdef 的编译条件
AI 生成的骨架 80% 可用,剩下的 20% 是我们手工补的边界(序列化、错误捕获、隐私模式降级)。
-
审查条件编译越界 :把 PR 的 diff 贴给 AI,专门问"哪些地方出现了业务页面内的
#ifdef"。这个活儿 AI 干得又快又准,比人扫代码高效得多。 -
生成跨端差异矩阵:让 AI 把已知的平台差异整理成文档,作为新人培训材料。
但这里我必须记录一次翻车:AI 在生成"小程序端支付实现"时,给我写了一个 wx.requestPayment 的配置对象,字段名和真实 API 对不上,真机一调就报错。平台 API 的细节,AI 的"记忆"不可靠,必须以官方文档为准 。从此我们立了一条规矩:AI 生成的平台相关代码,必须附上官方文档链接才能合入。
第三章 多端打包发版操作流程(逐端清单)
3.1 H5 发版
H5 看着最"简单",其实坑也不少。
构建:
bash
npm run build:h5
注意:HBuilderX 4.06+ 开始,构建产物目录从 unpackage/dist/build/h5 改成了 web。这是个隐蔽大坑------很多团队的 CI/CD 脚本还写死在 h5 目录,升级后产物为空,线上直接白屏。我们第一时间改掉了脚本,并把这个目录变化写进了升级回归清单。
路径配置 :部署到子路径(如 www.example.com/h5)时,必须在 manifest.json → h5.router.base 配置,否则资源 404。
部署后验证清单(三件事必查):
- 静态资源 404(js/css 引用路径);
- 路由刷新 404(history 模式需要服务端 fallback 到 index.html);
- 跨域接口连通性(生产环境 CORS)。
3.2 微信小程序发版
流程:配置 AppID → HBuilderX 发行 → 微信开发者工具上传 → 提交审核 → 发布。
易错点(每一条都有人栽过):
- 域名白名单未配 :request/uploadFile/downloadFile 的合法域名必须在公众平台配置,且不支持 IP 和端口,开发环境要勾"不校验合法域名";
- 包体积超限:主包 ≤ 2M、总包 ≤ 30M(服务商代开发 20M)。超了就分包------分包 + 图片懒加载 + 控制 vendor 体积是常规操作;
- 隐私政策接口未声明:微信强制要求在后台声明隐私接口(收集用户信息、手机号等),不声明直接审核不过;
- 审核类目与页面不符:类目选错会被打回,提前对照类目表。
3.3 Android App 发版
打包方式:
- 云打包:HBuilderX 云端打包,无需本地安卓环境,适合没有原生环境的小团队;
- 本地打包:配置好安卓 SDK 后本地出包,适合需要自定义原生模块的场景。
证书管理(最容易出事故的一条):
- 云打包证书与本地打包证书分离,证书密码存团队密码管理器,不写项目文件(写进 Git 等于裸奔);
- keystore 丢失 = 应用无法更新,只能换包名重新上架------这不是玩笑,见过团队这么死过一次。
渠道包:一套代码多渠道构建,渠道号走构建参数注入,不手工复制工程。渠道信息在代码里通过注入的 manifest 变量读取。
商店提审材料 :各商店截图尺寸、隐私政策、权限说明模板归档在仓库 release/ 目录,每次发版直接取用,别每次现做。
3.4 iOS App 发版
没有 Mac 也能上架:云打包 + uni 多商店上传(DCloud 应用发行平台)可以免 Mac 完成 App Store 上架流程------证书申请、构建、上传到 TestFlight、提交审核,全部走云端。这对没有苹果电脑的小团队是救命功能。
证书与到期管理:
- iOS 描述文件(Provisioning Profile)有有效期,过期后构建直接失败;
- 推送证书(APNs)同样有有效期,到期不续 = 用户突然收不到推送;
- 建议:证书到期时间单独进日历提醒,提前 30 天预警。
审核避坑(都是血泪):
- 隐私弹窗时机:首次启动的隐私政策弹窗文案和时机必须合规,苹果对"首次启动收集数据前未弹窗"零容忍;
- ATT 授权文案 :iOS 14.5+ 的 App 跟踪透明度,文案要说明用途,且不要在弹窗出现前偷偷调用 IDFA;
- 账号删除入口:涉及用户生成内容的 App 必须提供"删除账号"入口,且删除流程要走得通(审核员真会测)。
3.5 鸿蒙发版(重点记录)
鸿蒙是目前五端里流程最绕、文档最分散的一端,值得单独展开。
签名证书:
- 发布证书只能在 DevEco Studio 中手动申请 ,申请完成后把证书相关文件配置到
harmony-configs/build-profile.json5的release配置项; - 调试证书可以自动申请(HBuilderX 运行界面自助),但上架必须用发布证书。
AGC 证书数量限制 :每个开发者账号证书有配额,过期证书要定期清理,否则新证书申请会被卡。我们被卡过一次,排查半天才发现是配额满了。
授权 DCloud 上架 :鸿蒙应用 / 元服务可以授权 DCloud 完成上架流程。绑定服务商后,HBuilderX 发行可直接把构建产物上传到 AGC 提审,不用自己走一遍 AGC 上传。
包名一致性 :鸿蒙工程包名必须与 manifest.json 中的一致,否则证书失效。这个坑很隐蔽------改过一次包名没同步,提审直接被拒。
2026 年新增的两条注意事项:
- DevEco Studio 26.0.0 起支持 AGC 云管理证书和上传时自动重签,签名流程简化不少,但老项目迁移时要注意证书指纹的关联配置(推送服务需要添加公钥指纹);
- 华为 AGC 上架要求声明 AI 生成合成内容标识 :应用内如果包含 AI 生成内容,必须选"涉及"并上传 AI 标识材料。我们项目里有 AI 生成头像功能,这条直接触发合规要求------做 AI 功能的多端应用,上架合规记得提前查各商店的 AI 内容政策。
3.6 AI 辅助发版
发版是"重复 + 易错 + 不容错"的场景,AI 在这里的性价比极高:
- AI 写发版脚本 / CI 流程:把五端发版的步骤描述给 AI,让它生成 Jenkins / GitHub Actions 的 pipeline 初稿。AI 对常见 CI 语法很熟,初稿能跑,我们再调;
- AI 生成发版检查清单:把"发版前要确认的事"丢给 AI 结构化,生成附录里的 Checklist 初稿,再人工补平台特有项;
- 证书到期提醒自动化 :配合定时任务,把 iOS 描述文件、鸿蒙发布证书、APNs 推送证书的到期日做成提醒,到点自动发通知------这件事的价值远大于写十行代码,因为它防的是"静默失效";
- 提审材料初稿 :商店描述、更新日志(What's New)先让 AI 写初稿,人来改语气和合规措辞。注意:截图尺寸、权限说明、隐私政策这类硬信息绝不能让 AI 编,必须来自真实构建产物和真实代码。
第四章 实际困难与解决记录(现象 → 根因 → 解法)
这一章是全文最值钱的部分。我按"现象 → 根因 → 解法"的格式记录,方便团队直接查表。
4.1 样式类
| 现象 | 根因 | 解法 |
|---|---|---|
| H5 正常,App 低端机样式崩 | Android 4.4 WebView 不支持新 CSS(部分 flex/grid 特性) | 避免新语法;低端机降级方案;或引入 X5 内核 |
| 底部按钮被 iPhone 黑条遮挡 | 未适配安全区 | padding-bottom: env(safe-area-inset-bottom);iPhone X+ 必查 |
| H5 上 rpx 被放大 | PC/大屏浏览器宽度大,rpx 按比例放大 | manifest 配置 h5.rpxCalcMaxDeviceWidth: 960 限制最大换算宽度 |
| 自定义导航栏各端高度错位 | 状态栏、胶囊、H5 导航栏机制不同 | 封装 CustomNavbar 组件,用 uni.getSystemInfoSync 动态计算 |
展开案例:自定义导航栏 。小程序有胶囊按钮,App 有状态栏,H5 有浏览器标题栏,三端"顶部"的物理结构完全不同。第一版每个页面自己写导航栏样式,结果五个页面五种高度。后来统一封装 CustomNavbar,内部用 uni.getSystemInfoSync() 取状态栏高度,小程序端再量胶囊位置,一次计算,全局复用。凡是"系统级差异",都要做成组件/常量收口,不允许页面各写各的。
4.2 逻辑 / API 类
| 现象 | 根因 | 解法 |
|---|---|---|
| v-html 在小程序无效 | 小程序不支持 v-html,只有 rich-text | 改用 rich-text 组件;富文本字段统一在适配层转换 |
| 登录逻辑三端分裂 | 微信授权 / App SDK / H5 公众号机制不同 | 收口到 platform/auth.js,统一暴露 login() |
| 动态组件报 "Component is not found" | 小程序端动态引用组件导致静态分析失败 | 禁止字符串拼接组件路径,用静态 import + v-if 切换 |
| getApp() 拿到 undefined | App 生命周期与页面生命周期时序差异 | onLaunch 里同步初始化全局数据,页面侧做空值保护 |
| 部分机型 getSystemInfoSync 拿不到 | 部分机型同步 API 偶发失败 | 用异步 getSystemInfo + 缓存兜底 |
展开案例:动态组件 。我们曾用 :is="'comp-' + type" 动态切换组件,H5 跑得欢,一上小程序全报 "Component is not found"。根因是小程序端组件是静态编译的,运行时拼接路径无法解析。解法是改成静态 import 全部候选组件 + v-if 切换,代价是代码量多一点,换来五端一致。
4.3 性能类
小程序首屏慢 :分包 + 图片懒加载 + 减少主包 vendor 体积(把 echarts 等重库移到分包或按需加载)。小程序主包 2M 的硬限下,"把什么放进主包"是个持续博弈:我们的规则是主包只放首屏必需,其余全部进分包并按需预下载。
App 长列表卡顿:WebView 渲染瓶颈。两个方案:该页面改用 NVUE(原生渲染),或使用 recycle-view 组件做长列表复用。注意 NVUE 与普通 vue 页面的 API 子集不同,迁移要按页面评估。
H5 首屏白屏:路由懒加载 + 骨架屏 + 资源预加载。H5 是 SPA,白屏主要来自首屏 JS 太大,拆 chunk 是首选。
4.4 打包 / 发版类
| 现象 | 根因 | 解法 |
|---|---|---|
| 安卓包更新装不上 | 签名不一致(换证书 / 密码错) | 证书和密码统一管理,构建脚本固定 keystore 路径 |
| iOS 提交被拒 "Missing Privacy" | 隐私政策页缺失 / 不完整 | 隐私政策进仓库模板,发版前 Checklist 必查 |
| 鸿蒙提审证书失效 | 包名与 manifest 不一致 | 包名一致性进发版 Checklist |
| 线上小程序偶发白屏 | 分包预加载失败 + 缓存 | 预下载降级处理,失败回退懒加载 |
展开案例:证书过期连环事故。有段时间 iOS 推送"时好时坏",查了两周,最后发现是 APNs 推送证书过期------iOS 推送证书有效期一年,过期后推送静默失败,不报错。这个教训促成了两件事:证书到期全部进日历提醒;发版 Checklist 增加"证书有效期确认"一项。
4.5 AI 辅助排障实录
跨端问题排障时 AI 是好帮手,但要用对姿势。
有效姿势:把完整上下文给 AI------报错信息、运行端(小程序 / App / H5)、复现步骤、相关代码、uni-app 版本。AI 对这种"确定性排障"(语法、逻辑、配置)的准确率很高。比如"小程序端 uni.request 报 url not in domain list",AI 秒回域名白名单问题。
危险盲区:
- 跨端差异 :AI 经常不知道"某个 API 在某端不存在"。它给我建议过在小程序端用
localStorage(小程序是wx.setStorage),也建议过在 App 端用window.innerHeight(App 是 WebView 但没有完整 DOM)。凡是涉及平台特有 API 的建议,一律以官方文档为准; - 版本细节:AI 对"哪个版本开始 HBuilderX 产物目录变了""哪个微信基础库支持了什么"这类时效性信息的记忆不可靠,必须以官方文档 / 更新日志为准;
- AI 会自信地编 :它会一本正经地给一个不存在的配置项。所以我们的规矩是:AI 给的排障建议,先当"嫌疑人"而不是"结论",用最小代价验证,再应用到线上。
第五章 团队协作与组织能力(全栈视角的"非技术笔记")
5.1 代码规范与 Review 清单
多端项目的 Review 不能只看逻辑,要专门查"平台泄漏"。我们的 Review 清单分三类:
条件编译 Review:
- 业务页面是否出现了平台判断?(
#ifdef应只在 platform/ 层) - 这个平台差异能否通过统一接口消除?
样式 Review:
- 是否使用了
*选择器?(非 H5 平台不支持) - 是否硬编码了导航栏高度?(应用 CustomNavbar)
- 是否忘了安全区适配?(iPhone 底部按钮)
- rpx 在大屏下是否会放大失控?(rpxCalcMaxDeviceWidth)
API Review:
- 是否直接用了
window/document?(非 H5 不存在) - 是否直接 import 了浏览器专用库?(需条件编译或降级)
- 是否直接用了未验证的第三方 UI 组件?(小程序兼容性)
5.2 发版流程与权限管理
证书 / 密钥管理 :iOS 证书、Android keystore、鸿蒙证书统一存团队密码管理器(1Password / Bitwarden 这类),不存 Git、不传聊天群。密码管理器要设"只有发版负责人能读"的共享项。
发版 Checklist(每次发版前跑一遍,完整版见第六章附录):
- 版本号一致性(三端一致,且已递增);
- 环境配置注入确认(生产 baseURL);
- 隐私政策更新确认;
- 商店截图更新确认;
- 回滚包准备确认;
- 证书有效期确认。
热更新边界(写进团队规范,避免"以为热更了其实没生效"):
- 允许热更:JS 逻辑、样式、静态资源(uni-app 的 wgt 包);
- 必须重新提审:原生插件变更、权限新增、原生模块升级、商店审核要求的变更;
- 注意 App 端的 wgt 增量更新有平台差异(安卓可静默、iOS 有限制),别把"热更新"当成万能药。
5.3 新人上手路径
多端项目的新人最容易迷失在"五个端的环境搭建"里。我们固定了一套三天路径:
- 第一天 :跑通 H5 开发环境,理解
platform/适配层设计(读 auth.js / storage.js 的实现); - 第二天 :跑通微信开发者工具,知道条件编译怎么写(改一个
#ifdef看两端表现); - 第三天:参与一次测试包构建,阅读发版 Checklist,陪跑一次完整发版。
三天后新人能独立改需求而不闯祸,剩下的就是时间积累。
5.4 技术债务跟踪
"临时绕过的坑"如果不记录,三个月后没人记得为什么要绕。我们的做法是维护一张债务登记表(见附录),每笔债务记录:
- 问题描述 + 临时解法;
- 为什么临时(根因);
- 计划处置时间(如"Q3 迁移 NVUE");
- 责任人 + 状态。
例如:某个高流量页面为了快速上线用了 WebView 全量渲染,标记为"需迁移 NVUE,预计 Q3 处理"------这条债务跟着我们一个季度,因为记录在案,才没有变成永久债。
5.5 AI 赋能团队
AI 在我们团队不是"某个人的效率工具",而是团队级的工作流升级:
- AI Code Review 前置:合入前先让 AI 过一遍"条件编译越界 / window 泄漏 / 硬编码高度"三类检查,人工 Review 专注业务逻辑。效率提升明显,而且 AI 不会漏;
- AI 生成测试用例:多端兼容性测试矩阵(端 × 页面 × 功能点)让 AI 生成初稿,测试同学补边界。覆盖从"拍脑袋"变成"结构化";
- AI 维护文档 :发版 Checklist、差异速查表、新人文档的初稿由 AI 生成,人来校准------文档活是最适合 AI 的活,因为它是"已知知识的整理",不是"未知知识的创造";
- 提示词库沉淀:团队把高频提示词(条件编译审查、差异矩阵生成、排障上下文模板)沉淀成一个共享文档,新人直接复用,不用每次从零开始。
第六章 附录(随手查)
6.1 各端关键差异速查表
| 维度 | H5 | 微信小程序 | App(iOS/Android) | 鸿蒙 |
|---|---|---|---|---|
| 登录 | 公众号 OAuth / 手机号 | uni.login + 手机号 | 微信 SDK / 手机号 | 华为账号 |
| 支付 | 微信 JSAPI / 支付宝 | 微信支付 | 微信/支付宝 SDK | 华为 IAP |
| 存储 | localStorage | wx.setStorage | plus.storage | 偏好数据库 |
| 包体积限制 | 无(但影响加载) | 主包 2M / 总包 30M | 无硬限,但影响启动 | 类似 App |
| 推送 | 无(浏览器受限) | 微信订阅消息 | 厂商推送 + APNs | 华为推送 |
| 地图 | 网页地图 | 小程序地图组件 | 原生/高德 SDK | 华为地图 |
| 分享 | 网页分享 | 小程序转发 | 系统分享/微信 SDK | 华为分享 |
| 热更新 | 部署即更新 | 审核后发布 | wgt 包热更 | 元服务/应用审核 |
| 条件编译标识 | H5 | MP-WEIXIN | APP-PLUS | APP-HARMONY(uni-app x) |
6.2 发版前 10 分钟检查清单
- manifest.json 版本号已递增(三端一致)
- 生产环境 baseURL 已注入
- 隐私政策弹窗已配置(iOS/鸿蒙审核必查)
- 回滚包已归档到 release 目录
- 商店审核材料已更新(截图、描述、权限说明)
- 证书有效期确认(iOS 描述文件、APNs、鸿蒙发布证书)
- 小程序域名白名单确认
- 微信隐私接口声明已配置
6.3 常用命令与路径
bash
# H5 构建
npm run build:h5
# 查看鸿蒙设备 UDID
hdc shell bm get -u
# 鸿蒙证书配置路径
harmony-configs/build-profile.json5
# 构建产物目录(HBuilderX 4.06+)
unpackage/dist/build/web # 注意:以前是 build/h5
6.4 AI 辅助开发工具箱
常用场景与提示词模板:
- 适配层骨架生成:
text
我在做 uni-app 多端项目(微信小程序/App/H5),需要 platform/{X}.js 适配层。
对外只暴露 {接口},内部用 #ifdef 处理平台差异。
请生成完整实现,每个 #ifdef 标注编译条件,并给出官方文档链接。
- 条件编译越界审查:
text
以下代码来自 uni-app 业务页面,请找出所有平台相关代码
(#ifdef、window/document、平台特有 API),
并判断哪些应该下沉到 platform/ 适配层。
【代码】
- 排障上下文模板:
text
uni-app {版本},运行端:{小程序/App/H5}
报错:{完整报错信息}
复现步骤:{步骤}
相关代码:{代码}
请给出最可能的根因和最小验证方案。
使用原则(团队铁律):
- AI 是发散引擎,人是收敛引擎------决策、验收、上线永远人拍板;
- 平台特有 API 的建议必须回官方文档验证;
- AI 给的排障建议先当"嫌疑人",最小代价验证后再用;
- 文档初稿 AI 写,硬信息(证书、版本号、包名)人填。
结语:反思与展望
写这篇笔记时,uni-app 生态已经走过了"能不能跑通五端"的阶段,进入了"跑得稳、发得快、维护得起"的深水区。几个趋势值得记录:
- uni-app x 方向:直接编译到各端原生语言(Kotlin / Swift / ArkTS),性能和鸿蒙原生适配会更好,但代价是 API 子集更严。新项目值得评估,老项目按页面渐进迁移;
- 鸿蒙是长期变量:华为生态的政策和工具链还在快速变化(证书、AGC、AI 内容标识),鸿蒙在五端里的"流程最绕"地位短期不会变,值得单独投入维护一套文档;
- AI 不会取代多端工程师,但会取代不做记录的人:AI 能写代码、查报错、生成文档,但它记不住"我们项目为什么这样选""哪个坑的结构性原因"。团队的知识沉淀,才是 AI 无法复制、也无法替你积累的资产。
最后,给后来者五条建议,都是我摔过跤换来的:
- 先把"不选什么"写进文档,比"选了 uni-app"更能保护未来;
- 平台差异收口到适配层,页面代码保持平台无关,这是多端项目唯一的活路;
- 版本号、证书、包名是纪律不是技术,全部进 Checklist 和日历提醒;
- 发版流程要跑通到"回滚",能回滚的发版才是安全的发版;
- 让 AI 干活,让人记坑------AI 负责发散和整理,你负责记录"为什么"和"哪里塌"。
如果这篇笔记能帮你少加一个班的夜、少踩一个我踩过的坑,那就值了。
(完)------ 欢迎交流:如果你在 uni-app 多端项目里也踩过什么"结构性大坑",值得评论区补一条。