'Setting service worker to exclude certain urls only

I built an app using create react which by default includes a service worker. I want the app to be run anytime someone enters the given url except when they go to /blog/, which is serving a set of static content. I use react router in the app to catch different urls.

I have nginx setup to serve /blog/ and it works fine if someone visits /blog/ without visiting the react app first. However because the service worker has a scope of ./, anytime someone visits any url other than /blog/, the app loads the service worker. From that point on, the service worker bypasses a connection to the server and /blog/ loads the react app instead of the static contents.

Is there a way to have the service worker load on all urls except /blog/?



Solution 1:[1]

So, considering, you have not posted any code relevant to the service worker, you might consider adding a simple if conditional inside the code block for fetch

This code block should already be there inside your service worker.Just add the conditionals

self.addEventListener( 'fetch', function ( event ) {

    if ( event.request.url.match( '^.*(\/blog\/).*$' ) ) {
        return false;
    }
     // OR

    if ( event.request.url.indexOf( '/blog/' ) !== -1 ) {
        return false;
    }
    //    **** rest of your service worker code ****

note you can either use the regex or the prototype method indexOf. per your whim.

the above would direct your service worker, to just do nothing when the url matches /blog/

Solution 2:[2]

Another way to blacklist URLs, i.e., exclude them from being served from cache, when you're using Workbox can be achieved with workbox.routing.registerNavigationRoute:

workbox.routing.registerNavigationRoute("/index.html", {
  blacklist: [/^\/api/,/^\/admin/],
});

The example above demonstrates this for a SPA where all routes are cached and mapped into index.html except for any URL starting with /api or /admin.

Solution 3:[3]

here's whats working for us in the latest CRA version:

// serviceWorker.js

window.addEventListener('load', () => {
  if (isAdminRoute()) {
    console.info('unregistering service worker for admin route')
    unregister()
    console.info('reloading')
    window.location.reload()
    return false
  }

we exclude all routes under /admin from the server worker, since we are using a different app for our admin area. you can change it of course for anything you like, here's our function in the bottom of the file:

function isAdminRoute() {
  return window.location.pathname.startsWith('/admin')
}

Solution 4:[4]

Here's how you do it in 2021:

import {NavigationRoute, registerRoute} from 'workbox-routing';

const navigationRoute = new NavigationRoute(handler, {
  allowlist: [
    new RegExp('/blog/'),
  ],
  denylist: [
    new RegExp('/blog/restricted/'),
  ],
});
registerRoute(navigationRoute);

https://developers.google.com/web/tools/workbox/modules/workbox-routing#how_to_register_a_navigation_route

Solution 5:[5]

If you are using or willing to use customize-cra, the solution is quite straight-forward.

Put this in your config-overrides.js:

const { adjustWorkbox, override } = require("customize-cra");

module.exports = override(
  adjustWorkbox(wb => 
    Object.assign(wb, {
      navigateFallbackWhitelist: [
        ...(wb.navigateFallbackWhitelist || []),
        /^\/blog(\/.*)?/,
      ],
     })
   )
);

Note that in the newest workbox documentation, the option is called navigateFallbackAllowlist instead of navigateFallbackWhitelist. So, depending on the version of CRA/workbox you use, you might need to change the option name.

The regexp /^/blog(/.*)?/ matches /blog, /blog/, /blog/abc123 etc.

Solution 6:[6]

Try using the sw-precache library to overwrite the current service-worker.js file that is running the cache strategy. The most important part is setting up the config file (i will paste the one I used with create-react-app below).

  1. Install yarn sw-precache
  2. Create and specify the config file which indicates which URLs to not cache
  3. modify the build script command to make sure sw-precache runs and overwrites the default service-worker.js file in the build output directory

I named my config file sw-precache-config.js is and specified it in build script command in package.json. Contents of the file are below. The part to pay particular attention to is the runtimeCaching key/option. "build": "NODE_ENV=development react-scripts build && sw-precache --config=sw-precache-config.js"

CONFIG FILE: sw-precache-config.js

module.exports = {
    staticFileGlobs: [
        'build/*.html',
        'build/manifest.json',
        'build/static/**/!(*map*)',
    ],
    staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
    swFilePath: './build/service-worker.js',
    stripPrefix: 'build/',
    runtimeCaching: [
        {
            urlPattern: /dont_cache_me1/,
            handler: 'networkOnly'
        }, {
            urlPattern: /dont_cache_me2/,
            handler: 'networkOnly'
        }
    ]
}

Solution 7:[7]

Update (new working solution) In the last major release of Create React App (version 4.x.x), you can easily implement your custom worker-service.js without bleeding. customize worker-service

Starting with Create React App 4, you have full control over customizing the logic in this service worker, by creating your own src/service-worker.js file, or customizing the one added by the cra-template-pwa (or cra-template-pwa-typescript) template. You can use additional modules from the Workbox project, add in a push notification library, or remove some of the default caching logic.

You have to upgrade your react script to version 4 if you are currently using older versions.

Solution 8:[8]

Working solution for CRA v4

Add the following code to the file service-worker.js inside the anonymous function in registerRoute-method.

// If this is a backend URL, skip
if (url.pathname.startsWith("/backend")) {
    return false;
}

Solution 9:[9]

To simplify things, we can add an array list of items to exclude, and add a search into the fetch event listener.

Include and Exclude methods below for completeness.

var offlineInclude = [
    '',                // index.html
    'sitecss.css',
    'js/sitejs.js'
];

var offlineExclude = [
    '/networkimages/bigimg.png',   //exclude a file
    '/networkimages/smallimg.png',
    '/admin/'                      //exclude a directory
];

self.addEventListener("install", function(event) {
  console.log('WORKER: install event in progress.');
  event.waitUntil(
    caches
      .open(version + 'fundamentals')
      .then(function(cache) {
        return cache.addAll(offlineInclude);
      })
      .then(function() {
        console.log('WORKER: install completed');
      })
  );
});

self.addEventListener("fetch", function(event) {
  console.log('WORKER: fetch event in progress.');

  if (event.request.method !== 'GET') {
    console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
    return;
  }

  for (let i = 0; i < offlineExclude.length; i++)
  {
    if (event.request.url.indexOf(offlineExclude[i]) !== -1)
    {
      console.log('WORKER: fetch event ignored. URL in exclude list.', event.request.url);
      return false;
    }
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Schrodinger's cat
Solution 2 Edric
Solution 3 goldylucks
Solution 4 Max Flex
Solution 5 apaatsio
Solution 6 Tope
Solution 7 Ali Titan
Solution 8 mleister
Solution 9