uni-app 一套代码多端发布实战:打包、兼容、踩坑与 CI 自动化方案
前言
uni-app 最大的卖点就是一次开发,多端分发,一份 Vue 代码可以编译输出 H5、微信 / 支付宝 / 抖音小程序、Android/iOS App、鸿蒙元服务等平台。但很多同学写完代码,卡在打包发布环节:同样的页面,H5 正常、小程序报错、App 样式错乱、证书打包失败、各平台审核规则不一样。
本文从发布前准备 → 各端打包流程 → 多端兼容核心手段 → 高频踩坑清单 → CI 自动化发布方案完整梳理,都是线上项目落地总结的实战经验。
一、发布前统一准备(所有端通用)
打包之前一定要做这几步,避免打包完才发现问题:
- manifest.json 配置校验
- 应用名称、版本号、appid、图标、启动图;图标必须准备多尺寸,小程序、App、H5 要求不一样;
- 权限配置:
permission,App 需要相机、定位、存储权限,小程序单独在平台后台申请权限; - 三方 SDK 配置:地图、推送、微信登录、支付等,这些配置只有打包后才生效,模拟器 / 真机预览不生效,很多人在这里踩坑uni-app。
- pages.json 检查
- 路由、tabbar、全局样式、分包配置;分包对小程序尤其重要,控制主包体积,避免超出 2M 限制。
- 统一规范:优先使用 uni 内置组件 尽量不要直接写
div / span,统一使用view / text / image;CSS 单位优先rpx,不要大量使用 rem、vw,不同平台渲染差异很大uni-app。 - 静态资源检查
- 图片资源尽量放到 static 目录;不要使用本地
file://路径; - 域名:所有接口、图片域名提前在各个平台后台配置白名单(小程序 request 域名、H5 跨域、App 网络安全域名)。
- 图片资源尽量放到 static 目录;不要使用本地
- 分支与版本管理 建议单独维护 release 分支,打包前合并测试分支,打包记录版本号、更新日志。
二、各平台打包发布详细流程
2.1 H5 发布
流程:HBuilderX 菜单 → 发行 → 网站 - H5 手机版
- 产物目录:
unpackage/dist/build/web - 部署:直接把 dist 静态资源丢到 Nginx、OSS、CDN;
- 重点坑点:
- 路由模式:
history模式需要后端配置 nginx 重定向,否则刷新 404;hash 模式不需要后端配合; - 相对路径:如果部署在二级目录,需要配置
publicPath,否则资源加载失败uni-app; - H5 不存在证书,但是跨域由后端 CORS 控制。
- 路由模式:
2.2 小程序(微信 / 支付宝 / 抖音等)
流程:发行 → 对应小程序(微信小程序)
- 产物:
unpackage/dist/build/mp-weixin - 步骤:
- 编译产出小程序源码;
- 导入对应平台开发者工具;
- 上传代码,提交后台审核;
- 重点:
- 每个小程序平台有独立 appid,不能混用;
- 包体积限制:微信主包 2M,分包单包 2M,总包 20M;图片、大资源尽量放 CDN;
- 平台特有 API:微信订阅消息、抖音开放能力,只能条件编译隔离。
2.3 App 端(Android /iOS)
两种打包方式:云打包(推荐新手)、本地打包
菜单:发行 → 原生 App - 云打包uni-app
- Android:需要签名证书;测试包可以 DCloud 自动生成测试证书,上架应用市场必须自己的正式证书;
- iOS:必须苹果开发者账号,打包需要
.p12证书 + 描述文件;证书过期会直接打包失败; - 云打包优势:不用本地装 Android Studio、Xcode;安心打包不会上传源码,适合商业项目;
- 产物:Android 得到 apk,iOS 得到 ipa;ipa 只能在 mac 或者云打包生成,Windows 无法直接打包 iOS;
补充:鸿蒙 Next / 鸿蒙元服务,HBuilderX 新版支持直接发行鸿蒙包,单独配置鸿蒙签名。
重要提醒:自定义调试基座 ≠ 正式包,基座用来真机调试,不能提交应用商店审核uni-app。
三、uni-app 多端差异如何处理(核心:条件编译)
这是 uni-app 多端项目的灵魂,也是面试高频考点。 语法:#ifdef、#ifndef、#endif #ifdef 平台:仅该平台编译这段代码 #ifndef 平台:除了这个平台,其他平台都编译
<template>
<!-- #ifdef H5 -->
<button @click="h5Login">H5网页登录</button>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<button @click="wxLogin">微信小程序登录</button>
<!-- #endif -->
<!-- #ifdef APP-PLUS -->
<button @click="appLogin">App原生登录</button>
<!-- #endif -->
</template>
<script>
export default {
methods: {
// #ifdef H5
h5Login() {},
// #endif
// #ifdef MP-WEIXIN
wxLogin() {},
// #endif
}
}
支持在 template、script、style 里面写条件编译,甚至可以按目录隔离:platforms/mp-weixin 目录,只在微信小程序生效,适合差异巨大的页面。
常见平台标识符
- H5:
H5 - 微信小程序:
MP-WEIXIN - 支付宝:
MP-ALIPAY - App(安卓 + ios):
APP-PLUS - 鸿蒙:
APP-HARMONY
原则:能复用就不写条件编译;只有平台独有能力、API、样式差异才隔离,过度使用会让代码难以维护。
四、多端样式、API、渲染引擎差异总结(踩坑重点)
- 渲染引擎不一样
- H5:浏览器 webview;
- 小程序:平台自研双线程(逻辑层、渲染层分离);
- App:默认 webview 渲染,nvue 是原生渲染; 同一个 css 属性,在 iOS WKWebView、安卓 webview、小程序渲染引擎表现不一样,很多样式 bug 只在某一端出现uni-app。
- API 能力差异
- uni 封装的基础 API(toast、storage、request)是统一的;
- 平台独有能力:微信小程序的 wx.getPhoneNumber、iOS 推送、鸿蒙能力,uni 无法抹平,必须条件编译。
- 样式坑
- 不要用过于新的 CSS:
filter、部分 css 变量在低版本 webview、老安卓 App 会失效; - 小程序自带默认样式,会覆盖你的 css;
- 页面高度 100vh 在 iOS App、小程序经常有底部安全区问题,统一用
uni.getSystemInfo获取安全区,或者--safe-area-inset-bottom。
- 不要用过于新的 CSS:
- 请求和跨域
- H5:浏览器同源策略,后端 CORS;
- 小程序:没有跨域,但是必须配置 request 合法域名;
- App:默认不校验域名(上线打包后可以开启校验)。
五、高频打包 & 上线踩坑清单(实战高频)
- 打包后 App 登录 / 支付失效:90% 是 manifest 里面 SDK 参数没填,预览基座不生效,打包才生效;
- iOS 打包证书报错:证书过期、钥匙串重复证书、描述文件不匹配;建议用 Appuploader 管理证书;
- 小程序审核驳回:包含隐私协议、未授权收集手机号、违规诱导分享;每个平台审核规则独立;
- 包体积过大:图片不压缩、引入大的第三方 npm 包、引入很多原生插件;方案:图片 CDN、分包、按需引入;
- 同样代码 H5 正常,App 白屏:大多是 es6 + 语法不兼容,或者异步逻辑、dom 操作写法不适合 webview;
- 条件编译写错大小写:
mp-weixin和MP-WEIXIN是不一样的,标识符大写; - 版本号混乱:H5、小程序、App 版本号各自独立,建议统一一套版本管理规范。
六、进阶:自动化 CI/CD 多端发布(工程化方案)
手动在 HBuilderX 点发行,版本多了非常低效,企业项目一般做自动化:
- 依赖 uni-cli,脱离 HBuilderX 图形界面,命令行打包;
- 接入 GitHub Actions / GitLab CI / Jenkins;
- 流程示例:
- git push release 分支触发流水线;
- lint 代码检查;
- 依次构建 H5 资源、小程序代码;
- 云打包 App(调用 dcloud 云打包 api);
- 自动上传到 OSS、小程序后台、输出打包报告;
适合团队、频繁迭代项目;个人小项目可以先用 HBuilderX 手动发行。
七、落地建议 & 架构选型总结
- 优先保证H5 + 微信小程序对齐,这两个端用户最多,问题最好复现;App 最后做适配;
- 封装一层统一业务 api,内部用条件编译分流不同平台逻辑,业务层尽量无感知;
- 测试策略:分端独立测试,不要 H5 测完就认为所有端没问题;
- 插件选型:优先 uni 官方插件;第三方原生插件大多只支持 App,小程序、H5 不能用。
结语
uni-app 的多端发布,难点不在 “一键打包”,而在于理解各平台底层引擎、审核规则、能力边界。框架给了你一套统一语法,但没有抹平所有平台差异。条件编译是工具,不是万能解药,合理控制差异代码,才能长期维护一套高质量跨端项目。
更多推荐




所有评论(0)