PWA必需manifest.json、Service Worker和HTTPS三者缺一不可;manifest需含name、short_name、start_url、display(推荐"standalone")、icons(192×192和512×512 PNG)等字段,且start_url须返回200,Service Worker须在HTTPS下注册并处理fetch事件。

HTML 本身不是 PWA,但它是 PWA 的起点;真正让网页变成 PWA 的,是 manifest.json、service worker 和 HTTPS 这三样东西缺一不可。没配对 start_url 和 display,浏览器根本不会显示“添加到桌面”按钮——这不是兼容性问题,是硬性校验失败。
manifest.json 必须填哪些字段才被识别为 PWA
浏览器只认几个关键字段,漏掉任意一个,manifest.json 就算加载成功,PWA 也不会激活。
-
name和short_name都要写:short_name用于桌面图标文字,超过 12 字可能被截断 -
start_url必须存在,且返回 HTTP 200(重定向到登录页会直接失败);推荐用相对路径如"/"或"/index.html" -
display推荐设为"standalone";设成"browser"就退化成普通标签页,不算 PWA -
icons至少含两个 PNG:一个"192x192",一个"512x512";src路径必须可被 fetch 到(404 会导致整个 manifest 加载失败)
service worker 注册不生效的常见原因
注册失败通常不报错,控制台静默跳过——这是最让人抓狂的地方。问题往往出在环境或路径上,而不是代码逻辑。
- 必须跑在 HTTPS 下(
localhost是唯一例外;http://127.0.0.1不行) -
navigator.serviceWorker.register()的参数是相对于当前页面 URL 的,不是 JS 文件位置。比如页面在/blog/post.html,想注册根目录的sw.js,得写"/sw.js",不能写"./sw.js" - 注册后刷新页面看不到效果:service worker 默认要等下次加载才激活。开发时可用
skipWaiting()+clients.claim()强制接管,但上线前务必删掉 - 验证是否生效:打开 DevTools → Application → Service Workers,看状态是不是
"Activated and is running",并勾选"Update on reload"
离线缓存策略别只靠 cache.addAll()
很多人以为在 install 事件里调用 caches.addAll() 就万事大吉,其实这只是缓存静态资源的第一步;fetch 事件没处理,用户依然无法离线访问。
立即学习“前端免费学习笔记(深入)”;
-
fetch事件里必须显式调用caches.match()并return response || fetch(request),否则请求直接走网络,缓存形同虚设 - JS/CSS 等静态资源适合缓存,但 service worker 更新时旧缓存不会自动清理——得在
activate事件里遍历caches.keys()手动删旧版本 - API 请求别盲目缓存:带用户态的接口(如
/api/user/profile)缓存前必须把 auth token 或用户 ID 加进 cache key,否则不同用户看到彼此数据 -
fetch()默认不带 cookie,需要显式传{ credentials: "include" },否则登录态请求会 401
最容易被忽略的是 start_url 的响应状态和 service worker 的作用域路径——它们不像 JS 报错那样明显,但只要不对,整个 PWA 就卡在第一步,连 Lighthouse 检测都过不了。



















