Lighthouse PWA 评分为什么一直卡在80多分?

春萍 阅读 86

我用 Lighthouse 测了一个 PWA 页面,其他项都过了,但“可安装性”和“离线支持”总是拿不到满分,卡在80多分。明明注册了 service worker,也加了 manifest.json,但 Lighthouse 还是报“未满足 PWA 安装条件”。

我试过检查 manifest 的 start_url 和 scope,也确认了 HTTPS 环境,但还是不行。下面是我注册 service worker 的代码:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js')
      .then(reg => console.log('SW registered:', reg))
      .catch(err => console.error('SW registration failed:', err));
  });
}
我来解答 赞 11 收藏
二维码
手机扫码查看
2 条解答
❤静怡
❤静怡 Lv1
八成是manifest.json没配好或者sw.js没缓存页面。检查这几点:

1. manifest里必须有icons数组,而且至少包含192x192和512x512两种尺寸
2. sw.js里要缓存页面主文档,比如这样:
const cacheName = 'v1';
const assets = ['/', '/index.html'];

self.addEventListener('install', e => {
e.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll(assets))
);
});


3. 确保start_url能离线访问,别整什么重定向的幺蛾子
点赞 1
2026-03-07 00:02
百里芸菡
你这问题我见过太多次了,Lighthouse 的 PWA 检查其实挺苛刻的,尤其是“可安装性”和“离线支持”这两项,光有 manifest.json 和注册 sw.js 是远远不够的。

先说 manifest.json,它必须满足以下条件:
- 有 nameshort_name(必须有一个)
- 有 icons 数组,且至少一个 icon 是 192×192 或更大的 PNG,建议再加个 512×512 的
- start_url 要正确,不能带 query 参数,比如 //index.html
- display 建议设为 standalonefullscreenminimal-ui
- orientation 如果设置了,必须是有效值(比如 portraitlandscape

重点来了:manifest 必须通过 HTTP 头 Content-Type: application/manifest+jsonapplication/json 返回,Lighthouse 会校验这个,很多人就栽在这一步。

再看 service worker:
- sw.js 必须放在根目录或更浅的路径(比如 /app/sw.js 也可以,但 scope 会被限制在 /app/ 下,start_url 必须在这个 scope 内)
- sw.js 里必须实现 installfetch 事件(哪怕只是空处理)
- fetch 事件里必须有响应,比如缓存静态资源,否则 Lighthouse 会认为“离线不可用”

常见坑:
1. sw.js 里只写了 install 事件但没处理 fetch,Lighthouse 会认为它没实际功能
2. manifest 的 icons 用了 SVG,但 Lighthouse 要求 PNG 或 WebP(SVG 有时能过,但不稳定)
3. start_url 设置成了 ./index.html?foo=bar,后者直接挂

我建议你先用 Chrome DevTools → Application → Manifest 和 Service Workers 面板手动验证:
- Manifest 页看有没有红叉
- Service Workers 页确认 sw 已激活且状态是 active

附一个最简可过 Lighthouse 的 sw.js 示例:

const CACHE_NAME = 'v1';
self.addEventListener('install', e => {
e.waitUntil(
caches.open(CACHE_NAME).then(cache => {
return cache.addAll(['/', '/index.html', '/styles.css', '/main.js']);
})
);
});

self.addEventListener('fetch', e => {
e.respondWith(
caches.match(e.request).then(resp => {
return resp || fetch(e.request);
})
);
});


manifest.json 最小示例:

{
"name": "My PWA",
"short_name": "PWA",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}


最后提醒:Lighthouse 是跑在模拟环境里,如果你用的是本地 http://localhost,它其实也能过(因为 localhost 视为安全上下文),但必须确保不是 127.0.0.1,有时会踩坑。
真不行就用 ngrokcloudflared 搭个临时 HTTPS 测试,比在本地瞎调快多了。
点赞 6
2026-02-27 06:01