HTTP/1.1: Where Waterfalls and Bundling Came From
- date
- category
- Networking
- also in
- Frontend
- reading
- 1 min / 251 words
Frontend practices such as:
bundle everything
sprite sheets
inline small assets
domain sharding
did not appear by accident.
A large part of them was an answer to the cost of many requests in HTTP/1.1.
One connection, sequential responses
A simplified model:
connection A:
request 1 -> response 1
request 2 -> response 2
If response 1 is slow, the next request on that connection has to wait.
HTTP/1.1 had pipelining, but deployment problems and head-of-line behavior meant that browsers in practice relied mostly on several parallel connections.
So the model of a page looked roughly like:
conn 1 ─ CSS ───── image
conn 2 ─ JS ─ font
conn 3 ─ image ─ image
...
The number of parallel lanes was limited.
Request overhead mattered
Every request carried textual headers:
GET /assets/icon.svg HTTP/1.1
Host: example.com
Cookie: ...
Accept: ...
With hundreds of small resources the overhead was noticeable.
Hence bundling:
100 JS files
|
v
bundle.js
We gained fewer requests at the cost of a bigger file and worse cache granularity.
Domain sharding
If the browser limited parallel connections per host, resources could be split:
static1.example.com
static2.example.com
to get more parallel connections.
But we paid with:
more DNS
more TCP
more TLS
It was a hack that followed from the limits of the transport layer.
Frontend architecture adapted to the protocol
That is an important conclusion.
Build tooling optimizations are not independent of the network.
If the transport rewards:
few large files
the bundler will try to reduce the number of requests.
If the transport handles many parallel streams well, the optimum can move towards:
more granular resources
better caching
selective loading
Of course the cost of a request never drops to zero.
But its character changes.
The biggest change in HTTP/2
HTTP/2 did not change this:
GET /app.js
Nor this:
200 OK
Cache-Control: ...
It changed how many requests are carried over a connection.
Instead of:
several connections
each mostly sequential
we got:
one connection
many concurrent streams
That is multiplexing.
And it fundamentally changed the frontend network waterfall.