Konrad Kowalski (rootsher)Principal Platform & Reliability Architect000100000000011100000010000100100010000111010101

HTTP/1.1: skąd wzięły się waterfall i bundling

data
kategoria
Networking
także w
Frontend
czytanie
1 min / 205 słów

Frontendowe praktyki takie jak:

text
bundle everything
sprite sheets
inline small assets
domain sharding

nie powstały przypadkiem.

Duża część była odpowiedzią na koszt wielu requestów w HTTP/1.1.

Jeden connection, sekwencyjne odpowiedzi

Uproszczony model:

text
connection A:
request 1 -> response 1
request 2 -> response 2

Jeżeli response 1 jest wolny, kolejny request na tym connection musi czekać.

HTTP/1.1 miał pipelining, ale problemy wdrożeniowe i head-of-line behavior sprawiły, że browsery w praktyce polegały głównie na kilku równoległych connections.

Model strony wyglądał więc mniej więcej:

text
conn 1 ─ CSS ───── image
conn 2 ─ JS ─ font
conn 3 ─ image ─ image
...

Liczba równoległych torów była ograniczona.

Request overhead miał znaczenie

Każdy request niósł textual headers:

http
GET /assets/icon.svg HTTP/1.1
Host: example.com
Cookie: ...
Accept: ...

Przy setkach małych zasobów overhead był zauważalny.

Stąd bundling:

text
100 JS files
      |
      v
bundle.js

Zyskiwaliśmy mniej requestów kosztem większego pliku i gorszej granularności cache.

Domain sharding

Jeśli browser ograniczał równoległe connections per host, można było rozbić zasoby:

text
static1.example.com
static2.example.com

i uzyskać więcej równoległych połączeń.

Ale płaciliśmy:

text
more DNS
more TCP
more TLS

Był to hack wynikający z ograniczeń warstwy transportowej.

Frontend architecture dopasowała się do protokołu

To ważny wniosek.

Optymalizacje build tooling nie są niezależne od sieci.

Jeśli transport premiuje:

text
few large files

bundler będzie próbował zmniejszać liczbę requestów.

Jeśli transport radzi sobie dobrze z wieloma równoległymi streamami, optimum może przesunąć się w stronę:

text
more granular resources
better caching
selective loading

Oczywiście koszt requestu nigdy nie spada do zera.

Ale jego charakter się zmienia.

Największa zmiana HTTP/2

HTTP/2 nie zmienił tego:

http
GET /app.js

Nie zmienił też:

http
200 OK
Cache-Control: ...

Zmienił sposób przenoszenia wielu requestów przez connection.

Zamiast:

text
several connections
each mostly sequential

dostaliśmy:

text
one connection
many concurrent streams

To jest multiplexing.

I to fundamentalnie zmieniło frontendowy network waterfall.