HTTP/2 Multiplexing and Asset Bundling Strategies

The transition to HTTP/2 multiplexing has fundamentally transformed modern front-end build pipelines, shifting the primary goal from minimizing total request counts to maximizing caching efficiency and granular delivery. Under HTTP/1.1, developers relied on massive, monolithic bundles and image spriting to bypass browser connection limits. HTTP/2 eliminates these connection bottlenecks by allowing concurrent requests over a single connection, enabling a more balanced, modular bundling architecture that dramatically improves long-term caching and reduces initial page load times.

The HTTP/1.1 Baseline: The Need for Monolithic Bundles

Under HTTP/1.1, browsers were limited to opening between six and eight concurrent TCP connections per domain. Each request suffered from head-of-line blocking, where a slow or stalled request held up subsequent assets in the queue.

To mitigate this constraint, web developers adopted aggressive packaging strategies:

  • Combining all application code and third-party libraries into a single, massive JavaScript or CSS file.
  • Utilizing CSS image sprites to merge dozens of small graphics into one file.
  • Implementing domain sharding to trick browsers into opening additional connections.

While this reduced round-trip times (RTT) and connection overhead, it introduced significant drawbacks, particularly regarding cache invalidation. Changing a single line of application code invalidated the entire production bundle, forcing returning users to re-download unchanged library dependencies repeatedly.

How HTTP/2 Multiplexing Changes the Game

HTTP/2 replaces plain-text HTTP/1.1 protocols with an optimized binary framing layer. Instead of opening multiple TCP sockets, HTTP/2 uses a single persistent TCP connection per origin.

Within this single connection, HTTP/2 introduces independent, bidirectional streams. This is known as multiplexing:

  • Multiple requests and responses can be in flight simultaneously.
  • Packets are interleaved across the connection, preventing one large asset from blocking the delivery of smaller, critical assets.
  • HPACK header compression drastically cuts down the metadata overhead previously associated with firing dozens of separate HTTP requests.

Because the cost of initiating individual network requests dropped dramatically, the architectural imperative to merge everything into one single file disappeared.

The Fallacy of Going Completely Unbundled

When HTTP/2 was first standardized, some proposed abandoning bundlers entirely in favor of serving hundreds of raw, individual ES modules (ESM). In practice, full unbundling harms performance due to several technical trade-offs:

  1. Compression Penalties: Compression algorithms like Gzip, Brotli, and Zstandard rely on finding repeated patterns across larger blocks of text. Compressing one 200KB file yields significantly better compression ratios than compressing fifty 4KB files separately.
  2. Dependency Waterfalls: Even with multiplexing, the browser must parse an initial JavaScript file to discover which sub-modules to import. If module A requires module B, which requires module C, the browser still endures serial network round trips to discover the full dependency tree.
  3. Server and Browser Overhead: Managing thousands of simultaneous streams introduces internal memory and processing overhead on both client and server engines, negating initial speed gains.

The Modern Approach: Granular Chunking

The transition to HTTP/2 has repositioned bundlers (such as Vite, Rollup, and Webpack) from concatenation tools to optimization engines centered around granular chunking.

Modern asset delivery strategies now rely on three core principles:

  • Route-Based and Component Splitting: Code is broken down based on entry points and dynamic imports. Users only download the JavaScript and CSS required for the initial view, fetching additional components on demand as they navigate.
  • Separating Vendor and Application Code: Stable third-party dependencies (like UI frameworks or utility libraries) are split into dedicated chunks distinct from rapidly changing business logic. When business logic updates, users retain the cached vendor chunks, saving significant bandwidth on repeat visits.
  • Smart Bundle Sizing: Build tools aim for a sweet spot in chunk size—typically between 30KB and 100KB (gzipped). This range is large enough to retain dictionary compression efficiency while remaining small enough to parallelize over HTTP/2 multiplexed streams without blocking critical path rendering.