PWA 实战要点
Service Worker 与 Web Worker 区别?
- Web Worker:计算密集型,不阻塞主线程,不能操作 DOM
- Service Worker:网络代理型,拦截请求、缓存、离线、推送
- 作用完全不同,SW 更偏向网络与缓存
常见的 Service Worker 缓存策略有哪些?
缓存 | 网络二者交叉
- Cache First(缓存优先):先读缓存,没有再请求网络 → 适合永远不变的资源
- Network First(网络优先):先请求网络,失败读缓存 → 适合动态数据、接口
- Network Only(仅网络):只走网络,绝不缓存 → 敏感接口、支付、实时数据
- Cache Only(仅缓存):只走缓存 → 极少用
- Stale-while-revalidate 缓存先展示,后台异步更新
缓存策略的选择(超级关键 -> 看过来)
shell
# 1. 带 hash 的静态资源(js/css/img)
→ Cache First(缓存优先)
原因:文件永不变化,缓存最优
# 2. index.html(入口页面)
→ Network First(网络优先)
原因:必须保证发版能更新,离线兜底
# 3. 普通接口(列表 / 数据)
→ Network First(网络优先)
原因:网络优先保证最新,离线给缓存
# 4. 敏感接口(支付 / 余额 / 表单)
→ Network Only(仅网络)
原因:不能缓存,必须实时
# 总结
静态资源缓存优先、html和普通接口网络优先、敏感接口不缓存仅网络为什么 HTML 不能用 Cache First?
shell
因为 index.html 是整个应用的入口,不带 hash 值。
如果使用 Cache First,发版后用户永远拿不到新的 HTML,页面永远不更新,会导致白屏或异常。
所以 HTML 必须用 Network First。接口要不要缓存?怎么处理?为什么?
shell
1. 接口一般不缓存
其一是接口的数据总是在变化,如果缓存容易让客户获取到过期数据
其二是接口是用户行为驱动的,提交、删除、修改、查询,每次结果都可能不一样。缓存会导致:删除不删、修改不改、查询不变等问题
其三是接口缓存难以控制,无法检测到接口数据变化
其四是HTTP 协议本身就不建议缓存接口,接口默认 Cache-Control: no-cache,浏览器本来就不会缓存接口,PWA 强行缓存违背规范。
2. 怎么处理呢?
Network Only(只走网络) + 离线兜底(展示提示)
正常有网:直接请求,保证最新
断网 / 弱网:返回友好提示,不缓存旧数据
service-worker.js 里的标准写法
self.addEventListener('fetch', (e) => {
if (e.request.url.includes('/api/')) {
// 接口:只走网络,失败返回兜底
e.respondWith(
fetch(e.request).catch(() => {
return new Response(
JSON.stringify({
code: 500,
msg: '网络异常,请检查网络',
}),
{ headers: { 'Content-Type': 'application/json' } }
)
})
)
return
}
})
3. 什么情况下可以缓存接口?(特殊场景)只有满足下面全部条件才能缓存:
数据几乎不变(省市区、字典、枚举)
后台明确允许缓存
数据不敏感
能接受短时间旧数据
4. 非关键接口:非实时性接口,刷新频率不高的接口,讨厌断网的接口,可使用
Network First 网络优先,失败走缓存(接口)
5. 关键接口:绝对不能缓存的接口,如果缓存可能出事故
支付、余额、资产、库存
表单提交、POST 请求
实时性极强(聊天、直播数据)
敏感操作(删除、审核、权限)Service Worker 如何实现离线访问?
- 安装时缓存关键资源
- 拦截 fetch 事件。缓存接口
- 断网时返回缓存资源
Service Worker 不能做什么?
- 不能操作 DOM
- 不能用 window、document、alert
- 不能直接访问 localStorage(可用 indexedDB)
- 不能同步 API(全是 Promise)
如何让 PWA 发版后用户能更新?
- 修改 service-worker.js 内容(如版本号)
- 监听 updatefound
- 提示用户刷新
- 调用 skipWaiting + location.reload()
为什么线上发版后用户不更新?
- service-worker.js 被浏览器缓存了
- Nginx 没配置 no-cache,即:Cache-Control: no-store, no-cache
- 没监听 SW 更新事件
PWA 能提升首屏加载速度吗?
- 首次访问不能加速(还要下载 sw)
- 二次 / 回访极快(直接读缓存)
- 适合后台系统、常见访问 H5。
Manifest 作用?
- 配置桌面图标
- 配置启动画面
- 配置全屏 /standalone 模式
- 配置主题色
如何避免缓存混乱?
- 缓存名加版本:cache-v1, cache-v2
- activate 阶段删除旧版本缓存
- 静态资源带 hash
SW 安装失败常见原因?
- addAll 里有不存在的文件(404)
- HTTPS 证书问题
- 文件跨域
- sw 缓存导致旧代码不更新
总结
shell
PWA 是标准,SW 是实现技术
SW 是独立线程,不能操作 DOM
生命周期:install → activate → idle
缓存策略:CacheFirst / NetworkFirst
必须 HTTPS
发版更新靠修改 sw.js + 提示刷新
PWA 优化二次首屏,不优化首次