JavaScript
intermediate
#javascript#modules#bundlers

Import maps and the slow departure from bundlers

How import maps are changing the JavaScript landscape by letting browsers resolve modules natively, reducing our dependence on traditional bundling tools

July 3, 2025
6 min read
Share this article:

Import maps let browsers look up JavaScript modules on their own, without the bundling step that has shaped web build pipelines for more than a decade. Chrome, Edge, and Safari ship the feature out of the box, and Firefox joined them in version 108 after a long stint behind a flag. This coverage means more than ninety-three percent of global users can run an import map today, although older devices and some in-house browsers still need a polyfill. The shift invites a fresh conversation about when bundlers remain essential and when a plain set of modules, served as individual files, is the simplest choice.

What an import map does

An import map is a short JSON document that the browser reads before it starts resolving JavaScript modules. It translates bare specifiers such as lodash or @org/ui/button into absolute URLs. Because that translation happens at runtime, you can rename or move files without touching the source code. The concept left the WICG incubator and moved into the HTML standard earlier this year, closing a multiyear design loop that balanced power with safety.

MDN frames import maps as the bridge between Node-style imports and the open web, freeing authors from long relative paths and complex build rewrites.

Where import maps support stands in mid-2025

Caniuse lists full support for import maps in Chrome since version 89, Edge since the same baseline, Safari since 16.4, and Firefox from 108 onward. Independent compatibility trackers confirm the same matrix across desktop and mobile channels, pushing worldwide coverage above ninety percent.

The remaining gap sits mostly in embedded browsers and older enterprise systems, so production sites still ship a tiny polyfill for defence in depth. The most common choice is ES-Module-Shims, a thirteen-kilobyte script that bails out instantly when native support is present.

Why bundlers became the norm

Bundlers answered two early web constraints. First, HTTP 1.1 allowed only a handful of parallel connections, so concatenating many scripts into one file reduced queueing delays. Second, JavaScript lacked any native module syntax until ES2015. Tools like Browserify, RequireJS, and later Webpack filled both gaps, wrapping each module in a private scope and packing everything into a single request.

HTTP 2 and HTTP 3 changed the landscape by multiplexing many files over one connection, trimming the latency penalty that once justified massive bundles. Studies from network researchers and CDNs report meaningful gains for small files under these newer protocols. Yet bundling still helps in two areas: it lets compressors find more repeated code, and it hides implementation details behind a single hashed filename that the browser can cache forever.

Building without a bundle

Developers now explore "unbundled" builds that ship source modules directly, anchored by an import map that fixes every bare specifier to a content-addressed URL. Early adopters report shorter rebuild times and simpler deployments. One JavaScript runtime engineer described the approach as "the raw web at your fingertips" after running a small component library with no transpiler or bundler for a month. A newer case study, published in May, shows the same pattern in Deno and modern browsers, arguing that native resolution lets teams scale without third-party tool chains.

Shopify, which manages thousands of theme and app scripts, contributed patches to Chrome and WebKit to support multiple import maps on one page, making the pattern safe at large scale. Rails added first-class helpers for import maps as well, offering a no-bundler path that still plugs into the asset pipeline's digests and cache headers.

Performance and cache trade-offs

Real-world measurements show a mixed picture. A five-year-old experiment at Khan Academy found that unbundled modules slowed first render compared with one compressed bundle, even on HTTP 2. More recent numbers look better because HTTP 3 reduces head-of-line blocking, but there is still overhead in building many small dependency graphs and in transferring duplicate boilerplate between modules. The right answer depends on the size and makeup of the app, the prevalence of shared code, and the time-to-first-byte goals.

Caching strategy changes as well. With a bundle, one hash change invalidates the full payload; with import maps, each file has its own cache lifetime. You gain the ability to update a single helper without forcing users to redownload everything, but you must now ship a new import map whenever any URL changes. Work in the HTML spec and in community tooling explores signed external maps that let the browser cache the mapping separately from the page, easing that churn.

Polyfills and fallback paths

ES-Module-Shims fills three gaps. It adds import map support in browsers that only understand basic modules, it implements the integrity attribute for map security, and it mimics future features such as JSON and CSS imports for consistency across environments. The library checks HTMLScriptElement.supports('importmap') before doing any work, so modern browsers skip its code path entirely. Developers can drop the script conditionally or keep it on every page for simplicity; the weight difference is negligible next to most application code.

Limitations and open questions

Import maps are static. The browser must see the final mapping before it begins any module fetch, and the current standard disallows adding or changing a map once parsing starts. The issue tracker for the feature holds long discussions about dynamic maps, but consensus remains elusive because late changes would complicate the module graph and caching rules. There is also no tree-shaking, minification, or dead-code elimination at this layer, so heavy apps still lean on a bundler for production builds even if day-to-day development works fine unbundled.

Choosing your path

If your site serves a handful of well-scoped modules, or if you run code at the edge where startup cost matters more than peak throughput, an import map with no bundler can simplify infrastructure and reduce build minutes. If you distribute a large single-page app, bundle size and compression savings may still outweigh extra requests, and tools like Vite or Rollup can emit an import map alongside the bundle to ease gradual migration.

Either way, the existence of native import maps shifts the decision from "must we bundle at all" to "where does bundling still help." Testing both setups with real metrics in your own environment remains the surest guide. The web platform now gives you the freedom to decide.