Jump to content

PW & Google Workbox PWA


Recommended Posts

Around 3yrs ago I got excited about Progressive Web Apps (PWAs) and found a site that magically created an offline experience with a few clicks. It worked until it didn't. Had to backtrack and remove the PWA code on lots of sites due mainly to exceeded offline cache storage causing problems. My JS skills weren't, and still aren't, up to the level of expertise needed to rectify.

I still did the manifest.json thing, reduced the network load wherever possible and got some great Google Lighthouse performance results by tweaking PW especially with ProCache.

3yrs is a long time in web life. If 1 dog year = 7 human years, then 1 web year must be 10+ human years. I delved back into PWAs recently and Google Workbox in particular.

The biggest hurdle I had to overcome was Google's own Workbox docs. Forget the "Import" statements and the CLI easy PWA method recommended in the docs. They don't (or I could not get them to) work with ProcessWire. They're geared to web apps like React that have a build process that publishes to a directory eg 'app'. ProcessWire doesn't work that way.

So here's what worked for me:

  1. Create a template. I called mine "offline" that may only have one page, no children and does not have a trailing slash at the end of the URL.
  2. Create a page, add fields as necessary, eg 'body' and apply the 'offline' template and save as a child of "Home"
  3. Change the page url to 'offline.html' - this is the default page name for Workbox. Easier to change this than fiddle around overriding the Google Workbox defaults. For extra comfort, I made the page name 'Unique' and 'Hidden' from lists and searches.
  4. Ensure the workbox service worker javascript is NOT appended to the offline.html page
  5. On all other pages append the following to the <body> tag. I'm using Regions so this goes in my <region id="regFooterScripts"> in _main.php
    <?php if ($page->name != "offline.html") : ?>
            if ('serviceWorker' in navigator) {
                let scrUrl = '<?=$pages->get('/')->httpUrl?>sw.js';
                window.addEventListener('load', () => {
                    navigator.serviceWorker.register(scrUrl, {scope: '/'}).then(registration => {
                        console.log('Service Worker registered: ', registration)
                    }).catch(registrationError => {
                        console.log('Service Worker registration failed: ', registrationError)
    <?php endif; ?>

Next, by hook or by crook, get the workbox library into a directory of your PW project. You can use the CLI 'copyLibraries' feature. See https://developers.google.com/web/tools/workbox/modules/workbox-cli for more info. Do NOT use any of the other CLI features! You can also download the library from gitHub. Didn't go there so please don't ask for help. I used the CLI method & saved the files to site/templates/scripts/workbox.

Now you can start building your sw.js file which is saved in root directory. Here's mine using the Google Workbox docs & recipes. The big thing to remember is NOT to "Import" anything despite what the docs say. When you configure workbox to use your local copy of the library, all importing is done for you by using the 'workbox' namespace.


    modulePathPrefix: '/site/templates/scripts/workbox/workbox-v6.0.2/',
    globIgnores: ['processwire/**.*']  // change according to your PW admin URL

// Include offline.html in the manifest
    {url: '/offline.html', revision: null }

    ({url}) => url.pathname.startsWith('/processwire/'), // change according to your PW admin URL
    new workbox.strategies.NetworkOnly()






These are all the basic workbox features & recipes including offline.html and will probably need updating as time goes by. Up to you to add/modify/delete as you like and outside the scope of this tutorial.

Good luck & have fun with Google Workbox PWAs in ProcessWire sites.

  • Like 7
Link to comment
Share on other sites

Hi @psy, thanks for the tutorial. I've implemented workbox in the Architekturführer Köln project, though I used the Workbox webpack plugin to generate the service worker (which is easier for JavaScript-applications that use Webpack anyway, not for ProcessWire sites). A couple of things that stood out to me in your guide:

  • What's the purpose of not including the service worker on the /offline.html page? Service workers have a seperate lifecycle from individual page visits. Once registered, they will stay active until replaced or manually removed. It shouldn't matter if the registration code is repeated on the offline fallback page.
  • One way to improve the user experience would be to precache important pages, so they will be available offline even before the user has visited them! See https://developers.google.com/web/tools/workbox/modules/workbox-precaching
    The list of pages to precache could even be generated dynamically, maybe have a checkbox on all pages to allow them to be precached, expose that list to the service worker and take it from there ...
  • Seems like you're jumping through many hoops just to avoid having a simple build step for your JavaScript code. I often see people shy away from JavaScript compilation and actually make their job much harder because of this, but your code could be much simplified with a simple JS build step that would take only a couple of lines of configuration to set up. This will make it much easier to use libraries like Workbox, since you can just follow the installation and setup guides without having to, for instance, find workarounds for imports. I've written a guide on how to setup a basic JavaScript build step with ParcelJS on processwire.dev, take a look if you're interested. (Admittedly, Parcel seems kinda dead, nowadays I would recommend using Webpack 5. Or Snowpack, which seems to be all the rage right now ? )

Finally, and I know this may be personal preference, I feel like the whole "offline.html" thing is kinda ... superfluous? For an app / SPA, yes, I would expect a custom offline notification screen. But for a classic website with individual page loads, telling me I'm offline on a custom page with your logo on top doesn't really help me in any way, since it doesn't offer anything that the "you're offline" page of the browser can't …

  • Like 4
Link to comment
Share on other sites

Hi @MoritzLost thanks for your reply. Obviously, I'm new to workbox and really appreciate the feedback ? 

7 hours ago, MoritzLost said:

What's the purpose of not including the service worker on the /offline.html page?

Probably no reason other than when I did, I got lots of errors in the console.

7 hours ago, MoritzLost said:

One way to improve the user experience would be to precache important pages, so they will be available offline

Precaching important pages is an excellent tip, as is auto-generating workbox-config.js in PW then including it in the service worker.

This is my first successful attempt with Workbox after many, many failures trying to follow the docs. Just wanted to get it working. I especially struggled with the workbox-config.js generation using the CLI. The 'publish' directory cannot be '/' - which it is in PW and when when I could get it to generateSW with the publish directory as the root, it picked up loads of unnecessary files eg in /modules/, /assets/, etc. Seemed easier to create it manually than unpick the CLI's best guesses.

7 hours ago, MoritzLost said:

I feel like the whole "offline.html" thing is kinda ... superfluous?

For me, a nicely presented page with a logo & phone number is a better UX than the ugly browser default. At least the user can call if their internet is down.

  • Like 3
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...