app端全局错误日志必须js层(uni.onerror/onunhandledrejection)与原生层(bugly/umeng等sdk)双通道捕获,缺一不可;二者需在app.vue onlaunch中立即注册、统一字段、分接口上报,并配合文件系统归档、智能上传策略及真机验证。

App端的全局错误日志必须分两层处理:JS异常靠uni.onError和uni.onUnhandledRejection捕获,原生崩溃必须用SDK(如Bugly、UMeng)补充,二者缺一不可。只做JS层上报,等于漏掉80%的真实崩溃。
uni.onError 和 uni.onUnhandledRejection 必须在 App.vue 的 onLaunch 中注册
延迟注册(比如放到某个页面或 store 里)会导致冷启动阶段的异常完全丢失——用户刚点开App就闪退,你收不到任何日志。
-
uni.onError能捕获同步错误、throw语句、生命周期钩子中抛出的异常,但不捕获Vue模板渲染错误(如访问undefined.name) -
uni.onUnhandledRejection只管未被catch的Promise拒绝,包括async/await里没写try/catch的情况 - 这两个API在H5和小程序里无效,纯属App端专属通道,别指望它跨端通用
本地存储不能只靠 uni.setStorage,得用文件系统存日志文件
错误日志量大、高频、需按天归档、要支持滚动清理——用uni.setStorageSync存数组很快会超10MB限制,且无法按日期检索。
- 必须用
plus.io.requestFileSystem写入私有目录(如_doc/logs/),iOS/Android都走沙箱路径,无需额外权限 - 日志文件名建议用
app_2026-06-17.log格式,每天一个文件,避免单文件过大导致读写卡死 - 每次写入前检查文件大小,超过5MB自动切新文件;保留最近7天日志,过期文件用
plus.io.resolveLocalFileSystemURL+removeRecursively清理 - 不要直接
JSON.stringify(err)存整个Error对象——部分平台对err.stack里的函数引用序列化失败,应手动提取message、stack、name等基础字段
上报策略不能只靠“定时上传”,得组合事件触发
纯定时上传在弱网或后台被系统杀掉时极易失败,必须叠加关键事件兜底。
- 应用进入后台时触发一次上传:
uni.onAppHide(() => uploadLogs({ reason: 'APP_HIDE' })) - 捕获到错误立刻尝试上报,但加锁防重入:
let isUploading = false; if (!isUploading) { isUploading = true; uploadLogs().finally(() => isUploading = false); } - WiFi环境下用短间隔(5分钟),移动网络降级为长间隔(2小时),避免耗电和流量投诉
- 用户点击“反馈问题”按钮时,强制打包当前日志+设备信息+vuex状态快照,走
uni.uploadFile发zip包(比JSON更省带宽)
原生崩溃日志必须单独接入,uni-app本身不提供能力
uni.onError收不到iOS EXC_BAD_ACCESS或Android NullPointerException,这类错误发生在JS引擎之外,必须靠原生SDK桥接。
- 插件市场搜
uni-crash-report,选已适配最新uni-app CLI版本的插件,旧版可能不兼容Android 14或iOS 18 - 接入后务必在
manifest.json → App模块配置里勾选对应SDK,否则打包时会被剥离 - 调试阶段崩溃日志只出现在Xcode控制台或Android Studio的Logcat里,不会自动上报——得先连真机跑一遍,确认原生日志能打印出来再配上报地址
- 原生SDK上报字段和JS日志要对齐:设备型号、系统版本、uni-app版本、用户ID(脱敏后)、时间戳,否则排查时根本串不上上下文
最易被忽略的一点:JS错误上报和原生崩溃上报要用不同接口、不同鉴权方式,但共用同一套日志分析平台。如果两个数据源时间戳不同步、用户标识不一致,再全的埋点也白搭。











