Od fetch() do pierwszego bajtu
- data
- kategoria
- Frontend
- także w
- Networking · Observability
- czytanie
- 1 min / 256 słów
Mamy kod:
const response = await fetch(
"https://api.example.com/users/42"
);
Co dzieje się pomiędzy tą linią a otrzymaniem Response?
Nie istnieje jedna identyczna ścieżka dla każdego requestu, ale możemy zbudować właściwy model.
1. Fetch tworzy request abstrakcyjny
Aplikacja definiuje:
URL
method
headers
body
credentials mode
cache mode
redirect mode
signal
Browser waliduje request zgodnie z Fetch i security model.
JavaScript nie tworzy raw HTTP bytes.
2. Browser sprawdza polityki i lokalny stan
Zależnie od requestu mogą wejść:
HTTP cache
cookies
CORS
service worker
redirect policy
Przykładowo request cross-origin może wymagać preflight.
To oznacza, że:
one fetch()
może oznaczać:
zero origin requests -> cache hit
one request -> normal network fetch
multiple requests -> preflight / redirects
3. Browser potrzebuje odpowiedniego connection
Może już istnieć connection nadające się do reuse.
Jeżeli nie:
DNS resolution
|
v
transport setup
|
v
TLS / secure session setup
|
v
HTTP protocol negotiation
Dokładne etapy zależą od HTTP version i istniejącego connection state.
4. Request staje się wire representation
Semantycznie:
GET /users/42
Accept: ...
Cookie: ...
ale sposób przesłania zależy od wersji.
HTTP/1.1
-> textual message framing
HTTP/2
-> binary frames on an HTTP/2 stream
HTTP/3
-> HTTP frames on QUIC streams
Aplikacja nie powinna odczuwać tej różnicy funkcjonalnie.
5. Backend zaczyna odpowiadać
Najpierw pojawiają się response headers.
W DevTools część czasu do tego momentu zwykle kojarzymy z TTFB:
request start
|
v
network + server work
|
v
first response byte
TTFB nie jest więc po prostu:
backend execution time
Może zawierać również koszty sieci i connection setup.
6. fetch() może dać Response, zanim pobierzemy całe body
const response = await fetch(url);
Następnie:
const data = await response.json();
To dwa różne etapy.
Przy dużym lub streamingowym response body różnica może być znacząca.
Model:
headers available
|
v
Response object
|
v
body continues arriving
|
v
body consumed
7. DevTools pokazuje efekt wielu warstw
Network panel może pokazać:
Queueing
Stalled
DNS
Initial connection
SSL
Request sent
Waiting / TTFB
Content download
Nie każdy request przechodzi przez każdy koszt.
Jeśli connection jest reuse'owane:
DNS/TCP/TLS cost ≈ already paid
Jeśli odpowiedź pochodzi z cache, ścieżka może być jeszcze krótsza.
Jeśli request jest HTTP/2 albo HTTP/3, wiele requestów może współdzielić niższe warstwy connection.
Cały model
JavaScript
|
v
Fetch API
|
v
browser policy + cache + cookies
|
v
HTTP semantics
|
v
HTTP/1.1 | HTTP/2 | HTTP/3
|
v
TCP | QUIC
|
v
network
|
v
backend
|
v
response headers
|
v
Response
|
v
response body
To jest najważniejszy rezultat tej serii.
Kiedy frontend jest wolny, pytanie:
„czy API jest wolne?”
jest zwykle zbyt ogólne.
Lepsze pytania brzmią:
Czy request w ogóle wyszedł do sieci?
Czy czekał na connection?
Czy został poprzedzony preflightem?
Czy requesty są serializowane przez kod?
Jaki protokół został użyty?
Kiedy przyszły headers?
Jak długo pobierało się body?
Dopiero z takim modelem Network panel staje się narzędziem diagnostycznym, a nie tylko listą endpointów.