Service worker add files from API call to precache

后端 未结 2 1499
迷失自我
迷失自我 2021-01-06 18:33

To enable my app running offline. During installation the service worker should:

  1. fetch a list of URLs from an async API
  2. reformat the response
  3. <
相关标签:
2条回答
  • 2021-01-06 18:54

    It looks like you're creating your own PrecacheController instance and also using the precacheAndRoute(), which aren't actually intended to be used together (not super well explained in the docs, it's only mentioned in this one place).

    The problem is the helper methods on workbox.precaching.* actually create their own PrecacheController instance under the hood. Since you're creating your own PrecacheController instance and also calling workbox.precaching.precacheAndRoute([...]), you'll end up with two PrecacheController instances that aren't working together.

    From your code sample, it looks like you're creating a PrecacheController instance because you want to load your list of files to precache at runtime. That's fine, but if you're going to do that, there are a few things to be aware of:

    • Your SW might not update Service worker updates are usually triggered when you call navigator.serviceWorker.register() and the browser detects that the service worker file has changed. That means if you change what /Assets returns but the contents of your service worker files haven't change, your service worker won't update. This is why most people hard-code their precache list in their service worker (since any changes to those files will trigger a new service worker installation).

    • You'll have to manually add your own routes I mentioned before that workbox.precaching.precacheAndRoute([...]) creates its own PrecacheController instance under the hood. It also adds its own fetch listener manually to respond to requests. That means if you're not using precacheAndRoute(), you'll have to create your own router and define your own routes. Here are the docs on how to create routes: https://developers.google.com/web/tools/workbox/modules/workbox-routing.

    0 讨论(0)
  • 2021-01-06 18:55

    I realised my mistake. I hope this helps others as well. The problem was that I did not call precacheController.install() manually. While this function will be executed automatically it will not wait for additional precache files that are inserted asynchronously. This is why the function needs to be called after all the precaching happened. Here is the working code:

    importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.1.0/workbox-sw.js');
    
    workbox.skipWaiting();
    workbox.clientsClaim();
    
    const precacheController = new workbox.precaching.PrecacheController();
    
    // Hook into install event
    self.addEventListener('install', (event) => {
      // Get API URL passed as query parameter to service worker
      const preInstallUrl = new URL(location).searchParams.get('preInstallUrl');
    
      // Fetch precaching URLs and attach them to the cache list
      const assetsLoaded = fetch(preInstallUrl)
        .then(response => response.json())
        .then((values) => {
          Object.keys(values.data.Assets).forEach((key) => {
            precacheController.addToCacheList([values.data.Assets[key]]);
          });
        })
        .then(() => {
          // After all assets are added install them
          precacheController.install();
        });
      event.waitUntil(assetsLoaded);
    });
    
    self.__precacheManifest = [].concat(self.__precacheManifest || []);
    workbox.precaching.suppressWarnings();
    workbox.precaching.precacheAndRoute(self.__precacheManifest, {});
    
    workbox.routing.registerRoute(/^.*\.(jpg|JPG|gif|GIF|png|PNG|eot|woff(2)?|ttf|svg)$/, workbox.strategies.cacheFirst({ cacheName: 'image-cache', plugins: [new workbox.cacheableResponse.Plugin({ statuses: [0, 200] }), new workbox.expiration.Plugin({ maxEntries: 600 })] }), 'GET');
    
    0 讨论(0)
提交回复
热议问题