spinny:~/writing $ vim nextjs-16-cache-components.md
1~2Pendant 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é.3~4Next.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.5~6La 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.7~8## Parce que cette chose compte9~10Dans 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.11~12La 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.13~14Si vous traitez tout comme une seule unité, vous vous retrouvez toujours dans l’un des deux extrêmes suivants :15~16- mise en cache agressive et risque de voir d'anciennes données ;17- rendu dynamique partout et performances moins bonnes que nécessaire.18~19Cache Components sert précisément à éviter ce faux choix.20~21## Le modèle en pratique22~23Avec `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`.24~25```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```33~34La configuration est petite :35~36```typescript37// next.config.ts38import type { NextConfig } from 'next';39~40const nextConfig: NextConfig = {41 cacheComponents: true,42};43~44export default nextConfig;45```46~47Le gros changement n'est pas dans la config. C'est dans la façon dont vous commencez à écrire les composants.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~93Il 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.94~95## `use cache` est une documentation exécutable96~97Ce 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".98~99C'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.100~101Une règle générale :102~103- 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 ».108~109## Invalider sans tout jeter110~111Le cache n'est utile que si vous pouvez le mettre à jour avec précision. Ici, `cacheTag`, `revalidateTag` et `updateTag` deviennent importants.112~113Exemple :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~130Le 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.131~132## Stable Turbopack : la partie que vous entendez tous les jours133~134Next.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.135~136Cela dit, je ne migrerais pas une base de code pleine de plugins personnalisés les yeux fermés. Je vérifierais :137~138- 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.144~145Pour les nouveaux projets, je partirais de la valeur par défaut. Pour les plus matures, je ferais une migration mesurée.146~147## React Compiler : supprime le bruit, pas pensé148~149React 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é ».150~151```typescript152// next.config.ts153import type { NextConfig } from 'next';154~155const nextConfig: NextConfig = {156 reactCompiler: true,157};158~159export default nextConfig;160```161~162Je 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é.163~164La façon saine de l’essayer :165~1661. 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.171~172Le 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.173~174## `proxy.ts` et la limite du réseau175~176L'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.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~193La 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.194~195## Comment je migrerais vraiment196~197Je n'activerais pas toutes les fonctionnalités en même temps. Je ferais ceci :198~1991. 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.208~209La 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.210~211## Ce qui change dans la façon de penser212~213La 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".214~215Au 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.216~217## Sources utiles218~219- [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~
NORMAL · nextjs-16-cache-components.md [readonly]223 lines · :q to close