spinny:~/writing $ vim nextjs-16-cache-components.md
1~2Po léta jedna z nejotravnějších otázek v Next.js zní: „Je tato stránka statická nebo dynamická?“. Zdá se to jako jednoduchá otázka, dokud nepřidáte volání `cookies()`, `fetch` s různými možnostmi, databázového klienta, CMS, nákupní košík nebo vlastní obsah.3~4Next.js 16 je zajímavý, protože se snaží tuto konverzaci učinit méně tajemnou. Neodstraňuje složitost, ale posouvá mentální model: trasy jsou ve výchozím nastavení dynamické, mezipaměť se deklaruje tam, kde je potřeba, a `Suspense` se stává přirozeným způsobem, jak skládat rychlé skořápky s částmi, které zůstávají čerstvé.5~6Funkce, kterou je třeba pochopit, jsou komponenty mezipaměti. Stable Turbopack, React Compiler, `proxy.ts` a nová rozhraní API pro zneplatnění jsou důležité, ale točí se kolem stejného problému: vytváření rychlých aplikací, aniž byste museli hádat, jak se framework v zákulisí rozhodl.7~8## Protože na této věci záleží9~10Ve skutečné aplikaci nemáte jen „statické stránky“ a „dynamické stránky“. Máte různé kousky s různými potřebami.11~12Produktový list se může několikrát denně změnit. Cena se může měnit častěji. Dostupnost musí být téměř živá. Uživatelské jméno je osobní. Recenze lze streamovat. Boční lišta může být stabilní. Vozík ne.13~14Pokud se vším zacházíte jako s jednou jednotkou, vždy skončíte v jednom ze dvou extrémů:15~16- agresivní ukládání do mezipaměti a riziko zobrazení starých dat;17- dynamické vykreslování všude a výkon horší, než je nutné.18~19Komponenty mezipaměti slouží právě k tomu, aby se zabránilo této falešné volbě.20~21## Model v praxi22~23Pomocí `cacheComponents: true` můžete deklarovat, co je možné uložit do mezipaměti pomocí `"use cache"`. Poté můžete přiřadit trvání a značky k `cacheLife()` a `cacheTag()`. Dynamické části zůstávají dynamické a lze je izolovat pomocí `Suspense`.24~25```mermaid26flowchart TD27 Request[Žádost uživatele] --> Shell[Skořápka uložená v mezipaměti]28 Request --> Dynamic[Dynamické sekce]29 Shell --> FirstPaint[První rychlý obsah]30 Dynamic --> Stream[Streamování v Suspense]31 Stream --> Complete[Celá stránka]32```33~34Nastavení je malé:35~36```typescript37// next.config.ts38import type { NextConfig } from 'next';39~40const nextConfig: NextConfig = {41 cacheComponents: true,42};43~44export default nextConfig;45```46~47Velká změna není v konfiguraci. Jde o to, jak začnete psát komponenty.48~49```tsx50// app/products/[slug]/page.tsx51import { Suspense } from 'react';52import { cacheLife, cacheTag } from 'next/cache';53~54async function getProduct(slug: string) {55 'use cache';56~57 cacheLife('hours');58 cacheTag(`product:${slug}`);59~60 return db.product.findUnique({ where: { slug } });61}62~63async function ProductDetails({ slug }: { slug: string }) {64 const product = await getProduct(slug);65~66 return (67 <section>68 <h1>{product.name}</h1>69 <p>{product.description}</p>70 </section>71 );72}73~74async function LiveInventory({ slug }: { slug: string }) {75 const inventory = await db.inventory.findFirst({ where: { slug } });76 return <p>{inventory.quantity} pezzi disponibili</p>;77}78~79export default async function ProductPage({ params }: { params: Promise<{ slug: string }> }) {80 const { slug } = await params;81~82 return (83 <>84 <ProductDetails slug={slug} />85 <Suspense fallback={<p>Controllo disponibilità...</p>}>86 <LiveInventory slug={slug} />87 </Suspense>88 </>89 );90}91```92~93Stránka nemusí být celá uložena v mezipaměti nebo musí být dynamická. Produktový list může být rychlý a opakovaně použitelný. Zásoby mohou zůstat čerstvé. Uživatel něco vidí hned, aniž by čekal na nejpomalejší část.94~95## `use cache` je spustitelná dokumentace96~97Na `"use cache"` se mi líbí to, že vás nutí vyjádřit záměr. Když čtete funkci, okamžitě pochopíte, že se někdo rozhodl: „tato data lze znovu použít“.98~99Je to zvláště užitečné, když nepoužíváte `fetch`. Mnoho aplikací čte data z Prisma, Drizzle, interních SDK, CMS klientů nebo servisních funkcí. V těchto případech staré úvahy založené pouze na možnostech `fetch` nestačily.100~101Základní pravidlo:102~103- obsah cachea relativně stabilní;104- používat granulované značky;105- opustí dynamická oprávnění, relace, košíky, oznámení a transakční stavy;106- vložte pomalé části dovnitř `Suspense`;107- změřte, než řeknete „zlepšili jsme výkon“.108~109## Zneplatnit, aniž byste všechno zahodili110~111Mezipaměť je užitečná pouze tehdy, pokud ji dokážete přesně aktualizovat. Zde se stávají důležitými `cacheTag`, `revalidateTag` a `updateTag`.112~113Příklad:114~115```typescript116'use server';117~118import { updateTag } from 'next/cache';119~120export async function updateProductName(productId: string, name: string) {121 await db.product.update({122 where: { id: productId },123 data: { name },124 });125~126 updateTag(`product:${productId}`);127}128```129~130Důležitým detailem je štítek. `product:${productId}` uvádí přesnou hranici. `products` říká obrovské vědro. Zpočátku je obrovský kbelík pohodlný; po několika měsících se to stane důvodem, proč zrušíte platnost poloviny aplikace, abyste změnili název.131~132## Stabilní Turbopack: součást, kterou slyšíte každý den133~134Next.js 16 přináší Turbopack do centra pro vývoj a sestavení. Není to nejpoetičtější funkce, ale je to ta, kterou cítíte při práci: server, který se spouští dříve, rychleji se obnovuje, sestavy, které vám přestanou připadat jako nucená přestávka na kávu.135~136To znamená, že bych nemigroval kódovou základnu plnou vlastních pluginů se zavřenýma očima. Zkontroloval bych:137~138- místní stavba;139- nestandardní dovoz;140- MDX, SVG a CSS;141- Webpack pluginy vlevo;142- kritické stránky;143- rozdíly v dobách výstavby.144~145U nových projektů bych začal od výchozího nastavení. U zralých bych udělal měřenou migraci.146~147## React Compiler: odstraňte šum, ne myšlenku148~149React Compiler 1.0 je stabilní a Next.js 16 jej podporuje s `reactCompiler`. Slibem je snížit množství ručního zapamatování: méně `memo`, méně `useMemo`, méně `useCallback` používané „pro bezpečnost“.150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162Nechoval bych to jako kouzelný prach. Kompilátor pomáhá, když kód dobře dodržuje pravidla React. Pokud mají komponenty podivné vedlejší účinky, skryté mutace nebo špatně použité háčky, je třeba to nejprve opravit.163~164Zdravý způsob, jak to vyzkoušet:165~1661. aktualizovat `eslint-plugin-react-hooks`;1672. opravit skutečná porušení;1683. povolit jej v kontrolované oblasti;1694. měřit dobu výstavby a chování;1705. ruční ukládání do paměti odstraňte pouze tehdy, když již není potřeba.171~172Cílem není vymazat každých `useMemo`. Cílem je přestat psát preventivní zapamatování, protože se bojíme vykreslování.173~174## `proxy.ts` a hranici sítě175~176Ze starého `middleware.ts` se stane `proxy.ts`. Jde o změnu názvu, ale dává to smysl: tento soubor leží na hranici požadavku, není to tradiční generický middleware typu backend.177~178```typescript179// proxy.ts180import { NextRequest, NextResponse } from 'next/server';181~182export default function proxy(request: NextRequest) {183 const isLoggedIn = Boolean(request.cookies.get('session'));184~185 if (!isLoggedIn && request.nextUrl.pathname.startsWith('/dashboard')) {186 return NextResponse.redirect(new URL('/login', request.url));187 }188~189 return NextResponse.next();190}191```192~193Pravidlo je zde jednoduché: držte to malé. Přesměrování, auth routing, hlavičky, zásadní přepisy. Pokud vám to začne připadat jako druhý backend, pravděpodobně toho dělá příliš mnoho.194~195## Jak bych opravdu migroval196~197Nezapínal bych všechny funkce najednou. udělal bych toto:198~1991. Aktualizuji Next, React a React DOM;2002. Spouštím oficiální codemod;2013. Opravuji zásadní změny na `params`, `searchParams`, `cookies()`, `headers()` a `draftMode()`;2024. Migruji `middleware.ts` na `proxy.ts`;2035. Kontroluji sestavení a kritické stránky;2046. Povoluji komponenty mezipaměti v sekci, kde mezipaměť aktuálně vytváří tření;2057. Definuji konvence pro značky a zneplatnění;2068. Zkouším React Compiler samostatně;2079. srovnání metrik před a po.208~209Dobrá migrace není ta, která využívá všechny nové funkce. Díky tomu je chování aplikace čitelnější.210~211## Co se mění ve způsobu myšlení212~213Na Next.js 16 je nejužitečnější to, že vás nutí lépe pojmenovávat záměry. Funkce není jen „získat produkt z databáze“. Je to "získat produkt, můžu ho hodiny uložit do mezipaměti, tímto tagem ho znehodnotím". Komponenta není jen „vykreslení stránky“. Je to "toto je rychlá skořápka, tento kousek je osobní, tohle se vysílá."214~215Zpočátku to vypadá jako více práce. Pak se to stane formou klidu. Rozhodnutí o výkonu již nejsou skryta v kombinaci výchozích hodnot, heuristiky a kmenové paměti. Jsou v kódu.216~217## Užitečné zdroje218~219- [Poznámky k vydání Next.js 16](https://nextjs.org/blog/next-16)220- [Komponenty mezipaměti – dokumenty Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [použít mezipaměť – dokumenty Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [React Compiler v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223~
NORMAL · nextjs-16-cache-components.md [readonly]223 lines · :q to close