我正在使用 ServiceWorker 来预缓存文件。每当我构建应用程序时都会生成 serviceworker.js,并且所有比 serviceworker.js 最新版本更新的文件以及当前时间戳都会添加到该文件中,因此如果我修改缓存文件,则会添加它到缓存并且时间戳发生变化,因此重新安装了serviceworker。在安装事件处理程序中,我删除新文件然后添加它们:
newFiles.forEach((resource) => {
cache.delete(resource)
.then(() => { })
.catch((error) => { console.warn(`${resource}: ${error}`); });
});
newFiles.forEach((resource) => {
cache.add(resource)
.then(() => { })
.catch((error) => { console.warn(`${resource}: ${error}`); });
}
我要求客户:
self.addEventListener('activate', (event) => {
event.waitUntil(clients.claim())});
在 serviceworker 中,我记录缓存命中:
/css/main.css cached
不幸的是,页面使用旧版本的 main.css 进行渲染。如果我进行硬重新加载,我会得到使用新 css 渲染的页面,但如果我进行常规重新加载,旧的 css 就会回来。使用curl 请求文件会获取新版本。所以看来缓存的文件被保留了。我知道我可以删除整个缓存,并且我知道我可以将文件名更改为 main-datestamp.css,但这看起来不太优雅。我错过了什么?
问题是我有 2 个版本的程序;演示和生产;它们在不同的 URL 上运行。我在演示中缓存了更多文件,因此我为 https://demo.example.com 提供了演示缓存,为 https://product.example.com 提供了生产缓存。因此,当我更新演示缓存中的 css 文件时,它仍然在生产缓存中找到它,因为我正在从所有缓存中读取:
const responseFromCache = await caches.match(request);
我将其更改为:
const responseFromCache = await caches.match(request,{'cacheName': 'demo-cache'});
此外,cache.delete 是不必要的。那么我们该如何处理有人删除缓存的情况呢?由于我们有完整的资源列表,因此我们只需使用 Set 操作:
cache.keys().then((keys) => {
const resourceSet = new Set(myresources);
const cacheSet = new Set(keys);
const difference = resourceSet.difference(cacheSet);
const newfilesSet = new Set(newFiles).union(difference);
newfilesSet.forEach((resource) => {
cache.add(resource)
.then(() => { })
.catch((error) => { console.warn(`${resource}: ${error}`); });
})
})
请注意,此代码的目的是缓存有限数量的文件,在我的例子中是动画所需的图像和音频文件。