9

I run the website https://www.igluonline.com running Hugo and I recently installed a service worker following Google's sw-precache.

This is the Config file:

module.exports = {
  staticFileGlobs: [
    'dist/css/**.css',
    'dist/**/*.html',
    'dist/images/**.*',
    'dist/js/**.js'
  ],
  skipWaiting: true,
  stripPrefix: 'dist',
  runtimeCaching: [{
    urlPattern: /\/*/,
    handler: 'networkFirst'
  }]
};

Considerations:

Although sometimes the automatic generated code runs into some erros, the service worker works properly and deliver the offline experience both on web and mobile.

Also it has cache-control set to max-age=0 and when I push a new code it makes the update.

Problem:

I set the runtimeCaching handler to networkFirst and according to Google's sw-toolbox API (which is present in sw-precache when using runtimeCaching) it should get the page preferably from the http call and if there is no connection it should fallback to the cache.

But when I refresh my code and open a new window to test (note that I do close all tabs and windows running the website prior to the update), it will show the cached page. It will naturally download the new service worker and on second reload update the page, but I don't expect my visitors to double refresh my homepage every time to get new content.

I try changing the runtimeCachingcode to the following hoping to get at least my homepage to load directly from the network, but I had no luck:

runtimeCaching: [{
    urlPattern: /\//,
    handler: 'networkOnly'
  },{
    urlPattern: /\/*/,
    handler: 'networkFirst'
  }]

Now I'm not sure if the desired PWA experience is like that - meaning that users have to reload twice or at least visit two pages to see the refreshed code - or if I'm making some mistake. I'd really appreciate a consideration.

André Lucas
  • 1,788
  • 1
  • 18
  • 36
  • Is the issue that when loading your site users are always getting the cached version or that when when you update the service worker users don't see the new service worker changes until their second page load? – abraham May 07 '17 at 15:05
  • @abraham, thanks for the comment. That would be the second option. When I update my site with a new article, for example (and by consequence the worker), users won't see changes until they load a second time the same page or probably any other page on the site. – André Lucas May 07 '17 at 22:53
  • Possible duplicate as this seems related to same issue described here: http://stackoverflow.com/questions/41422474/new-version-available-with-service-worker-and-sw-precache – lax1089 May 15 '17 at 22:45
  • @lax1089 thanks for the link, but that question was one of the first I found online about the issue. The solution there specifies the max-age and unfortunately that is not the issue I'm trying to resolve. I think I'll consider that sw-prechace is flawed. – André Lucas May 16 '17 at 06:24

1 Answers1

5

When generating service-workers, the easiest way to get the policy you want, is by using sw-precache with sw-toolbox.

When generating a new service-worker withsw-precache, you can also get the sw-toolbox code at the end of the generated file by passing the correct configuration options.

According to the sw-precache Documentation:

The sw-precache module has the ability to include the sw-toolbox code and configuration alongside its own configuration. Using the runtimeCaching configuration option in sw-precache (see below) is a shortcut that accomplishes what you could do manually by importing sw-toolbox in your service worker and writing your own routing rules.

This is an example of the runtimeCaching option showed on the sw-precache documentation:

runtimeCaching: [{
  urlPattern: /^https:\/\/example\.com\/api/,
  handler: 'networkFirst'
}, {
  urlPattern: /\/articles\//,
  handler: 'fastest',
  options: {
    cache: {
      maxEntries: 10,
      name: 'articles-cache'
    }
  }
}]

You can use this option alongside your configuration of choice.

For example you can use a configuration file as stated in the documentation:

There's support for passing complex configurations using --config . Any of the options from the file can be overridden via a command-line flag. We strongly recommend passing it an external JavaScript file defining config via module.exports. For example, assume there's a path/to/sw-precache-config.js file that contains:

module.exports = {
  staticFileGlobs: [
    'app/css/**.css',
    'app/**.html',
    'app/images/**.*',
    'app/js/**.js'
  ],
  stripPrefix: 'app/',
  runtimeCaching: [{
    urlPattern: /this\\.is\\.a\\.regex/,
    handler: 'networkFirst'
  }]
};

That file could be passed to the command-line interface, while also setting the verbose option, via

$ sw-precache --config=path/to/sw-precache-config.js --verbose

This provides the most flexibility, such as providing a regular expression for the runtimeCaching.urlPattern option.

Or you can use a JSON file:

We also support passing in a JSON file for --config, though this provides less flexibility:

{
  "staticFileGlobs": [
    "app/css/**.css",
    "app/**.html",
    "app/images/**.*",
    "app/js/**.js"
  ],
  "stripPrefix": "app/",
  "runtimeCaching": [{
    "urlPattern": "/express/style/path/(.*)",
    "handler": "networkFirst"
  }]
}

This example uses the JS file for the configuration options:

$ sw-precache --config=path/to/sw-precache-config.js --verbose

After executing the command and generating the service-worker with this configurations, you can handle the precache and policies much easier than with just sw-precache.

You can configure your policies directly in the file or add them manually at the bottom of your service-worker code.

Here is the example of the bottom part of the generated code:

//sw-precache generated code...

// *** Start of auto-included sw-toolbox code. ***
/*
 Copyright 2016 Google Inc. All Rights Reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/ 
//(!function(e){if("object"==typeof exports&&"undefined"!=typeof module))...

// *** End of auto-included sw-toolbox code. ***

// Runtime cache configuration, using the sw-toolbox library.

toolbox.router.get(/this\\.is\\.a\\.regex/, toolbox.networkFirst, {});

toolbox.options.debug = true;

//Here you can configure your precache:

toolbox.precache([
    '/',
    '/assets/background.png',
    '/assets/logo.png',
    '/assets/application.css',
]);

//And here you can configure your policies for any route and asset:

toolbox.router.get('/', toolbox.fastest);
toolbox.router.get('/assets/background.png', toolbox.fastest);
toolbox.router.get('/assets/logo.png', toolbox.fastest);

//Here is the Network First example

toolbox.router.get('/myapp/index.html', toolbox.networkFirst);

I've found this much more effective and flexible than using just sw-precache.

Here you can find the sw-toolbox Usage Guide for more info on the configuration.

Jorge Cuevas
  • 755
  • 3
  • 10
  • 30