在同一个域但使用不同文件夹的多个javascript服务工作者 [英] Using multiple javascript service workers at the same domain but different folders

查看:113
本文介绍了在同一个域但使用不同文件夹的多个javascript服务工作者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



每个网络应用都托管在不同的文件夹中。



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



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



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



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



实际上我在vanilla.js上编码,没有角度,没有反应,没有vue,没有nada。

解决方案

这里要记住两件事:


  1. 可以随意注册给定来源的服务工作人员数量,因为每个服务工作者都有自己独特的范围 。听起来你已经这样做了,注册了一个范围为 / 的顶级服务工作者,然后另外的服务工作者确定了每个你的路径独立的网络应用程序运行。


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


将这两个事实放在一起,我的猜测是发生的事情是你在其中一个服务工作者的 activate 处理程序中有一些缓存清理代码范围限定为特定的Web应用程序,该代码检索当前缓存名称的列表并删除它认为已过期的任何缓存。这在服务工作者中是常见的事情,但如果你不考虑 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 => {
//在缓存中添加条目...
})
);
});

self.addEventListener('activate',event => {
event.waitUntil(
caches.keys()。then(cacheNames => cacheNames.filter(cacheName) => {
//查找属于此范围的缓存,但与CACHE_NAME不匹配。
返回cacheName.startsWith(`$ {registration.scope}!`)&&
cacheName!== CACHE_NAME;
})。then(cachesToDelete => Promise.all(cachesToDelete.map(caches.delete))
);
});


My website offers an array of web apps for each client. Each client has a different mix of apps that can be used.

Each web app is a hosted in a different folder.

So I need to cache for each client only it's allowed web apps instead of caching all the apps, many of them he the user, will not use at all.

I naively created a global service worker for the shell of the website and custom named service worker for each folder or app.

However I noticed that after the first service worker, say sw_global.js service worker registers, installs, activates, fetches succesfully and creates a cache named cache-global, the second service worker, say sw_app1,js, which creates it's own cache cache-app1, clears all cache-global.

How can I use custom service worker for each folder?. Please keep in mind that each folder is a microservice or a web app which is not necesarilly allowed for all users, so it's imperative to not cache all content from a unique service worker.

Actually I code on vanilla.js, no angular, no react, no vue, no nada.

解决方案

There's two things to keep in mind here:

  1. It's possible to register an arbitrary number of service workers for a given origin, as long as each service worker has its own unique scope. It sounds like you're doing this already, registering both a top-level service worker with a scope of / and then additional service workers scoped to the paths from which each of your independent web apps run.

  2. The Cache Storage API (and other storage mechanisms, like IndexedDB) are shared throughout the entire origin, and by default there's no "sharding" or namespace segregation.

Taking those two facts together, my guess is that what's happening is that you have some cache cleanup code in the activate handler of one of the service workers that's scoped to a specific web app, and that code retrieves a list of current cache names and deletes any caches that it thinks is out of date. That's a common thing to do in a service worker, but you can run into trouble if you don't take into account the fact that caches.keys() will return a list of all the caches in your origin, even the caches that were created by other service worker instances.

Assuming that's what's going on here, a model that I'd recommend following is to include the value of registration.scope as part of the cache name when you create your caches. When it comes time to delete old cache entries in your activate handler, it's easy to make sure that you're only cleaning up caches that your specific service worker is supposed to manage by filtering out those that don't match registration.scope.

E.g., something like this:

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 => {
  event.waitUntil(
    caches.keys().then(cacheNames => cacheNames.filter(cacheName => {
      // Find the caches that belong to this scope, but don't match CACHE_NAME.
      return cacheName.startsWith(`${registration.scope}!`) &&
             cacheName !== CACHE_NAME;
    }).then(cachesToDelete => Promise.all(cachesToDelete.map(caches.delete))
  );
});

这篇关于在同一个域但使用不同文件夹的多个javascript服务工作者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆