Search code examples
service-workeroffline-cachingworkboxsw-precacheparceljs

how do I include files that sw-precache misses


Context

I'm using parcel-plugin-sw-precache which wraps around sw-precache to make it work with Parcel.js. Everything was working as expected, and I have been testing my offline app.

Problem

I added react-pdf.js into my project, one of the dependencies for this library doesn't get added into the service worker when it is generated by the sw-precache. I know this because the file "pdf.worker.entry.7ce4fb6a.js" gives a 304 error when I switch to offline mode.

What I have tried

I'm trying to add the file manually to the package.json parcel-plugin-sw-precache config using this code:

 "sw-precache": {
    "maximumFileSizeToCacheInBytes": 10485760,
    "staticFileGlobs": [
      "/pdf.worker.entry.7ce4fb6a.js"
    ]
  },

I'm not sure if the file path should be relative to package.json or relative the generated service worker. In anycase, the manually specified file doesn't get added to generate services worker as I would expect. As seen below.

self.__precacheManifest = [{
  "url": "index.html",
  "revision": "ac5ace7a43a0fef7ae65fd3119987d1f"
}, {
  "url": "castly.e31bb0bc.css",
  "revision": "657409f7159cb857b9409c44a15e653f"
}, {
  "url": "castly.e31bb0bc.js",
  "revision": "018d4664d809ec19d167421b359823ad"
}, {
  "url": "/",
  "revision": "af5513bb330deae3098ab289d69a40c7"
}]

The question

If the sw-precache or parcel-plugin-sw-precache seem to be missing some files, how can I make sure they get added to the generated service worker?


Solution

  • In my exploration for an answer. I gave up on using parcel-plugin-sw-precache and instead I switched to using workbox. If you are interested in creating an offline app with Parcel.js. Then I recommend Workbox as it is the next generation of sw-precache.

    There is how I got it working:

    Learning

    Learn what Workbox is and what is does with this code lab.

    Implimenting

    1) Install the Workbox CLI globally.
    2) create a placeholding service worker in the root directory. e.g. sw_shell.js - The shell is a holding file. The Workbox wizard will pick it up and generate a new sw.js file automatically. 3) Add to the sw_config.js the following code:

    importScripts("https://storage.googleapis.com/workbox-cdn/releases/3.6.3/workbox-sw.js");
    
    if (workbox) {
    workbox.skipWaiting();
    workbox.clientsClaim();
    workbox.precaching.suppressWarnings();
    
    // The next line came from the code lab
    workbox.precaching.precacheAndRoute([]);
    workbox.routing.registerNavigationRoute("/index.html");
    } else {
      console.log(`Boo! Workbox didn't load 😬`);
    }
    

    4) Run this code from a command line opened in your project's root directory.

    workbox wizard --injectManifest
    

    5) Follow the steps in the wizard. For dev purposes point the "root web app" to your parcel dist folder. Workbox does it's magic and picks up those files to be hashed into a new sw.js file.

    6) The wizard will ask for your existing sw.js file. In my case I use the sw_shell.js.

    a:Workbox picks up the sw_shell.js.
    c:Generates as new sw.js file in a location specfied when running the wizard, and injects the files to run offline.

    In my case I let the new sw.js generate in my root folder because Parcel picks it up automatically as per the script in my index.js.

    'use strict';
    if ('serviceWorker' in navigator) {
      window.addEventListener('load', function() {
        navigator.serviceWorker.register('sw.js').then(function(reg) {
          console.log('Worker registration started')
          reg.onupdatefound = function() {
             console.log('update found')
            var installingWorker = reg.installing;
            installingWorker.onstatechange = function() {
    
              console.log('installing worker')
              switch (installingWorker.state) {
    
                case 'installed':
                  if (navigator.serviceWorker.controller) {
                    console.log('New or updated content is available.');
                  } else {
                    console.log('Content is now available offline!');
                  }
                  break;
    
                case 'redundant':
                  console.error('The installing service worker became redundant.');
                  break;
              }
            };
          };
        }).catch(function(e) {
          console.error('Error during service worker registration:', e);
        });
      });
    } 
    

    7) Add workbox injectManifest to your package.json to make sure Workbox picks up any changes to your files:

      "scripts": {
        "start": "parcel index.html workbox injectManifest"
    }
    

    Let me know if you want to know more about this. There is a video here that helped me a little bit also.