Workbox: Add docs on how to handle pretty URLS.

Created on 16 Oct 2017  路  10Comments  路  Source: GoogleChrome/workbox

Taken from #640

So I went offline, and things weren't working as expected. I eventually realized that the links throughout my page all use "pretty URLs", whereas WB cached the full file names, including the .html extension. Seems like a pretty common scenario, maybe WB should have a flag that handles this?

At this point, I realized that I probably need to my own service worker with a fetch listener that handles the pretty URLs. It was surprisingly hard to find out how to do this on the docs site. This seems like a core user-journey, I think it should have an entry on the "How To" page. I think I need to use the injectManifest() method, but my first attempt hasn't worked yet.

Breaking Change Documentation

All 10 comments

Thinking on this a little more, this is messy for precaching.

Let's say you have a precache of the following:

  • /index.html
  • /about.html
  • /something/nested.html

At the moment (Out of the box) we will do the following:

  • Match for the URLs out right (i.e. '/index.html', '/about.html', '/something/nested.html).
  • If that fails, we match minus search params
  • If that fails and the URL DOES end in '/', we add index.html and see if that matches.

This means we'll handle '/'. However, we won't handle the pretty URL case of '/about' or '/something/nested'.

@jeffposnick would you be happy to add this into precaching's cache matching? This isn't an issue on template matching or runtime routes.

I'm okay with that additional "magic" being added in, and perhaps on by default, with the option to disable it via prettyUrls: false.

FWIW, the other option is to create a recipe that they used in their build process along the lines of:

buildConfig.templatedUrls = glob.sync('**/*.html').map((htmlFile) => {
  const url = path.basename(htmlFile, '.html');
  return {[url]: htmlFile};
});

That's pretty gnarly, and wouldn't work well for developers who are just using the CLI or webpack plugin. So we can support this by default instead.

Is there any workaround so far? I really want this feature so that my websites work offline as it is without rewriting any link URLs.

A workaround is to use a config like the one in https://github.com/GoogleChrome/workbox/issues/903#issuecomment-348611755, where you explicitly set templatedUrls to a mapping of "pretty" URL => the underlying .html file.

Have you had any luck with that?

I forgot to mention that I use the CLI version.

You could actually do this with the CLI version, too 馃槃

(I totally understand that this is ugly and not what we'd ideally want developers to have to do, but I want to help unblock you given what's currently possible.)

// Inside workbox.config.js:

// Run `npm install -g glob` to make sure it's globally available:
const glob = require('glob');

const templatedUrls = glob.sync('**/*.html').map((htmlFile) => {
  const url = path.basename(htmlFile, '.html');
  return {[url]: htmlFile};
});

module.exports = {
  templatedUrls,
  // Your existing config:
  globDirectory: '...',
  globPatterns: ['...']
};

Thank you @jeffposnick! I ended up this script. Note that I use Jekyll here and compiled HTML files of my website is located in _site directory.

const glob = require('glob')
const path = require('path')

module.exports = {
  templatedUrls: Object.assign(...glob.sync('_site/**/*.html').map((filename) => {
    if (path.basename(filename) === 'index.html') {
      return {}
    }

    return {[filename.slice(6, -5)]: filename}
  })),
  globDirectory: '_site/',
  globPatterns: [
    '**/*.{css,html,js,json,png}'
  ],
  globIgnores: [
    'register-service-worker.js',
    'service-worker.js'
  ],
  swDest: 'service-worker.js'
}

This is actually documented under clean URLs here: https://developers.google.com/web/tools/workbox/modules/workbox-precaching

For all users who reached to this issue, now it's no need for configuration of clean URLs. With the latest version of workbox-cli, the script I posted above is almost equivalent to:

module.exports = {
  globDirectory: '_site/',
  globPatterns: [
    '**/*.{css,html,js,json,png}'
  ],
  globIgnores: [
    'register-service-worker.js',
    'service-worker.js'
  ],
  swDest: 'service-worker.js'
}

So that works for precaching but how would I use a normal route to cache them? I currently precache (using the html files) and the cache never refreshes.

Was this page helpful?
0 / 5 - 0 ratings