App端离线缓存必须用plus.io或plus.sqlite,因uni.setStorage仅支持小量键值对,无法安全存储图片、HTML等大资源,易致内存溢出、读取失败或iOS写入丢失。
uni-appApp端离线缓存不能只靠,必须结合或才能真正落地——因为在App端虽映射为(持久化),但它只适合小量键值对,无法存图片、HTML、JSON文件等资源型内容。
为什么
不够用?
它本质是键值对存储,value 会被序列化为字符串。一旦你要缓存一张 2MB 的商品图、一个含 HTML 的富文本详情页、或一组带附件的离线工单数据,
就会触发内存溢出、写入失败或读取变慢。
常见错误现象包括:
写入大对象时无报错但实际未写入(尤其 iOS)
读取后 JSON.parse 失败,提示 “Unexpected token”(因字符串被截断或编码损坏)
H5 端和 App 端行为不一致:H5 的
有 5MB 限制,而 App 端虽无硬限制,但直接塞大字符串仍会卡 UI 线程
App端推荐用
存文件资源
这是最贴近“离线包”语义的方案:把远程资源(如
)下载并保存为本地文件(如
),后续直接用
读取并渲染。
实操要点:
使用
目录(App 可读写,且不会被系统清理)
文件路径必须用
转成可被
或
加载的本地 URL
下载前先检查磁盘空间:
,避免写满导致崩溃
文件名建议用资源 URL 的 MD5 值(如
),避免特殊字符和路径冲突
怎么管理离线包的版本与更新?
离线包不是“写一次就完事”,必须支持增量更新、过期校验、回滚机制。关键动作:
uni-app电商系统实战精讲课程课件
uni-app电商系统实战精讲课程
下载
服务端提供 manifest.json,包含每个资源的
、
、
和
App 启动时比对本地 manifest 与服务端 manifest,只下载变更/新增的文件(跳过未变的)
下载完成后原子替换:
+
,防止半更新状态
异常中断时,保留上一版完整 manifest 和资源,保证下次启动仍可用
注意:
没有事务概念,所以“原子替换”要靠重命名 +
实现,不能直接覆盖写。
离线包加载时如何无缝 fallback?
用户打开页面时,你得先尝试加载本地离线包,失败再走网络请求。但不能简单 try/catch
就去发网络请求——因为首次冷启动时文件可能还没下完,或者用户刚删了缓存。
更稳妥的做法是:
用
记录当前离线包状态(
/
/
)
在页面
中,先查状态;若为
,则用
加载;否则显示 loading 并静默拉取
网络请求失败时,才兜底用本地缓存(哪怕旧一点),而不是直接报错或白屏
容易被忽略的一点:iOS 上
读取文件时,如果路径含中文或空格,
会返回 null —— 必须提前
文件名,且全程用英文路径命名离线包目录。
uni.setStorageplus.ioplus.sqliteuni.setStorageplus.storageuni.setStorageuni.setStorageplus.storagelocalStorageplus.iohttps://api.example.com/pages/order-detail.html_doc/offline/order-detail.htmlplus.ioplus.io.PRIVATE_DOCplus.io.convertLocalFileSystemURL(path)uni.loadSubNVueplus.runtime.getDiskInfo()md5('https://.../detail.json')urlmd5sizetimestampmanifest.json.new → manifest.json资源文件.new → 资源文件plus.iomoveToplus.io.resolveLocalFileSystemURLuni.getStorageSync('offline_status')'ready''downloading''failed'onLoad'ready'plus.io.resolveLocalFileSystemURLplus.ioresolveLocalFileSystemURLencodeURIComponent