0

This is my first time experimenting with service workers, and I'm sure I'm doing something stupid.

  • I have a service worker set up for a WordPress theme I'm working on. It's located at /public_html/wp-content/themes/framework/assets/scripts/service-worker.js.
  • I have set the header Servie-Worker-Allowed: "/" via the .htaccess file.
  • I'm using sw-toolbox to make things easier. My script is below.

Script:

toolbox.precache(["/", "../media/logo.svg", "../media/spritesheet.svg", "../scripts/modern.js", "../styles/modern.css"]);
toolbox.router.get("../media/*", toolbox.cacheFirst);
toolbox.router.get("/wp-content/uploads/*", toolbox.cacheFirst);
toolbox.router.get("/*", toolbox.networkFirst, {NetworkTimeoutSeconds: 5});

The service worker properly registers, and no errors are thrown. All files set to precache show up under Cache > Cache Storage in Chrome's developer tools correctly. For some reason these cached files aren't being served when offline.

I know there's issues with the scope of the service worker, but the Service-Worker-Allowed header should correct for that. Given that the files do in fact show up in cache without issue, I'd think that this is all working correctly.

What am I missing?

Note: I'd like to keep service-worker.js and the files I'm caching where they are and with relative paths; it becomes problematic moving them to the root or giving them absolute paths because this WordPress theme gets re-used on builds and has its name changed every time, making absolute paths a pain. I tested out rewriting to the root with .htaccess, which did work, but had it's own issues. I don't understand why that would work but what I'm currently trying wouldn't.

JacobTheDev
  • 17,318
  • 25
  • 95
  • 158
  • How are you testing offline functionality? If you're not calling `clients.claim()` inside of your service worker's `activate` handler, then you should be aware that the service worker won't take control over the current page, and you would need to navigate away and then back to have the service worker take control: https://stackoverflow.com/a/41066148/385997 – Jeff Posnick Jul 21 '17 at 14:54
  • @JeffPosnick thanks, I'll see if I can figure that out. – JacobTheDev Jul 24 '17 at 15:18

1 Answers1

3

I think I was going about this wrong. There doesn't appear to be a need to manually specify to cache my theme assets as long as I've enabled caching in general. To that end, I've instead set up a rewrite rule so that service-worker.js lives at the root (i.e. https://www.example.com/service-worker.js), thus giving it correct scope. This has enabled my project to work offline. Code for this is below.

((global) => {
    // disable the service worker for post previews
    global.addEventListener("fetch", (event) => {
        if (event.request.url.match(/preview=true/)) {
            return;
        }
    });

    // ensure the service worker takes over as soon as possible
    global.addEventListener("install", event => event.waitUntil(global.skipWaiting()));
    global.addEventListener("activate", event => event.waitUntil(global.clients.claim()));

    // set up the cache
    global.toolbox.precache(["/", "/offline/"]);
    global.toolbox.router.get("/wp-content/uploads/*", toolbox.cacheFirst);
    global.toolbox.router.get("/*", toolbox.networkFirst, {NetworkTimeoutSeconds: 5});

    // redirect offline queries to offline page
    self.toolbox.router.get("/(.*)", function (req, vals, opts) {
        return toolbox.networkFirst(req, vals, opts).catch((error) => {
            if (req.method === "GET" && req.headers.get("accept").includes("text/html")) {
                return toolbox.cacheOnly(new Request("/offline/"), vals, opts);
            }

            throw error;
        });
    });
})(self);
JacobTheDev
  • 17,318
  • 25
  • 95
  • 158