主要问题是 index.html 的最长期限为 30 天。在我看来,Android 上的 Chrome 在访问pwa 缓存之前首先从标准浏览器缓存加载。
这不是在 Chrome 桌面上发生的,只是在我测试的 Android 中发生。
我通过以下方式解决了这个问题:
- 在 index.html 上设置一个较短的 max-age 到期(服务器端)
根据您的情况,可能不需要额外的步骤:
- 删除 index.html
ngsw.config.json
以强制从网络加载。
- 自定义服务人员提供“您离线”消息(见下文)
定制服务人员,在app.module.ts
ServiceWorkerModule.register('./offline-service-worker.js', { enabled: environment.production }),
offline-service-worker.js
文件:
const CACHE_NAME = 'offline';
const OFFLINE_URL = '/assets/offline-page.html';
self.addEventListener('install', (event) => {
event.waitUntil((async () => {
const cache = await caches.open(CACHE_NAME);
await cache.add(new Request(OFFLINE_URL, {cache: 'reload'}));
})());
});
self.addEventListener('activate', (event) => {
event.waitUntil((async () => {
if ('navigationPreload' in self.registration) {
await self.registration.navigationPreload.enable();
}
})());
self.clients.claim();
});
self.addEventListener('fetch', (event) => {
if (event.request.mode === 'navigate') {
event.respondWith((async () => {
try {
// First, try to use the navigation preload response if it's supported.
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
return preloadResponse;
}
const networkResponse = await fetch(event.request);
return networkResponse;
} catch (error) {
// catch is only triggered if an exception is thrown, which is likely
// due to a network error.
// If fetch() returns a valid HTTP response with a response code in
// the 4xx or 5xx range, the catch() will NOT be called.
console.log('Fetch failed; returning offline page instead.', error);
const cache = await caches.open(CACHE_NAME);
const cachedResponse = await cache.match(OFFLINE_URL);
return cachedResponse;
}
})());
}
});
importScripts('./ngsw-worker.js');
整个 PWA 是一件棘手的事情。但是当它起作用时很棒!