Sitemap

Some Service Worker Absurdity

4 min readJun 19, 2025

--

It’s been years since this lovely primitive landed on all relevant browsers but the current state feels stuck in the 90s’ and is hostile for no reason:

  • if the ServiceWorker is registered as a module Firefox might throw out of the box when statically importing more complex files
  • in Chrome/ium + Edge browsers you cannot use lovely shortcuts such as https://esm.run/@project/module because it does a redirect and, apparently, that’s not allowed
  • if you use the right URLs with no redirects, Firefox breaks and those imports also cannot be asynchronous, module or not … the dynamic import(...) is not allowed for “reasons” nobody can actually reason about (keep reading)
  • if the ServiceWorker is not registered as a module, we’re off with blocking/synchronous importScripts, a Jurassic, awkward, and synchronous, global polluter for an API space where nothing can block or be synchronous by design ( see event.respondWith(value:Promise) and caching based APIs, all async )

Now … “what if I told you” that none of these imposed limitations or forever unresolved bugs make any sense, when one could write a ServiceWorker like this one and no browser would complain about it?

let defaultValue = null;

const dflt = (_, value) => {
defaultValue = value.trim();
};

const named = (_, values) => {
const literal = [`default:${defaultValue ?? 'null'}`];
for (const exports of values.split(',')) {
const [ref, name] = exports.split('as');
literal.push(`${name.trim()}:${ref.trim()}`);
}
return `\nreturn {${literal.join(',')}};`;
};

const amaro = fetch('https://esm.run/@webreflection/amaro').then(r => r.text()).then(
code => Function(
code
.replace(/\/\/# sourceMappingURL=.*$/, '')
.replace(/export\s+default([^;]+?);/, dflt)
.replace(/export\s*\{(.+?)\}/, named)
)()
);

// ... the rest of the logic

All limitations just vanished 🤦

  • I am effectively using a CDN with a redirect to …
  • dynamically import anything I want and …
  • evaluating runtime transformed code
  • without blocking anything at all!

Now bear with me, except for the last point of this list it feels like a circus of bad practices all compressed in a few lines of code … fair … but can we agree that there is nothing stopping me to bypass those absurd limitations, limitations or inconsistencies (Firefox breaking on static imports) that brought me to write that “horror show” of working code?

What’s that code for? Well, I’ve ported NodeJS amaro to the Web and a user asked me if it could transpile on the file .ts files via regular imports intercepted via a Service Worker so that I’ve created a Proof of Concept that showcases just that and … it works 🥳

No counter-arguments

One could argue that dynamic imports are bad because (really … why is that?) but if I need to evaluate code in a SW the situation just got worst.

The follow up comment would be “yeah but … you wrote that Service Worker code and you cannot use a Service Worker from a CDN, it’s your own code in there” and so was my own intent to use dynamic imports when/if needed (think about polyfills too for primitives and APIs not there yet).

It’s not that me evaluating code in my file is better than me explicitly importing a well known and maintained module from a well trusted CDN, you know? So why cannot we have dynamic imports when actually we can if we stretch a bit our nonsense beyond the “you must not use eval”?

I don’t want to write that code but if it’s the only way to make my site/service better, why should I listen to standards that have no concrete reasons to impose those limitations, when the alternative is to use blocking old primitives that could also be generated at runtime via server after UserAgent sniffing and pile up the list of bad practices as a result?

Extremely hard to debug

For all these Web standards promoters, use PWA and yada-yada, debugging a Service Worker has been, and still is, one of the most complicated and convoluted experience the Web development flow has to offer … how can we promote PWAs if nobody can easily understand what’s going on in there? Please let’s focus a bit on these “modern” primitives left as a developer excercise to master, circumvent, and bypass in limitations so that we can really tell the story about how easy it is to develop for the Web?

</rant>

I am now facing an issue that appears only on iPad (not on iPhone) and a slightly different one that appears only on Firefox and you cannot imagine how frustrating it is, among other thousand things I would like to focus on, solve these things that work seamlessly on Chrome/ium + Edge so thank you for your patience in reading this little rant but please help me reach out people behind browsers that could empathize with my sentiment and help moving forward around this topic: very much appreciated 🙏

P.S. yes, I’ve filed tons of bugs in Firefox / Mozilla … most of those are stuck forever with no follow-up, updates, fixes, nothing … dare I say Firefox is already dead but they don’t really want to announce it … the amount of APIs that break and remain broken for years start becoming unbearable but breaking on static imports out of a module? Hell no, that’s unacceptable folks, I am both afraid and sorry for this browser 😢

--

--

Andrea Giammarchi
Andrea Giammarchi

Written by Andrea Giammarchi

Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.

Responses (1)