v156 · retry · service worker as the network

Flaky network recovery

A widget module fails to load, and a retry button tries again. Pre-156, the retry never leaves the module map; on Chrome 156 it reaches the network and recovers. To make that observable on a healthy connection, a service worker plays the unreliable network — dropping the first fetch, serving the module on the next — while the page counts how many attempts the "network" actually saw.

The unreliable network

The service worker here is only the network simulator — the module-map behaviour under test is entirely the browser's. The worker fails the first N fetches of the widget URL with Response.error() (a genuine network error) and serves a real module afterwards. Whether a retry ever reaches the worker is exactly the contract Chrome 156 changed.

Service worker not installed yet.

Load the widget, then retry

0import() attempts by the page
0fetches the network layer saw

The widget mounts here once its module finally evaluates.

Install the network simulator first.

event log

The retry pattern this enables

async function importWithRetry(url, attempts = 3) {
  for (let i = 1; i <= attempts; i++) {
    try {
      return await import(url);
    } catch (error) {
      if (i === attempts) throw error;
      await new Promise((r) => setTimeout(r, 250 * 2 ** i)); // backoff
    }
  }
}
// Pre-156 this loop was pointless: attempts 2..n rejected from cache.
// From Chrome 156 each attempt is a real fetch, so it recovers as soon
// as the network does.

see also