Issue 1: Service Worker Debugging, RAIL on 3G, Offline Analytics, Progressive Web Apps, Rollupify & more.

Totally Tooling Tears is a new companion to Matt and Addy’s YouTube show Totally Tooling Tips. It’s a raw weekly brain-dump of notes, issues and workarounds we’ve found building apps and libraries over the last 7 days.

Debugging Service Workers in Firefox — a small gotcha

Firefox recently added support for debugging Service Worker and Push Notifications via about:debugging which has been super helpful for testing.

One edge case we both ran into (independently) this week was if you’re testing against both Firefox stable and Firefox Nightly, you can run into a surprising issue with your shared user profile getting corrupted and Service Worker failing to correctly register. This cost us a few hours and was as sad as the day we discovered our Universal Remote Control did not, in fact, control the Universe. The “fix” for this was deleting our profiles from the file system and restarting Firefox.

Advice from Firefox engineers was to make sure you’re using separate user profiles for debugging in different channels of Firefox. They’re super nice so they’re going to look at whether they can improve profile upgrading so this isn’t an issue for others. Thanks for the quick responses, browser friends ❤.

Debugging Service Workers in Chrome (Sources, what?)

If you’ve been debugging a Service Worker in Chrome, you’re probably familiar with the Service Workers tab in the Resources panel:

Testing out Smaller Pictures — a Web Worker image compression Progressive Web App I built last week.

Something we noticed caught a lot of folks at events by surprise was that in addition to about:serviceworker-internals, there’s also a Service Worker sub-panel in Sources. This has options for forcing updates during development every time your page reloads or just unregistering the selected Service Worker. It feels a bit hidden in it’s current location and there may be opportunities to improve the UX there.

Service Workers and Cookies

During our Progressive Web Apps event in London, one question we got was how do you interact with cookies from a Service Worker context?. Cookies are not included with fetch requests by default, but you can include them as follows: fetch(url, {credentials: ‘include’}). You can also communicate with a controlled page using postMessage() if you want to pass cookie data around.

What we could really use is a clean API for interacting with cookies from SW and we might just get one in the form of the async cookies API. Mostly sharing as an FYI as we had no idea about this until we searched on GitHub.

RAIL in the real world (a score to target for 3G)

While building some recent apps, we wanted to keep the RAIL performance model in mind. RAIL defines some good numbers to target for cable/WiFi connections on desktop — like delivering first meaningful paint in under a second. Something we were missing is what good scores would look like in a 3G world. After talking it over with Paul Lewis, he suggested the following (which we found reasonable):

  • First load (network-bound), 3G (normal, as defined by WPT): First paint at 2s or sooner (including TLS handshake), Speed Index of 3,000 or less
  • Second load (disk-bound because SW): First paint at 300ms or sooner, Speed Index of 1,000 or less.

Offline Google analytics and Service Worker

Some of us have been shipping Progressive Web Apps lately and the topic of whether or not it’s worth caring about offline Google analytics (and offline queuing/syncing requests from those types of scripts) came up. For smaller apps, you might consider this way overkill, but if you’re a larger app or a content site, this may be a problem you’d like to cater for.

The Google IO app team ran into just this last year and put together a few ideas people can check out. There’s the IOWA15 offline analytics script as well as this sample from the GoogleChrome SW samples repo. Also read the IO app case study if you want more context around how to tackle this. I think we could do a better job of wrapping this work up into a reusable script and we’re going to look at doing this in the coming months.

Progressive Web Apps on iOS

Progressive Web Apps on iOS are a really interesting topic and again came up at the event we held in London this week.

  • Progressive enhancement is key here and you can still get a fast first meaningful paint on Safari for iOS using some of the app shell architecture decisions we suggest for Progressive Web Apps. SW just helps you get instant loading for repeat visits. See which has a fantastic experience on Chrome/Android but a good one on iOS too, just without SW or Push.
  • We wouldn’t recommend it personally, but if you absolutely need to, you can still craft an offline experience using Service Worker that falls back to AppCache. If you have a really strong reason to support offline on iOS (maybe for a very simple single-view app), it might make sense to support both AppCache and Service Worker, otherwise ignore it. Tooling for this has started to appear and some folks have looked at building abstractions around both offline mechanisms. When both a Service Worker registration and an AppCache are available for the navigation of resources, if the navigation happens to be under the scope of a SW, it will bypass the AppCache. There’s again something to be said about needing to be careful here as you can end up in uncanny valley pretty easily with all things AppCache related. Browser vendors are looking to deprecate the feature.

Service Worker is currently labelled ‘Under Consideration’ on the WebKit feature status dashboard, so there’s always a possibility we’ll get to see it supported some day.

Runtime Service Worker caching helpers for third-party scripts

We’ve been playing around with sw-toolbox a bunch for some of our projects. One point of friction we ran into was having to configure it to properly runtime cache third-party origins for different assets. Things like Google Fonts. We’re thinking about building a set of easily reusable helpers here that let you avoid having to configure support for such origins yourself (see So, we’d take care of doing this with sw-toolbox:

// Google Fonts

global.toolbox.router.get(‘/(.+)’, global.toolbox.cacheFirst, {origin: /https?:\/\/fonts.+/})

// Google hosted static content

global.toolbox.router.get(‘/(.*)’, global.toolbox.cacheFirst, { origin: /\.gstatic\.com$/ });

If we can get to a place where you just drop in a helper file that tackles say, SW runtime caching for Google CDNs or TypeKit and so on, that would really help ease getting Progressive Web Apps built that support assets that aren’t or can’t be local.

Gulp 4.0

We got out our new Totalling Tooling Tips mini-tip on upgrading to Gulp 4 earlier this week and had Blaine Bublitz from the Gulp team review. One thing we didn’t realise was that Gulp 1.2 ( already supports both Gulp 3 and 4. So if you’re upgrading, just keep that in mind. Matt is hacking on a new version of WSK using Gulp 4 over at (It even has some tests ;) ).

Why Matt has a Love / Hate Relationship with ES2015

First off, we both ❤ ES2015.

But there was a long day where Matt simply looked like this:

Basically, when transpiling ES2015, you need to manage how imports and requires are managed. Basically, for a sw-toolbox, a tool we’ve been working on, we needed to transpile the code so anyone can make use of it, but as a library, we didn’t want the window object to fill up with anything other than what the library intended, and using rollup (with plugins) and babel you get code that use require and imports to work in a browser, BUT modules lost their scoping.

This was about the point Matt cried, Addy laughed (what an evil man).

Rollup would merge files without any consideration for scoping and Babel would transpile this merged up blob of javascript, hence no scoping.

Browserify + babelify was the old approach Matt was use to, but Addy pointed up Rollup’s tree shaking is awesome at reducing the file size of the final JS, so in comes Nolan Lawsons Rollupify: to get the best of all the scenarios!!!

…..still, can I haz full ES2015 natively support now please? :)

Matt’s Minor Sass Discovery

Did you know that Sass doesn’t dedupe imports? Nah neither did I. I was working on a new version of my site and realised the final CSS was smaller if I figured out CSS for the individual “components” on a page, deduped and then inlined the files myself — WEIRD, but makes sense why Sass doesn’t because of dependencies might get weird with just inlining — but Matt found it weird. It looks like sass might look for a way to fix this:

That’s a wrap. We’ll try not to console.cry() so much next week :)