Skip to content
This repository was archived by the owner on May 7, 2025. It is now read-only.

Caching with Service Worker

Clint Cabanero edited this page Jun 28, 2019 · 6 revisions

Below are dev notes for creating a custom Service Worker template for caching Seafoodfest web app assets.

1. Register the Service Worker

src/index.js calls serviceWorker.register();

By default, this is commented out when scaffolding a React app with create-react-app CLI.

2. Update registerServiceWorker.js

In src/registerServiceWorker.js, update the register function such that the load event will generate a sw.js file instead of the default service-worker.js file after doing a build.

In this solution we made the following changes:

//const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
const swUrl = `${process.env.PUBLIC_URL}/sw.js`;

3. Create service worker build file

Added src/sw-build.js with the following:

const workboxBuild = require('workbox-build');
// NOTE: This should be run *AFTER* all your assets are built
const buildSW = () => {
  // This will return a Promise
  return workboxBuild.injectManifest({
    swSrc: 'src/sw-template.js', // this is your sw template file
    swDest: 'build/sw.js', // this will be created in the build step
    globDirectory: 'build',
    globPatterns: [
      '**\/*.{js,css,html,png}',
    ]
  }).then(({count, size, warnings}) => {
    // Optionally, log any warnings and details.
    warnings.forEach(console.warn);
    console.log(`${count} files will be precached, totaling ${size} bytes.`);
  });
}
buildSW();

4. Create service worker template file

Added src/sw-template.js with the below. Note, the Workbox cache rules need to be tweaked as needed for SeafoodFest.

  if ('function' === typeof importScripts) {
    importScripts(
      'https://storage.googleapis.com/workbox-cdn/releases/3.5.0/workbox-sw.js'
    );
    
    /* global workbox */
    if (workbox) {
      
      console.log('Workbox for SFF is loaded');
  
      /* injection point for manifest files.  */
      workbox.precaching.precacheAndRoute([]);
      
      /* custom cache rules */
      workbox.routing.registerNavigationRoute('/index.html', {
        blacklist: [/^\/_/, /\/[^\/]+\.[^\/]+$/],
      });
      
      /* 
         Custom cache rules - app images 
         Cache all image types.
         Get images from the cache first.  
         Fetch new images every 30 days so they are not stale - image update are NOT frequent. 
       */
      workbox.routing.registerRoute(
        /\.(?:png|gif|jpg|jpeg|svg)$/,
        workbox.strategies.cacheFirst({
          cacheName: 'sf-images',
          plugins: [
            new workbox.expiration.Plugin({
              maxEntries: 60,
              maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
            })
          ],
        })
      );

      /* 
         Custom cache rules - json 
         Cache .geojson files.
         Fetch garagesale.geojson from the network first if possible (as they are updated frequently).
         Fallback to the cached garagesale.geojson if disconnected from the internet.
       */
      workbox.routing.registerRoute(
        new RegExp('.*\.json'),
        new workbox.strategies.NetworkFirst({
          cacheName: 'sf-json'
        })
      );

      /* 
         Custom cache rules - map tiles 
         Cache map tiles from the external mapbox root url - for only successfull responses.
      */ 
      workbox.routing.registerRoute(
        new RegExp('^https://api.mapbox.com/v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v7,spatialdev.45mt0wo1,spatialdev.00lrg24b/'),
        new workbox.strategies.CacheFirst({
          cacheName: 'sf-map-tile-cache',
          plugins: [
            new workbox.cacheableResponse.Plugin({
              statuses: [0, 200],
            })
          ]
        })
      );
      

      // Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
      workbox.routing.registerRoute(
        /^https:\/\/fonts\.googleapis\.com/,
        new workbox.strategies.StaleWhileRevalidate({
          cacheName: 'google-fonts-stylesheets'
        })
      );

      // Cache the underlying font files with a cache-first strategy for 1 year.
      workbox.routing.registerRoute(
        /^https:\/\/fonts\.gstatic\.com/,
        new workbox.strategies.CacheFirst({
          cacheName: 'google-fonts-webfonts',
          plugins: [
            new workbox.cacheableResponse.Plugin({
              statuses: [0, 200]
            }),
            new workbox.expiration.Plugin({
              maxAgeSeconds: 60 * 60 * 24 * 365,
              maxEntries: 30
            }),
          ],
        })
      );

  } else {
      console.log('Workbox could not be loaded. No Offline support');
    }
  }
  

5. Update package.json to add build step and clean-up for Service Worker

 "scripts": {
    "start": "react-scripts start",
    "build-sw": "node ./src/sw-build.js", // <!--- ADDED THIS - BUILD THE CUSTOM SERVICE WORKER
    "clean-cra-sw": "rm -f build/precache-manifest.*.js && rm -f build/service-worker.js", <!-- ADDED THIS - CLEAN UP
    "build": "react-scripts build && npm run build-sw && npm run clean-cra-sw", <!--- UPDATED THIS - ADD BUILD STEP
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
Clone this wiki locally