v156 · module map · resource timing
Retry refetch probe
Two import() calls, one failing URL, and the Resource Timing buffer as the witness. Whether the second call reaches the network — one fetch recorded, or two — is precisely what "avoid caching module failures" changed. The verdict below is read from what this browser actually did.
Import a failing URL, twice
module URL for this run: —
| # | import() result | settled in | network fetches of this URL so far |
|---|---|---|---|
| no attempts yet | |||
How the probe reads the truth
Every real network attempt for a URL — even one that ends in a 404 — lands an entry in the Resource Timing buffer, with responseStatus on it. A rejection served from the module map cache lands nothing, because no request was made. So the count of entries whose name equals the module URL is the count of network attempts:
const fetches = performance.getEntriesByType("resource")
.filter((entry) => entry.name === moduleURL).length;
try { await import(moduleURL); }
catch (error) { /* TypeError: Failed to fetch dynamically imported module */ }
// pre-156: second import() → count unchanged (failure cached)
// 156+: second import() → count + 1 (real refetch)
Both attempts still reject either way — the URL really is broken. The change is only that the retry is allowed to try. The settle time column shows another tell: a cached failure rejects in well under a millisecond-scale round trip, while a refetch takes a real network round trip.