【问题标题】:How to clear cache of service worker?如何清除服务工作者的缓存?
【发布时间】:2019-05-06 03:29:02
【问题描述】:

所以,我有一个带有 service worker 的 HTML 页面, service worker 缓存 index.html 和我的 JS 文件。

问题是当我更改 JS 时,更改不会直接显示在客户端浏览器上。当然,在 chrome dev-tools 中,我可以禁用缓存。但是在 chrome mobile 中,我该怎么做呢?

我尝试访问站点设置并点击 CLEAR % RESET 按钮。 但它仍然从缓存加载旧页面/加载。 我尝试使用其他浏览器或 chrome incognito 并加载新页面。

然后,我尝试清除我的浏览数据(只是缓存)并且它起作用了。

我想这不应该是这样的吧?如果不清除 chrome 浏览器缓存,我的用户不会知道页面是否已更新。

【问题讨论】:

标签: javascript html google-chrome service-worker


【解决方案1】:

最优雅的解决方案,使用 async/await:

const cacheName = 'v2';

self.addEventListener('activate', event => {
// Remove old caches
  event.waitUntil(
    (async () => {
      const keys = await caches.keys();
      return keys.map(async (cache) => {
        if(cache !== cacheName) {
          console.log('Service Worker: Removing old cache: '+cache);
          return await caches.delete(cache);
        }
      })
    })()
  )
})

【讨论】:

  • Service Worker 已安装在您的浏览器中。您的浏览器每次都会请求您的远程工作者(如果在线)并更新其本地安装的版本以供离线使用。您可以通过将其打印到控制台来查看哪些文件被缓存,即在 cache.put() 之后的 'fetch' 事件中的 console.log('Caching:', event.request.url)
【解决方案2】:

通常,您会在 Service Workers JS 文件中更新 CACHE_NAME,以便您的工作人员再次安装:

self.addEventListener('install', evt => {
  evt.waitUntil(
    caches.open(CACHE_NAME).then(cache => cache.addAll(inputs))
  )
})

或者,要清除 PWA 的缓存,请找到缓存名称:

self.caches.keys().then(keys => { keys.forEach(key => console.log(key)) })

然后运行以下命令将其删除:

self.caches.delete('my-site-cache')

然后刷新页面。

如果刷新后在控制台看到任何worker相关的错误,可能还需要注销已注册的worker:

navigator.serviceWorker.getRegistrations()
  .then(registrations => {
    registrations.forEach(registration => {
      registration.unregister()
    }) 
  })

【讨论】:

  • 最后一个代码:“navigator.serviceWorker.....”在删除 superpwa wordpress 插件后帮助我删除了所有与 service worker 相关的缓存。谢谢
  • 代码块 2 和 3 上方的描述性词语是否交换了?
  • 谢谢,大卫。在您的帮助下修复。
【解决方案3】:

这是唯一对我有用的代码。 这是我对Mozilla documentation的改编:

//Delete all caches and keep only one
const cachNameToKeep = 'myCache';

//Deletion should only occur at the activate event
self.addEventListener('activate', event => {
    var cacheKeeplist = [cacheName];
    event.waitUntil(
        caches.keys().then( keyList => {
            return Promise.all(keyList.map( key => {
                if (cacheKeeplist.indexOf(key) === -1) {
                    return caches.delete(key);
                }
            }));
        })
.then(self.clients.claim())); //this line is important in some contexts
});

【讨论】:

  • cacheNameToKeep ?? [cacheName] ??这两者是一回事吗? self.clients.claim() 是做什么的?
【解决方案4】:

如果您知道缓存名称,您可以简单地从 worker 中任何您喜欢的位置调用 caches.delete()

caches.delete(/*name*/);

如果你想擦除所有缓存(而不是等待它们,假设这是一个后台任务)你只需要add this:

caches.keys().then(function(names) {
    for (let name of names)
        caches.delete(name);
});

【讨论】:

  • 谢谢。它更简单更清晰。我只是快速写了我的回答这个问题
  • 不,不用担心。如果有人想删除 activate 侦听器中的一组特定缓存,您的将是完美的;我只是这样做,以防有人只想倾倒一个/一切
  • 最紧凑的代码可能是caches.keys().then(cs=>cs.forEach(c=>caches.delete(c))) 或异步函数(await caches.keys()).forEach(c=>caches.delete(c))
  • 我住的地方,你先生会被视为小胡子! (恭维)
  • 注意!您应该检查caches 是否存在。如果您想清除 Service Worker 之外的缓存,请添加 if (!window.caches) return; 之类的内容。也不是caches 对象在 HTTP 上可能不存在(例如在 Chrome 中)。
【解决方案5】:

使用它来删除过时的缓存:

self.addEventListener('activate', function(event) {
  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.filter(function(cacheName) {
          // Return true if you want to remove this cache,
          // but remember that caches are shared across
          // the whole origin
        }).map(function(cacheName) {
          return caches.delete(cacheName);
        })
      );
    })
  );
});

【讨论】:

  • 这里的self 是什么?窗口对象还是 serviceworker?
  • 在 Stack Overflow 上添加解释为什么您的解决方案应该有效是一种很好的做法。更多信息请阅读How To Answer
  • self 表示 serviceWorker 实例。 :)
  • self 是一个“SharedWorkerGlobalScope”对象。
  • 使用 'this' 而不是 'self' 可以做同样的事情。但这两个关键字是有区别的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2020-06-23
  • 2018-11-17
相关资源
最近更新 更多