Skip to content

Why bundle?

Eugene Lazutkin edited this page Jun 9, 2016 · 1 revision

I/O is a major bottleneck of web applications. Every request incurs penalties including:

  • DNS lookup (expensive, but amortized after the first access).
  • Establishing a connection (amortized by HTTP/1.1 by reusing a connection).
  • Network lag for every single I/O action (especially suffered by mobile users).
  • Compression inefficiency (when similar payload is compressed separately).

On top of that browsers restrict a number of active I/O requests per host to 2-8 depending on a browser (see for example Maximum concurrent connections to the same domain for browsers). Additionally different protocols may have more restrictions.

Spreading requests across multiple hosts are not always possible, and incurs an overhead of an additional DNS lookup, which is an expensive procedure.

These problems are not new and there are numerous strategies to deal with them. But almost all of them assume that we are dealing with static resources. We know how to:

  • Bundle like resources for better compression and to reduce a number of I/O requests:
    • Concatenate CSS together.
    • Concatenate JavaScript together.
    • Create sprites for images.
  • Minify them:
    • Minify CSS.
    • Minify JavaScript.
    • Use advanced compression techniques for images, e.g., using Zopfli for PNG images, or providing WebP, or JPEG XR formats.

But all these techniques are rarely applicable for dynamic server responses.

The upcoming HTTP/2 can solve many problems, especially with its Server Push. But we are a few years away from its full acceptance, when the general internet infrastructure (especially proxy and cache servers) will support it. And even with HTTP/2 in place we still can leverage some application-specific intelligence as well as generic web application patterns.

Generally on the client side we have two contradictory trends:

  1. Requesting all data at once reduces number of I/O requests, yet suitable more for monolithic applications. While individual components can pick pieces of common data, it starts to get out of hand, when they want to update, or refresh relevant pieces separately.
  2. Splitting a web application on manageable components, makes for better design, but almost inevitably increases a number of small I/O requests, or introduces an awkward API to fetch/store data. Some frameworks force to isolate data from components, and deal with it separately breaking encapsulation.

In order to speed up a web application the following architecture is introduced:

  • A server provides a bundler service, which accepts a list of requests from a client, runs them on its behalf in parallel locally, collects results in a bundle, and sends it back as whole.
    • For security reasons a size of bundle is restricted, all URLs are verified against a whitelist, and can be rejected.
  • A client can collect and submit I/O requests as bundles.
    • The request bundle can be better compressed than individual requests.
  • A client can receive a bundled response and unbundle it.
    • The response bundle can be better compressed than individual responses.
  • All responses can be stored in an application-level cache for future use.
    • This provision can be used as the Server Push technique, when resources can be submitted to a client ahead of time.

In general, bundling reduces a number of required I/O requests to fetch dynamically generated server responses, provides more opportunities for enhanced compression, and reduces lag by collecting data at a server level (hopefully using fast internal connections right in a data center) rather than remotely.

An application-level cache opens up even more opportunities to speed things up:

  • Data requests and bundles can be issued before even loading any JavaScript library, making data ready when a web application just started to initialize.
  • Special endpoints can be created that return a bundle when requested to populate the cache in advance before individual data requests even made.

Future versions of a bundler, or custom bundlers, can incorporate more complex techniques, like issuing requests depending on results of other requests without round-tripping to a client.

Clone this wiki locally