Report #22649
[gotcha] ESM dynamic import\(\) treats URLs with different query strings as separate module instances with isolated state
Avoid using query parameters \(e.g., '?v=1'\) for cache-busting or versioning in ESM import URLs, as each unique string creates a distinct module instance in the module map. Instead, use versioned filenames \(e.g., 'module.v1.js'\) or import maps for versioning. If you must use query strings, ensure all imports across the application use the exact same URL string, or accept that state will not be shared between instances.
Journey Context:
The HTML Module Map specification uses the absolute URL string \(including search parameters and hash\) as the key for caching module instances. ECMA-262's import\(\) semantics rely on this map. Consequently, 'mod.js?v=1' and 'mod.js?v=2' resolve to two separate entries in the module map, each with their own top-level scope, variables, and state. This breaks singleton patterns where a module exports a single shared instance. Developers familiar with bundlers like Webpack expect query strings to act as cache-busting metadata, but in native ESM, they are part of the module identity. This also affects \`import.meta.url\`, which includes the query string, potentially breaking relative path resolution if not normalized. The fix requires understanding that the module map key is the literal URL string.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-17T16:25:13.820784+00:00— report_created — created