ARTICLE · 1138301
uni-app 本地缓存策略:让应用「离线也能用」
一、先知道家底:三端的限额和差异
•小程序:单 key 上限 1MB,总上限 10MB,超限写入静默失败(这是最阴的,不报错,数据就是没存上)
•H5:走 localStorage,约 5MB,存的是字符串
•App:native storage,额度宽松,但同步 API 照样阻塞 UI 线程
两个结论:小程序端的缓存总量要有规划,别什么都往里塞;所有同步 storage 调用尽量别在循环里高频执行,大对象序列化一次几十毫秒,列表页滚动时会掉帧。
二、基础封装:序列化、命名空间、异常兜底
// utils/storage.jsconst PREFIX = 'myapp:' // 命名空间:清理时按前缀扫,调试时一眼认出是谁写的export function setCache(key, value) { try { uni.setStorageSync(PREFIX + key, JSON.stringify(value)) } catch (e) { // 小程序超限静默失败,这里能抓到 H5 的 QuotaExceededError console.warn('[storage 写入失败]', key, e) clearExpired() // 清一轮过期数据再试 try { uni.setStorageSync(PREFIX + key, JSON.stringify(value)) } catch (e2) {} }}export function getCache(key) { try { const raw = uni.getStorageSync(PREFIX + key) return raw ? JSON.parse(raw) : null } catch (e) { // JSON 解析失败说明数据脏了,删掉当没存过 uni.removeStorageSync(PREFIX + key) return null }}
三、过期时间与版本号
缓存最大的坑是「永远新鲜」,包一层元信息就能解决:

const CACHE_VERSION = 2export function setCacheV(key, value, ttl) { setCache(key, { data: value, expireAt: ttl ? Date.now() + ttl : Infinity, version: CACHE_VERSION })}export function getCacheV(key) { const wrap = getCache(key) if (!wrap) return null if (wrap.version !== CACHE_VERSION) return null // 结构变了,作废 if (Date.now() > wrap.expireAt) { // 过期了,顺手删掉 uni.removeStorageSync(PREFIX + key) return null } return wrap.data}
四、缓存优先渲染:秒开的关键
列表页、详情页的通用优化:先渲染缓存数据,同时发请求,回来后覆盖刷新。用户看到的是「瞬间有内容」而不是「白屏转圈」:
async function loadGoodsList() { const cached = getCacheV('goods:list') if (cached) { list.value = cached // 先上缓存,立刻可看 } const fresh = await request('/goods/list', { silent: !cached }) list.value = fresh setCacheV('goods:list', fresh, 5 * 60 * 1000) // 5 分钟 TTL}
这个策略的细节在「有无缓存」的分叉里:有缓存时请求走 silent 不开 loading,避免闪一下;没缓存时正常 loading。请求失败且有缓存时直接吞掉错误,弱网环境下页面依然可用,这就是「离线也能用」的底气。
五、清理策略:给缓存留个出口
•按前缀清理:登出时用 uni.getStorageInfoSync() 拿全部 key,过滤自家前缀批量删,别把别的业务数据误伤
•启动时清理:App onLaunch 里扫一遍过期项,控制总量
•上限淘汰:给关键业务缓存定上限条数,超了按写入时间删最旧的,模拟 LRU
这篇收掉了数据层模块的最后一块:storage 三端限额心里有数(小程序超限静默失败尤其要记牢),封装层用 try-catch 兜住脏数据,元信息里 expireAt 管新鲜度、version 管结构变更,列表页用缓存优先渲染做到秒开和弱网可用,清理按前缀、按过期、按上限三条路走。至此请求、登录态、文件、缓存四件基建全部就位,业务页面往上是纯 happy path。
觉得有用的话,点赞、分享、推荐三连支持一下。