Service Worker 更新,但旧文件仍缓存

Ste*_*e M 3 javascript service-worker

当我更新服务工作人员时,我关闭并重新打开页面,我得到控制台日志,表明新的服务工作人员已安装并激活,并且旧的缓存已被删除。但是,列出的要添加到缓存的文件不会再次从服务器获取,它们是几小时前的过时版本。如果不清除 Chrome 开发工具中的存储空间,则无法更新文件。

安装新版本时,如何让我的服务工作人员使用新文件填充其缓存?

例如,当 Service Worker 更新时,“stylesheet.css”仍然是旧版本:

let cacheName = "abc_web_v1_15";

self.addEventListener('install', (event) => {
    console.log('[Service Worker] Install');
    event.waitUntil(
        caches.open(cacheName).then(function (cache) {
            return cache.addAll([
                "/".
                "/stylesheet.css",
                ...
            ]);
        })
    );
});
self.addEventListener('fetch', (e) => {
    e.respondWith(
        caches.match(e.request).then(function (r) {
            console.log('[Service Worker] Fetching resource: ' + cacheName + ' ' + e.request.url);
            if (r) {
                console.log(cacheName + ' returning cached  ' + e.request);
                return r;
            } else {
                console.log(cacheName + ' returning fetched  ' + e.request);
                return fetch(e.request);
            }
        })
    )
});

self.addEventListener('activate', (e) => {
    console.log('[Service Worker] Activate');
    e.waitUntil(
        caches.keys().then((keyList) => {
            return Promise.all(keyList.map((key) => {
                if (cacheName.indexOf(key) === -1) {
                    console.log(`[Service Worker] Removing Cached Files from Cach-${key}`);
                    return caches.delete(key);
                }
            }));
        })
    );
});
Run Code Online (Sandbox Code Playgroud)

pat*_*ate 5

问题非常简单:当您的 Service Worker 请求“新”文件时,该fetch请求会通过常规浏览器 HTTP 缓存。如果在那里找到资源,浏览器会自动返回该资源,并且不会连接到网络。

如果您从代码中查看此片段:

return cache.addAll([
                "/".
                "/stylesheet.css",
                ...
            ]);
Run Code Online (Sandbox Code Playgroud)

您会发现,无论内容如何,​​样式表的名称始终相同。换句话说,当样式表更新时,文件名仍然相同。因此,该文件已经在浏览器的 HTTP 缓存中,因此 SW 在需要时即可获取该文件。

您应该对文件进行版本控制。通常使用文件内容的哈希值。通过哈希命名,您最终会得到类似stylesheet.iudfirio132.css这样的名称,每次文件更改(哪怕是一个字符)时,该名称都会更改。这样,应用程序的新版本始终使用不同名称的资源。您还应该拥有 Workbox 预缓存等构建工具来更新 Service Worker 文件中的资源列表,这样您就不需要手动执行此操作。更多:https://developers.google.com/web/tools/workbox/modules/workbox-precaching

为了完全掌握这里的主题,我建议您阅读这篇博客文章“缓存最佳实践和最大年龄陷阱” https://jakearchibald.com/2016/caching-best-practices/