The gotchas of caching ES-modules

Going all modern/native with an offline PWA using javascript modules, I had some problems getting the serviceworker cache to work as intended with es6 modules.

For my future self or anybody else googling around I thought I would write up on my findings quickly.

To use native modules the main-file must be loaded from a script-tag with a type=”module” attribute on it. But it turns out that script[type=module] makes a different kind of request to the server (specifically the mode+credentials parts).

Image for post
Image for post
Two different requests for the same file

This means that when we try to match that request against the cache, with cache.match(event.request), it won’t match the cache-entry for the file added using the normal request-type or the string-based approach cache.addAll([‘app.js’, ‘module1.js’, …]).

The solution should be to manually match the request-type when adding the the cache. Big shoutout to @jeffposnick for pointing me towards this 🤘

But it turns out this doesn’t work perfectly either. So I actually ended manually creating the request-object in the fetch-listener to match the cache… this works, but doesn’t seem very pretty, and hopefully will go away as this matures!

Obviously this is pseudo-code, and you should come up with a better approach for when to actually create the request objects yourself, and you probably want to fallback to the network as well… (and other things)

Written by

Google Dev Expert and Software Development Manager at @IMPACTdigitaldk

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store