小程序开发有种错觉:上手很快,跑通几个页面很容易;可一到上线前、或者用户量上来,各种问题就冒出来了——白屏、卡顿、审核被拒、真机和模拟器表现不一样。
这些问题很少是语法错误,更多是小程序运行机制带来的坑。这篇文章不罗列知识点,只讲 5 个最高频的问题,最后给一套可以复用的排查顺序。
01 包体积超限:还没上线,就被 2M 卡住了
最尴尬的场景是:功能都做完了,上传代码时提示“主包体积超过 2M”,或者总包超限。这不是 bug,而是平台的硬性规定:主包不能超过 2M,整个小程序所有分包合计不超过 30M(服务商代开发的小程序不超过 20M)。
超限的常见原因:本地图片太多太大、npm 依赖没有按需引入、页面没有拆分、打包时保留了 sourcemap 和未使用代码。
处理方案:
- 大图、视频等资源外置:放 CDN 或云存储,代码包里只留小图标
- 按业务模块拆独立分包:主包只保留启动页、TabBar 页面和公共资源
- npm 依赖按需引入,定期用构建分析看哪些库占了体积
- 勾选代码压缩,去掉 sourcemap,清理未使用的页面和组件
注意:主包 2M 是硬限制,不支持申请扩容,正确做法就是分包和资源外置。
02 setData 卡顿:页面越用越卡,问题多半在数据更新
小程序是双线程架构:逻辑层和渲染层分离,每次 setData 都要把数据序列化、跨线程传到渲染层。数据量一大、调用一频繁,通信成本就上去了。官方文档指出,影响数据更新性能的主要因素有两个:更新的数据量,以及组件 Shadow 树的节点总量——后者的影响更大。
处理方案:
- 只 setData 渲染层真正用到的字段,不要把整个大对象一次塞进去
- 高频更新做合并和节流:滚动、进度条这类场景,把多次更新攒成一次
- 长列表用分页或虚拟列表,不要一次性渲染几百条
- 把独立 UI 封装成自定义组件,缩小每次更新涉及的节点树
- 纯展示逻辑交给 WXS 在渲染层处理,减少跨线程通信
- 不要在 onLoad 里同步做耗时操作,先渲染首屏再补数据
03 登录态失效:明明登录了,接口却一直报 401
小程序登录的正确链路是:wx.login 拿到临时 code,交给后端,后端再用 code 换 openid 和 session_key,最后下发你自己的 token。问题常出在几个地方:把 code 或 session_key 直接存在本地当凭证用(code 有效期很短、只能用一次);token 过期后没有刷新机制;多个请求同时失败时,带着旧 token 的请求一起发出,刷新逻辑互相打架。
处理方案:
- 前端只持有自己的 token,openid、session_key 一律留在后端
- 请求统一封装:遇到 401 先静默刷新 token(重新 wx.login 换新 token),再重放原请求
- 刷新过程加并发锁,同一时间只允许一个刷新请求,其余请求排队等新 token
- 登录态收敛到全局处理,不要在页面里各写一套登录逻辑
04 真机与工具不一致:模拟器好好的,真机就白屏
开发者工具的内核和真机渲染环境并不完全一致,真机还会多出授权弹窗、系统配置、真实网络这些变量。所以“工具里正常”只能说明代码没写错,不能证明真机没问题。
处理方案:
- 先看真机日志和 vConsole,别靠猜
- 检查隐私接口声明:定位、相册、蓝牙等能力要在后台的“用户隐私保护指引”里声明,并按规范触发授权
- 检查 request 合法域名:开发阶段勾选“不校验合法域名”只是临时方案,上线前必须配置好并校验
- 用真机调试和远程调试复现,重点在低端安卓机上验证性能和稳定性
- 上线前按“最新 iOS + 低端安卓 + 多个基础库版本”过一遍关键流程
05 兼容性:同一个页面,两个手机两种样子
样式错乱、某个 API 在新手机上能用、在旧手机上就报错——本质是基础库版本和机型适配的差异。新能力依赖更高的基础库版本,旧版本会直接不支持;刘海屏、底部安全区、不同厂商的 webview 内核也会让页面表现不一样。
处理方案:
- 用 wx.canIUse 或基础库版本判断做能力降级,老版本走老逻辑
- 在后台设置最低基础库版本,并评估目标用户的版本分布
- 用 rpx 做响应式尺寸,用 env(safe-area-inset-bottom) 适配安全区
- 复杂页面先想清楚渲染模式:Skyline 和 WebView 渲染的能力与限制不同,按页面形态选择,不要默认全用一套
- 升级基础库或依赖后,做一次全量回归
遇到问题,按这四层顺序排查
与其遇到问题就改代码,不如先建立一套固定排查顺序,大多数问题都能在前两层定位:
第一层,看报错:vConsole、开发者工具 Console、真机日志,先拿到确切错误信息。
第二层,查配置:合法域名、隐私声明、分包配置、基础库版本、AppID 环境。
第三层,查数据:setData 数据量、接口返回、缓存和 storage 读写。
第四层,查环境:机型、系统版本、基础库版本、渲染模式、网络。
按这个顺序走一遍,能覆盖大部分问题:配置类问题最隐蔽,但往往就是一行配置的事;性能和兼容性问题,则需要回到上面 5 个专项里去解决。
写在最后
小程序开发的问题,绝大多数不是“写得不对”,而是“对小程序的运行机制理解得不够”:包有体积上限、数据更新有跨线程成本、登录有固定链路、真机有真实环境、能力有版本门槛。
建议在项目启动时就把这几件事定成规范:分包边界、setData 纪律、统一的请求封装、隐私声明清单、基础库版本策略。提前立好规矩,比事后救火省事得多。