spinny:~/writing $ less nextjs-16-cache-components.md
12Przez lata jednym z najbardziej irytujących pytań w Next.js było: „Czy ta strona jest statyczna czy dynamiczna?”. Wydaje się to prostym pytaniem, dopóki nie dodasz wywołania do `cookies()`, `fetch` z różnymi opcjami, klienta bazy danych, CMS, koszyka lub fragmentu niestandardowej treści.34Next.js 16 jest interesujący, ponieważ stara się uczynić tę rozmowę mniej tajemniczą. Nie eliminuje to złożoności, ale zmienia model mentalny: trasy są domyślnie dynamiczne, pamięć podręczna deklaruje się tam, gdzie jest to potrzebne, a `Suspense` staje się naturalnym sposobem komponowania szybkich powłok z części, które pozostają świeże.56Cechą, którą należy zrozumieć, są komponenty pamięci podręcznej. Stable Turbopack, React Compiler, `proxy.ts` i nowe interfejsy API unieważniające są ważne, ale dotyczą tego samego problemu: tworzenia szybkich aplikacji bez konieczności zgadywania, co framework zdecydował za kulisami.78## Ponieważ ta rzecz ma znaczenie910W prawdziwej aplikacji nie masz tylko „stron statycznych” i „stron dynamicznych”. Masz różne elementy i różne potrzeby.1112Karta produktu może zmieniać się kilka razy dziennie. Cena może zmieniać się częściej. Dostępność musi być prawie aktywna. Nazwa użytkownika jest osobista. Recenzje można przesyłać strumieniowo. Pasek boczny może być stabilny. Wózek nie.1314Jeśli potraktujesz wszystko jako jedną całość, zawsze znajdziesz się w jednej z dwóch skrajności:1516- agresywne buforowanie i ryzyko zobaczenia starych danych;17- dynamiczne renderowanie wszędzie i wydajność gorsza niż to konieczne.1819Cache Components służy właśnie do uniknięcia tego fałszywego wyboru.2021## Model w praktyce2223Za pomocą `cacheComponents: true` możesz zadeklarować, co można buforować, używając `"use cache"`. Następnie możesz powiązać czas trwania i znaczniki z `cacheLife()` i `cacheTag()`. Części dynamiczne pozostają dynamiczne i można je odizolować za pomocą `Suspense`.2425```mermaid26flowchart TD27 Request[Żądanie użytkownika] --> Shell[Powłoka buforowana]28 Request --> Dynamic[Sekcje dynamiczne]29 Shell --> FirstPaint[Pierwsza szybka treść]30 Dynamic --> Stream[Transmisja strumieniowa w napięciu]31 Stream --> Complete[Pełna strona]32```3334Konfiguracja jest niewielka:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647Duża zmiana nie dotyczy konfiguracji. Wszystko zależy od tego, jak zaczniesz pisać komponenty.4849```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';5354async function getProduct(slug: string) {55 'use cache';5657 cacheLife('hours');58 cacheTag(`product:${slug}`);5960 return db.product.findUnique({ where: { slug } });61}6263async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);6566 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}7374async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}7879export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;8182 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```9293Strona nie musi być w całości buforowana ani dynamiczna. Karta produktu może być szybka i wielokrotnego użytku. Zapasy mogą pozostać świeże. Użytkownik widzi coś od razu, nie czekając na najwolniejszą część.9495## `use cache` to dokumentacja wykonywalna9697To, co podoba mi się w `"use cache"`, to to, że zmusza cię do wyraźnego wyrażenia swojej intencji. Kiedy czytasz funkcję, od razu rozumiesz, że ktoś zdecydował: „te dane można ponownie wykorzystać”.9899Jest to szczególnie przydatne, gdy nie używasz `fetch`. Wiele aplikacji odczytuje dane z Prisma, Drizzle, wewnętrznych zestawów SDK, klientów CMS lub funkcji usługowych. W takich przypadkach stare rozumowanie oparte wyłącznie na opcjach `fetch` nie wystarczyło.100101Praktyczna zasada:102103- zawartość pamięci podręcznej stosunkowo stabilna;104- używaj szczegółowych tagów;105- pozostawia dynamiczne uprawnienia, sesje, koszyki, powiadomienia i stany transakcyjne;106- umieść powolne części wewnątrz `Suspense`;107- zmierzyć, zanim powiesz „poprawiliśmy wydajność”.108109## Unieważnij bez wyrzucania wszystkiego110111Pamięć podręczna jest użyteczna tylko wtedy, gdy możesz ją dokładnie zaktualizować. Tutaj `cacheTag`, `revalidateTag` i `updateTag` stają się ważne.112113Przykład:114115```typescript116'use server';117118import { updateTag } from 'next/cache';119120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125126 updateTag(`product:${productId}`);127}128```129130Ważnym szczegółem jest metka. `product:${productId}` wyznacza dokładną granicę. `products` mówi ogromnemu wiadro. Na początku ogromne wiadro jest wygodne; po kilku miesiącach staje się to powodem unieważnienia połowy aplikacji w celu zmiany tytułu.131132## Stabilny Turbopack: część, którą słyszysz każdego dnia133134Next.js 16 przenosi Turbopack do centrum rozwoju i kompilacji. Nie jest to może najbardziej poetycka cecha, ale odczuwa się ją podczas pracy: serwer uruchamia się wcześniej, szybsze odświeżanie, kompilacje przestają przypominać wymuszoną przerwę na kawę.135136To powiedziawszy, nie migrowałbym bazy kodu pełnej niestandardowych wtyczek z zamkniętymi oczami. sprawdziłbym:137138- kompilacja lokalna;139- niestandardowe importy;140- MDX, SVG i CSS;141- Pozostały wtyczki pakietu internetowego;142- strony krytyczne;143- różnice w czasie budowy.144145W przypadku nowych projektów zacząłbym od ustawień domyślnych. W przypadku dojrzałych przeprowadziłbym migrację odmierzoną.146147## React Compiler: usuń hałas, a nie myśl148149React Compiler 1.0 jest stabilny, a Next.js 16 obsługuje go za pomocą `reactCompiler`. Obietnica polega na zmniejszeniu ilości ręcznego zapamiętywania: mniej `memo`, mniej `useMemo`, mniej `useCallback` używanych „dla bezpieczeństwa”.150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Nie traktowałbym go jak magicznego pyłu. Kompilator pomaga, gdy kod jest zgodny z regułami React. Jeśli komponenty mają dziwne skutki uboczne, ukryte mutacje lub źle używane hooki, należy to najpierw naprawić.163164Zdrowy sposób, aby spróbować:1651661. aktualizacja `eslint-plugin-react-hooks`;1672. naprawić faktyczne naruszenia;1683. włącz to na kontrolowanym obszarze;1694. mierzyć czas i zachowanie kompilacji;1705. usuwaj ręczne zapamiętywanie tylko wtedy, gdy nie jest już potrzebne.171172Celem nie jest usunięcie każdego `useMemo`. Celem jest zaprzestanie pisania zapamiętywania zapobiegawczego, ponieważ boimy się renderowania.173174## `proxy.ts` i granicę sieci175176Stary `middleware.ts` staje się `proxy.ts`. To zmiana nazwy, ale ma to sens: ten plik znajduje się na granicy żądania, a nie jest to tradycyjne, ogólne oprogramowanie pośredniczące w stylu backendu.177178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188189 return NextResponse.next();190}191```192193Zasada jest tutaj prosta: trzymaj się małych rozmiarów. Przekierowanie, routing uwierzytelniania, nagłówki, niezbędne przeróbki. Jeśli zaczyna sprawiać wrażenie drugiego backendu, prawdopodobnie robi za dużo.194195## Jak naprawdę miałbym wyemigrować196197Nie włączałbym wszystkich funkcji na raz. Zrobiłbym to:1981991. Aktualizuję Next, React i React DOM;2002. Uruchamiam oficjalny codemod;2013. Naprawiam istotne zmiany w `params`, `searchParams`, `cookies()`, `headers()` i `draftMode()`;2024. Przeprowadzam migrację `middleware.ts` do `proxy.ts`;2035. Sprawdzam kompilacje i krytyczne strony;2046. Włączam komponenty pamięci podręcznej w sekcji, w której pamięć podręczna powoduje obecnie tarcia;2057. Definiuję konwencje dotyczące znaczników i unieważniania;2068. Próbuję oddzielnie React Compiler;2079. porównanie wskaźników przed i po.208209Dobra migracja to nie ta, która wykorzystuje wszystkie nowe funkcje. To sprawia, że zachowanie aplikacji jest bardziej czytelne.210211## Co się zmienia w sposobie myślenia212213Najbardziej użyteczną rzeczą w Next.js 16 jest to, że zmusza Cię do lepszego nazywania intencji. Funkcja to nie tylko „pobranie produktu z bazy danych”. To „zdobądź produkt, mogę go buforować godzinami, unieważniam go tym tagiem”. Komponent to nie tylko „renderowanie strony”. To „to jest szybka powłoka, ten utwór jest osobisty, to jest przesyłane strumieniowo”.214215Na początku wydaje się, że jest więcej pracy. Wtedy staje się to formą spokoju. Decyzje dotyczące wydajności nie są już ukryte w kombinacji ustawień domyślnych, heurystyki i pamięci plemiennej. Są w kodzie.216217## Przydatne źródła218219- [Informacje o wydaniu Next.js 16](https://nextjs.org/blog/next-16)220- [Składniki pamięci podręcznej — dokumentacja Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [użyj pamięci podręcznej - dokumentacja Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [Kompilator reakcji v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16, komponenty pamięci podręcznej i kompilator React: co naprawdę się zmienialines 1-223 (END) — press q to close