簡體   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