spinny:~/writing $ less nextjs-16-cache-components.md
12Pendant des années, l'une des questions les plus ennuyeuses de Next.js a été : « Cette page est-elle statique ou dynamique ? Cela semble être une question simple, jusqu'à ce que vous ajoutiez un appel à `cookies()`, un `fetch` avec différentes options, un client de base de données, un CMS, un panier ou un élément de contenu personnalisé.34Next.js 16 est intéressant car il tente de rendre cette conversation moins mystérieuse. Cela n'élimine pas la complexité, mais cela modifie le modèle mental : les routes sont dynamiques par défaut, le cache se déclare là où c'est nécessaire et `Suspense` devient le moyen naturel de composer des shells rapides avec des parties qui restent fraîches.56La fonctionnalité à comprendre est les composants de cache. Stable Turbopack, React Compiler, `proxy.ts` et les nouvelles API d'invalidation sont importants, mais ils tournent autour du même problème : créer des applications rapides sans avoir à deviner ce que le framework a décidé en coulisses.78## Parce que cette chose compte910Dans une vraie application, vous n'avez pas seulement des « pages statiques » et des « pages dynamiques ». Vous avez différentes pièces avec des besoins différents.1112La fiche produit peut changer plusieurs fois par jour. Le prix peut changer plus souvent. La disponibilité doit être quasiment réelle. Le nom d'utilisateur est personnel. Les avis peuvent être diffusés en streaming. La barre latérale peut être stable. Ce n’est pas le cas du chariot.1314Si vous traitez tout comme une seule unité, vous vous retrouvez toujours dans l’un des deux extrêmes suivants :1516- mise en cache agressive et risque de voir d'anciennes données ;17- rendu dynamique partout et performances moins bonnes que nécessaire.1819Cache Components sert précisément à éviter ce faux choix.2021## Le modèle en pratique2223Avec `cacheComponents: true`, vous pouvez déclarer ce qui peut être mis en cache en utilisant `"use cache"`. Ensuite, vous pouvez associer la durée et les balises à `cacheLife()` et `cacheTag()`. Les pièces dynamiques restent dynamiques et peuvent être isolées avec `Suspense`.2425```mermaid26flowchart TD27 Request[Demande de l'utilisateur] --> Shell[Coquille mise en cache]28 Request --> Dynamic[Sections dynamiques]29 Shell --> FirstPaint[Premier contenu rapide]30 Dynamic --> Stream[Streaming dans le suspense]31 Stream --> Complete[Pleine page]32```3334La configuration est petite :3536```typescript37// next.config.ts38import type { NextConfig } from 'next';3940const nextConfig: NextConfig = {41 cacheComponents: true,42};4344export default nextConfig;45```4647Le gros changement n'est pas dans la config. C'est dans la façon dont vous commencez à écrire les composants.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```9293Il n'est pas nécessaire que la page soit entièrement mise en cache ou entièrement dynamique. La fiche produit peut être rapide et réutilisable. L’inventaire peut rester frais. L'utilisateur voit quelque chose immédiatement, sans attendre la partie la plus lente.9495## `use cache` est une documentation exécutable9697Ce que j'aime dans `"use cache"`, c'est que cela vous oblige à exprimer une intention explicite. Quand on lit une fonction, on comprend tout de suite que quelqu'un a décidé : "ces données peuvent être réutilisées".9899C'est particulièrement utile lorsque vous n'utilisez pas `fetch`. De nombreuses applications lisent les données de Prisma, Drizzle, des SDK internes, des clients CMS ou des fonctions de service. Dans ces cas, l'ancien raisonnement basé uniquement sur les options `fetch` n'était pas suffisant.100101Une règle générale :102103- contenu du cache relativement stable ;104- utilisez des balises granulaires ;105- laisse les autorisations dynamiques, les sessions, les paniers, les notifications et les états transactionnels ;106- placez les parties lentes à l'intérieur de `Suspense` ;107- mesurer avant de dire « nous avons amélioré les performances ».108109## Invalider sans tout jeter110111Le cache n'est utile que si vous pouvez le mettre à jour avec précision. Ici, `cacheTag`, `revalidateTag` et `updateTag` deviennent importants.112113Exemple :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```129130Le détail important est l'étiquette. `product:${productId}` indique une limite précise. `products` indique un énorme seau. Au début, l’énorme seau est confortable ; après quelques mois, cela devient la raison pour laquelle vous invalidez la moitié d'une application pour changer un titre.131132## Stable Turbopack : la partie que vous entendez tous les jours133134Next.js 16 place Turbopack au centre du développement et de la construction. Ce n'est pas la fonctionnalité la plus poétique, mais c'est celle que l'on ressent pendant que l'on travaille : un serveur qui démarre plus tôt, un rafraîchissement plus rapide, des builds qui ne ressemblent plus à une pause café forcée.135136Cela dit, je ne migrerais pas une base de code pleine de plugins personnalisés les yeux fermés. Je vérifierais :137138- construction locale ;139- importation non standard ;140- MDX, SVG et CSS ;141- Plugins Webpack restants ;142- pages critiques ;143- différences dans les temps de construction.144145Pour les nouveaux projets, je partirais de la valeur par défaut. Pour les plus matures, je ferais une migration mesurée.146147## React Compiler : supprime le bruit, pas pensé148149React Compiler 1.0 est stable et Next.js 16 le prend en charge avec `reactCompiler`. La promesse est de réduire beaucoup de mémorisation manuelle : moins de `memo`, moins de `useMemo`, moins de `useCallback` utilisé « par sécurité ».150151```typescript152// next.config.ts153import type { NextConfig } from 'next';154155const nextConfig: NextConfig = {156 reactCompiler: true,157};158159export default nextConfig;160```161162Je ne le traiterais pas comme une poussière magique. Le compilateur est utile lorsque le code suit bien les règles de React. Si les composants ont des effets secondaires étranges, des mutations cachées ou des hooks mal utilisés, cela doit d’abord être corrigé.163164La façon saine de l’essayer :1651661. mettre à jour `eslint-plugin-react-hooks` ;1672. corriger les violations réelles ;1683. l'activer sur une zone contrôlée ;1694. mesurer le temps de construction et le comportement ;1705. supprimez la mémorisation manuelle uniquement lorsqu'elle n'est plus nécessaire.171172Le but n’est pas d’effacer tous les `useMemo`. Le but est d’arrêter d’écrire de la mémorisation préventive car on a peur du rendu.173174## `proxy.ts` et la limite du réseau175176L'ancien `middleware.ts` devient `proxy.ts`. C'est un changement de nom, mais cela a du sens : ce fichier se situe à la limite de la requête, ce n'est pas un middleware générique de style backend traditionnel.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```192193La règle ici est simple : restez petit. Redirection, routage d'authentification, en-têtes, réécritures essentielles. Si cela commence à ressembler à un deuxième backend, il en fait probablement trop.194195## Comment je migrerais vraiment196197Je n'activerais pas toutes les fonctionnalités en même temps. Je ferais ceci :1981991. Je mets à jour Next, React et React DOM ;2002. Je lance le codemod officiel ;2013. Je corrige les modifications avec rupture sur `params`, `searchParams`, `cookies()`, `headers()` et `draftMode()` ;2024. Je migre `middleware.ts` vers `proxy.ts` ;2035. Je vérifie les builds et les pages critiques ;2046. J'active les composants de cache sur une section où le cache crée actuellement des frictions ;2057. Je définis des conventions pour les balises et l'invalidation ;2068. J'essaie React Compiler séparément ;2079. comparaison des métriques avant et après.208209La bonne migration n’est pas celle qui utilise toutes les nouvelles fonctionnalités. C'est ce qui rend le comportement de l'application plus lisible.210211## Ce qui change dans la façon de penser212213La chose la plus utile à propos de Next.js 16 est qu'il vous oblige à mieux nommer les intentions. Une fonction ne consiste pas simplement à "récupérer le produit de la base de données". C'est "récupérer le produit, je peux le mettre en cache pendant des heures, je l'invalide avec cette balise". Un composant ne consiste pas simplement à "rendre la page". C'est "c'est le shell rapide, cette pièce est personnelle, elle vient en streaming".214215Au début, cela semble être plus de travail. Cela devient alors une forme de calme. Les décisions en matière de performance ne sont plus cachées dans une combinaison de valeurs par défaut, d'heuristiques et de mémoire tribale. Ils sont dans le code.216217## Sources utiles218219- [Notes de version de Next.js 16](https://nextjs.org/blog/next-16)220- [Composants de cache - Documents Next.js](https://nextjs.org/docs/app/getting-started/cache-components)221- [utiliser le cache - Documents Next.js](https://nextjs.org/docs/app/api-reference/directives/use-cache)222- [React Compilateur v1.0](https://react.dev/blog/2025/10/07/react-compiler-1)223
:Next.js 16, Cache Components et React Compiler : ce qui change vraimentlines 1-223 (END) — press q to close