繁体   English   中英

在同一个域但不同的文件夹中使用多个 javascript 服务工作者

[英]Using multiple javascript service workers at the same domain but different folders

我的网站为每个客户提供了一系列网络应用程序。 每个客户端都有不同的应用程序组合可供使用。

每个 Web 应用程序都托管在不同的文件夹中。

所以我只需要为每个客户端缓存它允许的网络应用程序而不是缓存所有的应用程序,其中许多是用户,根本不会使用。

我天真地为网站的外壳创建了一个全局服务工作者,并为每个文件夹或应用程序创建了自定义命名的服务工作者。

但是我注意到在第一个 service worker 之后,比如说 sw_global.js service worker 注册、安装、激活、获取成功并创建了一个名为 cache-global 的缓存,第二个 service worker,比如说 sw_app1,js,它创建了它自己的缓存缓存 - app1,清除所有缓存全局。

如何为每个文件夹使用自定义 Service Worker? 请记住,每个文件夹都是一个微服务或 Web 应用程序,并非所有用户都必须允许,因此必须不要缓存来自唯一服务工作者的所有内容。

实际上我在 vanilla.js 上编写代码,没有 angular,没有 react,没有 vue,没有 nada。

这里有两件事要记住:

  1. 可以为给定的origin注册任意数量的 service worker,只要每个 service worker 都有自己唯一的scope 听起来您已经在这样做了,注册了一个范围为/的顶级服务工作者,然后注册了范围为每个独立 Web 应用程序运行路径的其他服务工作者。

  2. 缓存存储 API (和其他存储机制,如IndexedDB )在整个源中共享,默认情况下没有“分片”或命名空间隔离。

将这两个事实放在一起,我的猜测是发生的事情是您在一个服务工作线程的activate处理程序中有一些缓存清理代码,该处理程序的范围限定为特定的 Web 应用程序,并且该代码检索当前缓存名称和删除的列表它认为已过时的任何缓存。 这是在 Service Worker 中很常见的事情,但是如果您不考虑caches.keys()将返回源中所有缓存的列表,甚至是caches.keys()的缓存,您可能会遇到麻烦由其他服务工作者实例创建。

假设这就是这里发生的事情,我建议遵循的模型是在创建缓存时将registration.scope的值包含为缓存名称的一部分。 当需要删除activate处理程序中的旧缓存条目时,很容易通过过滤掉那些与registration.scope不匹配的缓存来确保您只清理您的特定服务工作者应该管理的缓存。

例如,这样的事情:

const CACHE_VERSION = 'v2';
const CACHE_NAME = `${registration.scope}!${CACHE_VERSION}`;

self.addEventListener('install', (event) => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => {
      // Add entries to the cache...
    })
  );
});

self.addEventListener('activate', (event) => {
  const cleanup = async () => {
    const cacheNames = await caches.keys();
    const cachesToDelete = cachesNames.filter(
        (cacheName) => cacheName.startsWith(`${registration.scope}!`) &&
                       cacheName !== CACHE_NAME);
    await Promise.all(cachesToDelete.map(
      (cacheName) => caches.delete(cacheName)));
  };

  event.waitUntil(cleanup());
});

我不知道,但接受的答案对我不起作用,因为它有拼写错误以及我认为缺少代码。 我把对我有用的东西放在下面。 虽然我不想从接受的答案中拿走任何功劳,但只是添加一个工作代码,这将有助于其他人。

self.addEventListener('activate', (event) => {
  const cleanup = async () => {
    const cacheNames = await caches.keys();// here it should be caches
    console.log(cacheNames);
    const cachesToDelete = cacheNames.filter(      
    (cacheNames) => (cacheNames.startsWith(`${registration.scope}!`) && cacheNames !== CACHE_NAME));
    console.log(cachesToDelete); 
   // await Promise.all(cachesToDelete.map(caches.delete));// this line rewritten to make it working.
    await Promise.all(cachesToDelete.map(CACHE_NAME=>{ 
      return caches.delete(CACHE_NAME);
    })
    )    
  };  
  event.waitUntil(cleanup());
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM