Next.js prefetch zmierzony: Partial Prefetching w 16.3
Partial Prefetching w Next.js 16.3 zmniejszył w naszym benchmarku prefetch nawet o 93%, ale treść adresu przychodzi po kliknięciu. Kiedy co się opłaca.

Next.js 16.3 (otwiera się w nowej karcie) zmienia to, czym jest Next.js prefetch. Z włączonym partialPrefetching (otwiera się w nowej karcie) App Router nie pobiera już payloadu dla każdego linku na ekranie: pobiera jeden wspólny szkielet na trasę, a treść zależną od adresu zostawia na po kliknięciu. Zbudowaliśmy jedną aplikację na sześć sposobów i przeklikaliśmy ją 3744 razy, żeby sprawdzić, co ta zamiana daje i ile kosztuje.
Na stronie dokumentacji ze 100 linkami w bocznym menu prefetch zmalał o 93%. Ceną jest czas: treść, która wcześniej była na ekranie niemal od razu, przychodzi teraz kilkaset milisekund po kliknięciu, za szkieletem strony. Która strona tej zamiany jest lepsza, zależy od strony i od jednego szczegółu Reacta, który łatwo przeoczyć.
- 93%
- 11×
- 298 ms
- 43 ms
Co zmienia Partial Prefetching
Do wersji 16.3 App Router (otwiera się w nowej karcie) robił prefetch dla każdego linku: gdy na ekran wjeżdżało N linków, pobierał mniej więcej N payloadów. Z partialPrefetching (wymaga cacheComponents (otwiera się w nowej karcie)) pobiera jeden App Shell (otwiera się w nowej karcie) na trasę: wszystko, co strona renderuje niezależnie od adresu. Linki do tej samej trasy dzielą ten jeden prefetch. Treść, która czyta params albo searchParams, rozwiązuje się po kliknięciu, chyba że link poprosi o więcej przez prefetch={true}.
Porównaliśmy sześć buildów tej samej aplikacji:
- L0, bez Cache Components: klasyczny App Router.
- C0, samo Cache Components.
- P0, Cache Components z Partial Prefetching i domyślnym inliningiem prefetchu.
- P1–P3, to samo z wyłączonym inliningiem, z małymi progami i z dużymi.
Każdy przeklikaliśmy w trzech nawigacjach: z katalogu 48 produktów na stronę produktu, ze strony dokumentacji ze 100 linkami w menu na inną stronę dokumentacji i z wyników wyszukiwania na inne wyszukiwanie przez jeden z ośmiu linków z prefetch={true}.
Bajty prefetchu: nawet o 93% mniej
W dokumentacji samo Cache Components pobierało z wyprzedzeniem każdy widoczny link z menu. Partial Prefetching zmienił to z 402 kB → 29 kB−93%lepiej, w 8,5 żądaniach zamiast 49. W katalogu oszczędność wyniosła 78%. Wyszukiwanie prawie się nie zmieniło, bo jego osiem linków z prefetch={true} nadal pobiera własne wyniki.
Partial Prefetching pobiera ułamek bajtów na stronach z wieloma linkami
Skompresowane bajty RSC pobrane przed kliknięciem · komputer, bez ograniczeń, późne kliknięcie · mediany z 20 przebiegów
| Pozycja | Katalog → produkt | Dokumentacja → dokumentacja | Wyszukiwanie → wyszukiwanie |
|---|---|---|---|
| L0 · Klasyczny router | 30 kB | 408 kB | 98 kB |
| C0 · Cache Components | 160 kB | 402 kB | 163 kB |
| P0 · Partial Prefetching | 34 kB | 29 kB | 107 kB |
| P1 · Bez inliningu | 33 kB | 32 kB | 105 kB |
| P2 · Mały inlining | 32 kB | 28 kB | 103 kB |
| P3 · Duży inlining | 34 kB | 33 kB | 105 kB |
Pokaż jako obraz

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
Jeden wiersz zasługuje na drugie spojrzenie. Włączenie Cache Components bez Partial Prefetching sprawiło, że katalog pobierał pięć razy więcej niż klasyczny router, 30 kB → 160 kB+426%gorzej: prerenderowane szkielety produktów da się wtedy pobrać osobno dla każdego linku. Jeśli włączasz Cache Components na stronach z wieloma linkami, od razu zdecyduj o Partial Prefetching.
Czy nawigacja jest naprawdę natychmiastowa?
Szkielet tak. Przy Partial Prefetching pojawiał się 43 ms–45 ms po kliknięciu na zwolnionym telefonie. Z tym, po co ktoś kliknął, czyli produktem albo artykułem, jest inaczej: potrzebuje żądania po kliknięciu.
Samo Cache Components pokazuje treść od razu, Partial Prefetching po jednym żądaniu
Od kliknięcia do pierwszej klatki z treścią zależną od adresu · telefon, ograniczenie Lighthouse mobile, późne kliknięcie · ms
- L0 · Klasyczny router
- C0 · Cache Components
- P0 · Partial Prefetching
Pokaż dane
| Pozycja | L0 · Klasyczny router | C0 · Cache Components | P0 · Partial Prefetching |
|---|---|---|---|
| Katalog → produkt | 375 ms | 60 ms | 262 ms |
| Dokumentacja → dokumentacja | 47 ms | 52 ms | 345 ms |
| Wyszukiwanie → wyszukiwanie | 40 ms | 41 ms | 43 ms |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
W dokumentacji samo Cache Components pokazało nowy artykuł po 52 ms, Partial Prefetching po 345 ms. Na stronie produktu różnica była mniejsza, 60 ms → 262 ms+337%gorzej, a najwolniejszy był klasyczny router, bo dla dynamicznej trasy nie miał nic wyrenderowanego z góry. Wyszukiwanie, gdzie każdy link ma prefetch={true}, pokazywało treść po 40 ms–43 ms w każdej konfiguracji.
Szkielet, który zobaczysz: 300 ms
Na stronie produktu trzy etapy przychodzą po kolei: szkielet, produkt, a potem część renderowana w chwili żądania.
Przy Partial Prefetching strona przychodzi w trzech krokach
Katalog → produkt · telefon, zwolniony, późne kliknięcie · od kliknięcia do każdego etapu na ekranie · ms
- Szkielet
- Treść
- Część z serwera
Pokaż dane
| Pozycja | Szkielet | Treść | Część z serwera |
|---|---|---|---|
| L0 · Klasyczny router | 375 ms | 375 ms | 375 ms |
| C0 · Cache Components | 60 ms | 60 ms | 342 ms |
| P0 · Partial Prefetching | 47 ms | 262 ms | 562 ms |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
W dokumentacji szkielet był widoczny przez 298 ms w każdym buildzie z Partial Prefetching. To nie jest czas sieci: odpowiedź dochodziła po 250 ms.
Wczesne kliknięcie
Kliknięcie 50 ms po hydratacji, zanim skończy się jakikolwiek prefetch, zabiera przewagę wszystkim, którzy pobierają z wyprzedzeniem. Samo Cache Components jest wtedy mniej więcej tak samo wolne jak Partial Prefetching, bo obie konfiguracje najpierw pokazują fallback, a potem odczekują 300 ms.
Przy wczesnym kliknięciu żadna konfiguracja niczego jeszcze nie pobrała
Kliknięcie 50 ms po hydratacji · telefon, zwolniony · od kliknięcia do treści · ms
- L0 · Klasyczny router
- C0 · Cache Components
- P0 · Partial Prefetching
Pokaż dane
| Pozycja | L0 · Klasyczny router | C0 · Cache Components | P0 · Partial Prefetching |
|---|---|---|---|
| Katalog → produkt | 367 ms | 374 ms | 389 ms |
| Dokumentacja → dokumentacja | 262 ms | 528 ms | 529 ms |
| Wyszukiwanie → wyszukiwanie | 234 ms | 404 ms | 339 ms |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
Ostatni etap, czyli część z serwera, dzieli te kliknięcia na dwie grupy. Przy Partial Prefetching w 6 z 12 wczesnych kliknięć na stronie produktu cała strona była na ekranie po 375 ms–400 ms. W pozostałych 6 dopiero po 650 ms–700 ms, a pomiędzy nie trafił żaden przebieg. Ta przerwa to mniej więcej 300 ms, które React odczekuje między dwoma odsłonięciami: ostatni etap pojawia się razem z produktem albo jedno odczekanie później.
Ostatni etap przychodzi razem z produktem albo mniej więcej 300 ms później
Katalog → produkt, wczesne kliknięcie · Partial Prefetching · telefon, zwolniony, przebieg HTTP/2 · od kliknięcia do ostatniego etapu na ekranie · ms
Pokaż dane
| Zakres | przebiegi |
|---|---|
| 375 ms–400 ms | 6 |
| 400 ms–425 ms | 0 |
| 425 ms–450 ms | 0 |
| 450 ms–475 ms | 0 |
| 475 ms–500 ms | 0 |
| 500 ms–525 ms | 0 |
| 525 ms–550 ms | 0 |
| 550 ms–575 ms | 0 |
| 575 ms–600 ms | 0 |
| 600 ms–625 ms | 0 |
| 625 ms–650 ms | 0 |
| 650 ms–675 ms | 3 |
| 675 ms–700 ms | 3 |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
Cały rachunek
Partial Prefetching przenosi bajty sprzed kliknięcia na po kliknięciu, a na stronie produktu dodatkowo je podwaja: odpowiedź nawigacji niosła dwie pełne kopie payloadu produktu, 13 kB → 26 kB+99%gorzej po kompresji. Licząc wszystko, co pobiera nawigacja, razem z prefetchem, w dokumentacji i tak wychodzi daleko do przodu.
Cała nawigacja w dokumentacji kosztuje mniej więcej jedną dziesiątą bajtów
Wszystkie skompresowane bajty RSC jednej nawigacji w dokumentacji, prefetch i nawigacja · telefon, zwolniony, późne kliknięcie
Pokaż dane
| Pozycja | Wartość | n |
|---|---|---|
| L0 · Klasyczny router | 463 kB | 20 |
| C0 · Cache Components | 458 kB | 20 |
| P0 · Partial Prefetching | 40 kB | 20 |
| P1 · Bez inliningu | 43 kB | 20 |
| P2 · Mały inlining | 39 kB | 20 |
| P3 · Duży inlining | 44 kB | 20 |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
Mniej więcej 11 razy mniej bajtów w dokumentacji i 2,2 raza mniej w katalogu. Hydratacja i opóźnienie reakcji na stronie startowej nie zmieniły się w żadnej konfiguracji.
Kiedy prefetch={true} się opłaca
<Link prefetch={true}> (otwiera się w nowej karcie) pobiera też dane z adresu strony docelowej, więc kliknięcie jest tak samo natychmiastowe jak przy pełnym prefetchu. Płacisz za każdy widoczny link: osiem linków wyszukiwania kosztowało 107 kB, więcej niż cała strona dokumentacji przy Partial Prefetching. Używaj go tam, gdzie kliknięcie jest prawdopodobne, a dane da się cache'ować: podpowiedzi wyszukiwania, link „dalej”, kilka pierwszych wyników. Na siatkach kart rób prefetch na zamiar (najechanie albo dotknięcie), zamiast oznaczać każdą kartę.
prefetchInlining: zostaw włączony
experimental.prefetchInlining (otwiera się w nowej karcie) łączy małe odpowiedzi prefetchu w jedną. Ustawienie domyślne i nasze dwa zestawy progów różniły się najwyżej jednym żądaniem i kilkoma kilobajtami, bez mierzalnej różnicy w czasie.
| Konfiguracja | Scenariusz | Żądania | Pobrane z wyprzedzeniem |
|---|---|---|---|
| P0 · Partial Prefetching | Katalog → produkt | 11 | 34,4 kB |
| P0 · Partial Prefetching | Dokumentacja → dokumentacja | 8,5 | 29,4 kB |
| P0 · Partial Prefetching | Wyszukiwanie → wyszukiwanie | 17 | 106,5 kB |
| P1 · Bez inliningu | Katalog → produkt | 16 | 33,4 kB |
| P1 · Bez inliningu | Dokumentacja → dokumentacja | 7 | 32 kB |
| P1 · Bez inliningu | Wyszukiwanie → wyszukiwanie | 23 | 105 kB |
| P2 · Mały inlining | Katalog → produkt | 11 | 31,8 kB |
| P2 · Mały inlining | Dokumentacja → dokumentacja | 7 | 27,9 kB |
| P2 · Mały inlining | Wyszukiwanie → wyszukiwanie | 17 | 102,8 kB |
| P3 · Duży inlining | Katalog → produkt | 10 | 33,8 kB |
| P3 · Duży inlining | Dokumentacja → dokumentacja | 7 | 33,1 kB |
| P3 · Duży inlining | Wyszukiwanie → wyszukiwanie | 16 | 105,1 kB |
Wyłączenie inliningu dodało pięć albo sześć żądań w katalogu i wyszukiwaniu, a przez HTTP/1.1 kosztowało to wczesne kliknięcie w katalogu: sześć połączeń na host się zapycha. Przez HTTP/2 (otwiera się w nowej karcie) kara znikała. Wszystkie inne konfiguracje wypadły na obu protokołach tak samo.
HTTP/2 ma znaczenie tylko przy wyłączonym inliningu
Katalog → produkt, wczesne kliknięcie · telefon, zwolniony · od kliknięcia do treści · HTTP/1.1 i HTTP/2 na przemian, po 12 przebiegów · ms
- HTTP/1.1
- HTTP/2
Pokaż dane
| Pozycja | HTTP/1.1 | HTTP/2 |
|---|---|---|
| L0 · Klasyczny router | 365 ms | 363 ms |
| C0 · Cache Components | 375 ms | 373 ms |
| P0 · Partial Prefetching | 387 ms | 386 ms |
| P1 · Bez inliningu | 440 ms | 372 ms |
| P2 · Mały inlining | 390 ms | 383 ms |
| P3 · Duży inlining | 387 ms | 386 ms |

Wykres jako obraz. Możesz go użyć na licencji CC BY 4.0, podając Outofplace jako źródło i link do tej strony.
Którą konfigurację wybrać
Samo Cache Components
- Treść adresu od razu po późnym kliknięciu
- Jeden prefetch na każdy widoczny link
- Setki kilobajtów na stronach z wieloma linkami
Z Partial Prefetching
- Szkielet od razu, treść adresu po jednym żądaniu
- Jeden prefetch na trasę
- O 78–93% mniej bajtów prefetchu tam, gdzie linków jest dużo
const nextConfig: NextConfig = {
cacheComponents: true,
// Jeden App Shell na trasę zamiast prefetchu na każdy link.
partialPrefetching: true,
};<Link href={`/search?q=${suggestion}`} prefetch={true}>
{suggestion}
</Link>Policz linki
Najwięcej zyskują strony z wieloma linkami do tej samej dynamicznej trasy: dokumentacja, siatki, feedy. Strona z kilkoma linkami do różnych stron zyskuje niewiele.
Zdecyduj dla każdej trasy
Tam, gdzie natychmiastowa treść jest ważniejsza niż bajty, a strony są statyczne, zostaw pełny prefetch; gdzie indziej włącz Partial Prefetching. Konfiguracja segmentu
export const prefetch = 'partial'(otwiera się w nowej karcie) pozwala przechodzić trasa po trasie.Oznacz prawdopodobne kliknięcia
Dodaj
prefetch={true}tam, gdzie następne kliknięcie da się przewidzieć, a dane da się cache'ować.Zaprojektuj szkielet
Na wolnym łączu będzie widoczny przez około 300 ms. Tytuł i nawigację umieść w części niezależnej od adresu: pojawia się niemal od razu.
Ta strona działa na Partial Prefetching: większość naszych stron ma mało linków, a te, które mają ich dużo (blog, case studies), są statyczne i lekkie. Nasze własne produkty, Portivo, Sprawna Matura i Levera, też stoją na Next.js.
Jak mierzyliśmy
Czego te dane nie mówią
To laboratorium: jedna maszyna, localhost, bez CDN, bez obrazów i fontów, wygenerowany tekst i sztuczne 300 ms opóźnienia po stronie serwera. Ograniczanie działa per żądanie, nie na poziomie pakietów, więc czasy bezwzględne są optymistyczne; liczą się porównania. Późne kliknięcie to najlepszy przypadek dla prefetchu, a wczesne to jeden konkretny wyścig; prawdziwi użytkownicy klikają wszędzie pomiędzy. Mechanika App Shella, podwojony payload produktu i 300 ms odsłonięcia dotyczą Next.js 16.3.6 z jego wersją canary Reacta i mogą się zmienić w wydaniu poprawkowym.
App Shell przychodzi przez prawdziwy link
Wspólny szkielet jest pobierany przez adres tego linku, który router zaplanuje jako pierwszy, a ta odpowiedź niesie całą stronę dla tego adresu. Kliknięcie dokładnie w ten link nie potrzebuje żadnego żądania. Cele kliknięć wybraliśmy niżej na stronie, żeby to nie podbijało wyników Partial Prefetching.
Co to jest prefetch w Next.js?
Kiedy <Link> pojawia się na ekranie, App Router w tle pobiera payload React Server Components strony docelowej, więc po kliknięciu nie trzeba czekać na sieć. Next.js 16.3 dodaje Partial Prefetching, który pobiera jeden wspólny szkielet na trasę zamiast payloadu na każdy link.
Czy nawigacja w Next.js z Partial Prefetching jest natychmiastowa?
Szkielet tak: w naszym benchmarku pojawiał się po około 45 ms na zwolnionym telefonie. Treść zależna od adresu przychodzi po kliknięciu: po około 262 ms na stronie produktu i 345 ms w dokumentacji, gdzie samo Cache Components pokazywało ją po około 52 ms. Linki z prefetch={true} zostają natychmiastowe.
Czy wyłączyć prefetch w Next.js?
Zwykle nie. Prefetch przyspieszał kliknięcie nawet o 300 ms i nie spowalniał hydratacji ani reakcji na wejście. Jeśli problemem jest ruch z prefetchu, Partial Prefetching tnie go nawet o 93% na stronach z wieloma linkami, nie rezygnując ze szkieletu.
Czym Partial Prefetching różni się od Partial Prerendering?
Partial Prerendering decyduje, co serwer renderuje z wyprzedzeniem: statyczny szkielet z dynamicznymi dziurami. Partial Prefetching decyduje, co przeglądarka pobiera przed kliknięciem: jeden szkielet na trasę, a dane z adresu po nawigacji. Partial Prefetching wymaga Cache Components.
Czy HTTP/2 ma znaczenie dla prefetchu w Next.js?
Niewielkie, dopóki inlining prefetchu jest włączony (domyślnie). W naszym teście HTTP/2 jedyna duża różnica wyszła przy wyłączonym inliningu i wczesnym kliknięciu: HTTP/2 usunął 68 ms kary, którą powodował limit sześciu połączeń na host w HTTP/1.1.