spinny:~/writing $ less nextjs-16-cache-components.md
12De ani de zile, una dintre cele mai enervante întrebări din Next.js a fost: „Este această pagină statică sau dinamică?”. Pare o întrebare simplă, până când adăugați un apel la `cookies()`, un `fetch` cu diferite opțiuni, un client de bază de date, un CMS, un coș de cumpărături sau o bucată de conținut personalizat.34Next.js 16 este interesant, deoarece încearcă să facă această conversație mai puțin misterioasă. Nu elimină complexitatea, dar schimbă modelul mental: rutele sunt dinamice implicit, cache-ul se declară acolo unde este nevoie, iar `Suspense` devine modalitatea naturală de a compune shell-uri rapide cu părți care rămân proaspete.56Caracteristica de înțeles este Componentele cache. Stable Turbopack, React Compiler, `proxy.ts` și noile API-uri de invalidare sunt importante, dar se învârte în jurul aceleiași probleme: construirea de aplicații rapide fără a fi nevoie să ghicească ce a decis cadrul în culise.78## Pentru că chestia asta contează910Într-o aplicație reală nu aveți doar „pagini statice” și „pagini dinamice”. Aveți piese diferite cu nevoi diferite.1112Fișa produsului se poate schimba de câteva ori pe zi. Prețul se poate schimba mai des. Disponibilitatea trebuie să fie aproape live. Numele de utilizator este personal. Recenziile pot fi transmise în flux. Bara laterală poate fi stabilă. Căruciorul nu.1314Dacă tratezi totul ca o singură unitate, ajungi întotdeauna în una dintre cele două extreme:1516- stocarea în cache agresivă și riscul de a vedea date vechi;17- randare dinamică peste tot și performanță mai slabă decât este necesar.1819Cache Components servește tocmai pentru a evita această alegere falsă.2021## Modelul în practică2223Cu `cacheComponents: true`, puteți declara ceea ce poate fi stocat în cache folosind `"use cache"`. Apoi puteți asocia durata și etichetele cu `cacheLife()` și `cacheTag()`. Părțile dinamice rămân dinamice și pot fi izolate cu `Suspense`.2425```mermaid26flowchart TD27 Request[Solicitarea utilizatorului] --> Shell[Shell în cache]28 Request --> Dynamic[Secțiuni dinamice]29 Shell --> FirstPaint[Primul conținut rapid]30 Dynamic --> Stream[Streaming în interiorul Suspans]31 Stream --> Complete[Pagina intreaga]32```3334Configurația este mică:3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647Marea schimbare nu este în configurație. Este în modul în care începi să scrii componentele.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```9293Pagina nu trebuie să fie în totalitate în cache sau dinamică. Fișa produsului poate fi rapidă și reutilizabilă. Inventarul poate rămâne proaspăt. Utilizatorul vede ceva imediat, fără să aștepte partea cea mai lentă.9495## `use cache` este o documentație executabilă9697Lucrul care îmi place la `"use cache"` este că te obligă să explici o intenție. Când citești o funcție, înțelegi imediat că cineva a decis: „aceste date pot fi refolosite”.9899Este util mai ales când nu utilizați `fetch`. Multe aplicații citesc date de la Prisma, Drizzle, SDK-uri interne, clienți CMS sau funcții de serviciu. În acele cazuri, vechiul raționament bazat doar pe opțiunile `fetch` nu a fost suficient.100101O regulă generală:102103- conținutul cacheei relativ stabil;104- utilizați etichete granulare;105- lasă permisiuni dinamice, sesiuni, cărucioare, notificări și stări tranzacționale;106- pune piese lente în interiorul `Suspense`;107- măsurați înainte de a spune „am îmbunătățit performanța”.108109## Invalidați fără a arunca totul110111Cache-ul este util doar dacă îl puteți actualiza cu precizie. Aici `cacheTag`, `revalidateTag` și `updateTag` devin importante.112113Exemplu: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```129130Detaliul important este eticheta. `product:${productId}` indică o limită precisă. `products` spune unei găleți uriașe. La început găleata uriașă este confortabilă; după câteva luni devine motivul pentru care invalidezi o jumătate de aplicație pentru a schimba un titlu.131132## Turbopack stabil: partea pe care o auzi în fiecare zi133134Next.js 16 aduce Turbopack în centrul dezvoltării și construirii. Nu este cea mai poetică caracteristică, dar este cea pe care o simți în timp ce lucrezi: server care pornește mai devreme, reîmprospătare mai rapidă, build-uri care nu se mai simt ca o pauză de cafea forțată.135136Acestea fiind spuse, nu aș migra o bază de cod plină de pluginuri personalizate cu ochii închiși. as verifica:137138- construcție locală;139- module non-standard;140- MDX, SVG și CSS;141- Pluginuri Webpack rămase;142- pagini critice;143- diferențe de timp de construcție.144145Pentru proiecte noi, aș începe de la implicit. Pentru cei maturi aș face o migrație măsurată.146147## React Compiler: eliminați zgomotul, nu gândirea148149React Compiler 1.0 este stabil și Next.js 16 îl acceptă cu `reactCompiler`. Promisiunea este reducerea multă memorare manuală: mai puțin `memo`, mai puțin `useMemo`, mai puțin `useCallback` folosit „pentru siguranță”.150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Nu l-aș trata ca pe un praf magic. Compilatorul ajută atunci când codul respectă bine regulile React. Dacă componentele au efecte secundare ciudate, mutații ascunse sau cârlige prost folosite, trebuie remediat mai întâi.163164Modul sănătos de a-l încerca:1651661. actualizare `eslint-plugin-react-hooks`;1672. remediați încălcările reale;1683. activați-l pe o zonă controlată;1694. măsurați timpul de construcție și comportamentul;1705. eliminați memorarea manuală numai atunci când nu mai este necesară.171172Scopul este să nu ștergeți fiecare `useMemo`. Scopul este să nu mai scriem memorări preventive pentru că ne este frică de redare.173174## `proxy.ts` și limita rețelei175176Vechiul `middleware.ts` devine `proxy.ts`. Este o schimbare de nume, dar are sens: acel fișier se află la limita cererii, nu este un middleware generic tradițional în stil backend.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```192193Regula aici este simplă: păstrați-l mic. Redirecționare, rutare autentificare, anteturi, rescrieri esențiale. Dacă începe să pară un al doilea backend, probabil că face prea mult.194195## Cum aș migra cu adevărat196197Nu aș activa toate funcțiile deodată. as face asta:1981991. Actualizez Next, React și React DOM;2002. Lansez codul oficial;2013. Repar modificările de ruptură pe `params`, `searchParams`, `cookies()`, `headers()` și `draftMode()`;2024. Migrez `middleware.ts` la `proxy.ts`;2035. Verific versiunile și paginile critice;2046. Activez Componentele cache într-o secțiune în care memoria cache creează în prezent frecare;2057. Definesc convenții pentru etichete și invalidare;2068. Încerc React Compiler separat;2079. compararea valorilor înainte și după.208209Migrarea bună nu este cea care folosește toate funcțiile noi. Este ceea ce face comportamentul aplicației mai lizibil.210211## Ce se schimbă în modul de gândire212213Cel mai util lucru despre Next.js 16 este că te obligă să numești mai bine intențiile. O funcție nu este doar „obține produsul din baza de date”. Este „primiți produsul, îl pot păstra în cache ore în șir, îl invalidez cu această etichetă”. O componentă nu este doar „redarea paginii”. Este „aceasta este carcasa rapidă, această piesă este personală, aceasta vine în streaming”.214215La început pare mai multă muncă. Apoi devine o formă de calm. Deciziile de performanță nu mai sunt ascunse într-o combinație de valori implicite, euristică și memorie tribală. Sunt în cod.216217## Surse utile218219- [Note de lansare Next.js 16](https://nextjs.org/blog/next-16)220- [Componente cache - documente Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [utilizați memoria cache - documente 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
:Next.js 16, Cache Components și React Compiler: ce se schimbă cu adevăratlines 1-223 (END) — press q to close