Une règle simple, posée après dix projets Next 16 : par défaut, tout est server. Un composant ne devient client que quand il touche l'état du navigateur — clic, focus, scroll, animation pilotée.
Le filtre à appliquer
Avant de poser un 'use client' en haut d'un fichier, on se demande :
- Le composant a-t-il besoin de
useState,useEffect,useRef? - Lit-il la position du scroll, le
window, un événement DOM ? - Anime-t-il quelque chose qui dépend du scroll ou d'un input utilisateur ?
Si la réponse est non aux trois questions, ça reste serveur.
Pourquoi ça compte
Chaque composant marqué 'use client' ajoute du JavaScript dans le bundle.
Sur un site éditorial, c'est invisible — sur un site marketing avec 60+
sections, ça pèse. Sur Numelite v2, on est passés de 280 ko de JS hydraté
à 92 ko en disciplinant ce point.
Les zones où on triche
Trois exceptions où on accepte de "monter" un composant côté client :
- Les CTA principaux qui doivent réagir instantanément au hover.
- Les sliders / carrousels —
Carousel3Dest entièrement client. - Les éléments avec animation scroll-driven (
useScrollde motion/react).
Pour le reste, on découpe : un wrapper serveur qui passe les données, un îlot client qui gère seulement l'interaction.