web app manifest 不负责离线缓存,仅配置图标、启动屏等;离线能力必须依赖手动注册并编程控制的 service worker,且 manifest.json 与 .appcache 无关,后者已全平台彻底移除。

别配 Web App Manifest 了——它只管图标、启动屏和添加到主屏幕,不负责离线缓存。真要离线运行,必须用 Service Worker,且 Manifest 文件本身已全平台弃用。
Web App Manifest 和离线缓存是两回事
很多人混淆 manifest.json 和早已废弃的 .appcache 文件。前者(Web App Manifest)是纯声明式配置文件,只告诉浏览器:“这个 PWA 应该叫什么名字、用哪个图标、以什么模式启动”。它不参与任何资源缓存逻辑,也不触发离线能力。
后者(Application Cache / .appcache)才是过去负责缓存 HTML/CSS/JS 的机制,但已在 Chrome 94+、Firefox 95+、Safari 16.4+ 中彻底移除——不是“不推荐”,是代码已被删光,连控制台都不会报错,只是静默失效。
-
manifest.json可以和 Service Worker 共存,但两者无依赖关系 - 没有 Service Worker,
manifest.json再完整也无法让页面断网可用 - 把
manifest.json当成缓存开关,是当前最常踩的误解
Service Worker 必须手动注册并接管 fetch
离线能力实际由 Service Worker 脚本实现,它需要显式拦截网络请求并决定从缓存还是网络响应。不能靠 HTML 标签或 JSON 配置自动生效。
关键实操点:
- 注册必须在 HTTPS 或
localhost下进行,HTTP 域名直接失败 - 注册代码应放在
DOMContentLoaded后或用户交互(如按钮点击)中,避免被浏览器拦截 -
sw.js默认作用域是其所在路径,若放在/js/sw.js,则只能控制/js/下资源;根目录部署最稳妥 - 首次访问不会立即启用,需刷新一次才能完成 install → waiting → active 流程
最小可用注册示例:
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js')
.then(reg => console.log('SW registered:', reg.scope))
.catch(err => console.error('SW registration failed:', err));
});
}
Cache API 缓存策略必须分层设计
Service Worker 的 caches API 不像旧 manifest 那样“全有或全无”。你需要主动区分三类资源:
-
静态资产(HTML/CSS/JS):用
cache.addAll()在 install 阶段预加载 -
动态接口(如
/api/user):不能全量缓存,需在fetch事件里按 URL 模式判断,比如对带v=参数的 JS 请求走缓存,对 POST 请求一律放行 -
兜底响应:当所有缓存和网络都失败时,返回一个内联生成的离线页(
new Response(...)),而非依赖FALLBACK:这种全局重定向
常见错误:把整个 / 路径塞进 cache,结果导致 API 返回的 HTML 被缓存,下次拉取的是旧数据。
调试时最容易忽略的缓存残留问题
Service Worker 的缓存比旧 manifest 更难清理干净——它不随 Ctrl+F5 清除,也不受 DevTools “Disable cache” 影响。
开发阶段必须做三件事:
- 每次改
sw.js后,在 DevTools → Application → Service Workers 页面点 “Update on reload” 并勾选 “Skip waiting” - 手动执行
caches.delete('my-app-v1')删除旧缓存(可在 Console 或 sw.js 的 activate 事件里加) - 关闭所有同源标签页再重开,否则旧 SW 实例可能仍在控制页面
生产环境更新时,skipWaiting() + clients.claim() 是强制新 SW 立即接管的唯一可靠方式;指望用户手动刷新页面,基本等于放弃更新控制权。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











