Préparation d'entretien 100% Gratuit angularforall.com

Entretien Next.js Senior : performance et architecture

Next-Js Senior Quiz-Nextjs-Senior Performance-Nextjs Edge-Runtime Streaming-Ssr Caching Turbo-Monorepo Image-Optimization Questions-Entretien-Nextjs-Senior Qcm-Nextjs-Avance React-Server-Components Architecture-Nextjs Front-End
Sénior 🔀 Mixte 20 questions ⏱ 15 min
📝

Entretien Next.js Senior : performance et architecture

20 questions avancées Next.js : optimisation des performances, edge runtime, streaming SSR, caching, monorepo Turbo, image optimization et architectures avancées.

20 questions ⏱ ~15 min Niveau Sénior

Partager

Banque de révision : les 30 questions corrigées

Voici l'intégralité des 30 questions de « Entretien Next.js Senior : performance et architecture », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.

  • Request Memoization (dédoublonne les fetch), Data Cache (persiste entre requêtes), Full Route Cache (HTML/RSC statiques), Router Cache (cache client) (bonne réponse)
  • Cache navigateur uniquement
  • Un cache mémoire simple sans couches
  • Deux couches : serveur et client
Explication : Les 4 couches : 1) Request Memoization (React, durée d'une requête, dédoublonne les fetch identiques), 2) Data Cache (Next.js, persiste entre requêtes, invalidé par revalidateTag/revalidatePath), 3) Full Route Cache (HTML et RSC payload statiques sur le serveur), 4) Router Cache (cache in-memory côté client, durée de session ou 30s pour pages dynamiques).
Pour debugger le cache : activez les logs avec logging: { fetches: { fullUrl: true } } dans next.config.js.

  • Une fonctionnalité expérimentale qui combine SSG et streaming : un shell statique instantané avec des trous dynamiques (bonne réponse)
  • Un type de rendu uniquement côté client
  • Une technique de minification du HTML
  • Un mode de développement uniquement
Explication : Le PPR (expérimental, activable avec experimental: { ppr: true }) permet de pré-rendre une coquille statique au build tout en laissant des "trous" pour le contenu dynamique qui sera streamé. Combine le meilleur du statique (instantané) et du dynamique (données fraîches).
Dans PPR, tout ce qui est hors Suspense devient statique. Placez le contenu dynamique dans des <Suspense> pour créer les "trous" dynamiques.

  • Un bundler incrémental en Rust, successeur de Webpack ; disponible uniquement en dev actuellement (bonne réponse)
  • Un remplacement complet de Webpack pour la production
  • Un outil de test de performance
  • Un compilateur TypeScript uniquement
Explication : Turbopack est le nouveau bundler écrit en Rust par l'équipe Next.js (dirigée par le créateur de Webpack). Il offre des temps de compilation 5 à 10 fois plus rapides grâce à la compilation incrémentale et au cache. Limitation actuelle : disponible uniquement en développement (next dev --turbo).
Activez Turbopack dans next.config.js avec experimental: { turbo: {} } ou via next dev --turbo. Webpack reste utilisé pour le build production.

  • Tagger les fetch avec next: { tags: [...] }, puis appeler revalidateTag() dans une Server Action ou Route Handler (bonne réponse)
  • Utiliser un cron job externe
  • Redémarrer le serveur
  • La révalidation on-demand n'existe pas
Explication : On tague les fetch : fetch(url, { next: { tags: ["posts"] } }). Pour révalider, on appelle revalidateTag("posts") dans une Server Action ou Route Handler. Tous les composants utilisant ce fetch seront mis à jour.
Combinez avec un webhook (ex: CMS headless) qui appelle votre endpoint de révalidation avec un token secret pour la sécurité.

  • Les Server Actions sont sérialisées en références, envoyées via des requêtes POST fetch, exécutées sur le serveur avec les FormData (bonne réponse)
  • Elles sont directement exécutées dans le navigateur
  • Elles utilisent WebSockets pour la communication
  • Elles sont compilées en WebAssembly
Explication : Une Server Action est sérialisée côté serveur en une référence unique. Quand elle est appelée depuis un Client Component (via form action ou appel direct), Next.js envoie une requête POST avec les arguments sérialisés. Le serveur reconstitue le contexte, exécute la fonction, et retourne le résultat.
Les Server Actions créent automatiquement un endpoint POST. Pour les appels directs (pas via formulaire), utilisez startTransition pour une meilleure UX.

  • Un format binaire sérialisé représentant l'arbre React rendu côté serveur, envoyé via un stream HTTP (bonne réponse)
  • Du JSON classique comme les API REST
  • Du HTML uniquement
  • Du JavaScript interprété côté client
Explication : Le RSC Payload est une représentation sérialisée spéciale (pas du JSON ni du HTML pur) de l'arbre de composants React rendu côté serveur. Il contient les éléments React, les props, et les références aux Client Components. Il est streamé au client qui le reconstitue en UI.
Ce format n'est pas destiné à être lu directement. React côté client l'interprète pour hydrater l'interface. C'est ce qui permet de ne pas envoyer le code JavaScript des Server Components.

  • Streaming envoie le HTML par morceaux ; prioriser le contenu above-the-fold hors Suspense pour un bon TTFB/LCP (bonne réponse)
  • Le streaming envoie tout d'un coup à la fin
  • Le TTFB n'est pas affecté par le streaming
  • Il faut désactiver le streaming pour un bon LCP
Explication : Le streaming SSR (renderToPipeableStream) envoie le HTML progressivement. Pour optimiser TTFB : réduire le travail serveur, utiliser le caching. Pour optimiser LCP : mettre le contenu principal (above-the-fold) hors Suspense pour qu'il soit envoyé en premier.
Structurez vos pages : contenu critique hors Suspense envoyé immédiatement, contenu secondaire (commentaires, sidebar) dans des Suspense streamés après.

  • Exécution sur les nœuds CDN (proche utilisateur) ; APIs Web standard uniquement (fetch, Request, Response) ; pas de fs, net, ou modules natifs Node.js (bonne réponse)
  • Un Node.js complet sur CDN
  • Uniquement des fonctions mathématiques
  • Toutes les APIs Node.js sont disponibles
Explication : L'Edge Runtime exécute le code sur les serveurs edge de Vercel/Cloudflare, géographiquement proches de l'utilisateur. Limitations : pas de fs, net, child_process, modules natifs. Supporte les APIs Web standard : fetch, Request, Response, crypto, URL.
Activez avec export const runtime = "edge". Idéal pour Middleware, vérifications de tokens, A/B testing, redirections géolocalisées.

  • Un Server Component parent fetch les données et les distribue à des Server/Client Components enfants via props (bonne réponse)
  • Tous les composants sont des Client Components
  • Un seul composant monolithique par page
  • Utiliser Redux pour toutes les données
Explication : Le pattern consiste à avoir un Server Component "page" qui orchestre le fetching de données (souvent via Promise.all pour la parallélisation) et passe les résultats en props à des composants enfants spécialisés (Server ou Client). Cela maximise le rendu serveur et minimise le JavaScript client.
Structure recommandée : Page (Server, data fetching) → Layout (Server, structure) → InteractiveWidget (Client, interactivité).

  • useOptimistic(state, updater) met à jour l'UI immédiatement pendant que la Server Action s'exécute ; rollback automatique si erreur (bonne réponse)
  • Désactiver le cache et attendre la réponse
  • Utiliser useEffect pour simuler
  • Les mutations optimistes ne sont pas possibles avec Server Actions
Explication : Le hook useOptimistic() (basé sur React 18) prend l'état initial et une fonction de mise à jour. On passe addOptimistic() dans l'action du formulaire. L'UI se met à jour immédiatement. Si la Server Action échoue, React rollback automatiquement.
Pattern complet : const [optimisticMessages, addOptimistic] = useOptimistic(messages, (state, newMsg) => [...state, newMsg]).

  • Un compilateur qui automatise useMemo/useCallback/React.memo en analysant le code, éliminant la mémoïsation manuelle (bonne réponse)
  • Un nouveau moteur de rendu
  • Un remplacement de Babel
  • Un outil de build plus rapide uniquement
Explication : React Forget (en développement chez Meta) est un compilateur qui analyse automatiquement le code pour déterminer ce qui doit être mémorisé. Objectif : éliminer le besoin d'utiliser manuellement useMemo, useCallback, React.memo. Next.js l'intégrera dès sa sortie stable.
Forget permettra aux développeurs de se concentrer sur la logique métier sans se soucier des optimisations de re-rendu. Impact majeur sur la DX (Developer Experience).

  • SWC (Rust) pour la transpilation, Turbopack (Rust) pour le bundling ; performances 5-10x supérieures à Babel + Webpack (bonne réponse)
  • Babel pour transpiler, Webpack pour bundler
  • Uniquement SWC pour tout
  • Compilation via esbuild exclusivement
Explication : Next.js utilise SWC (Speedy Web Compiler, écrit en Rust) pour la transpilation TypeScript/JSX (remplace Babel) et Turbopack (Rust) pour le bundling en développement (remplace Webpack). Les deux sont écrits en Rust pour des performances nettement supérieures.
SWC est utilisé par défaut. Turbopack s'active avec next dev --turbo. En production, Webpack (ou Turbopack quand il sera stable) est utilisé.

  • Le stale-while-revalidate sert le contenu en cache (stale) puis régénère en arrière-plan ; configurable avec revalidate en secondes (bonne réponse)
  • Une invalidation immédiate du cache
  • Un cache qui ne se met jamais à jour
  • Une stratégie de cache navigateur uniquement
Explication : L'ISR avec stale-while-revalidate : quand une requête arrive après la période de revalidate, Next.js sert d'abord la version en cache (stale, rapide), puis déclenche la régénération en arrière-plan. La prochaine requête verra la nouvelle version. Configurable via next: { revalidate: 60 } ou on-demand.
Pour des données critiques qui doivent être fraîches, utilisez cache: "no-store". Pour des données moins critiques, un revalidate plus long réduit la charge serveur.

  • Utiliser des variables d'environnement (.env.local, .env.production) et next.config.js avec des conditions basées sur NODE_ENV (bonne réponse)
  • Maintenir plusieurs branches de code
  • Déployer manuellement avec des scripts
  • Next.js ne supporte qu'un seul environnement
Explication : Next.js supporte les fichiers .env.local, .env.development, .env.production. Dans next.config.js, on peut conditionner la configuration : if (process.env.NODE_ENV === "production") { ... }. Vercel gère automatiquement les environnements de preview.
Utilisez NEXT_PUBLIC_VERCEL_ENV sur Vercel pour détecter l'environnement (development/preview/production).

  • Placer les composants, tests, et logique métier dans le même dossier que la route qui les utilise (bonne réponse)
  • Mettre tous les composants dans /components
  • Utiliser un monorepo obligatoirement
  • Séparer strictement les composants par type
Explication : La colocation consiste à placer les fichiers liés à une fonctionnalité dans le même dossier que la route (ex: app/dashboard/_components/, app/dashboard/_actions/). Les dossiers préfixés par _ ne sont pas routables. Cela améliore la maintenabilité et la clarté.
Organisation type : app/route/_components/ (UI), app/route/_actions/ (Server Actions), app/route/_lib/ (utilitaires), app/route/__tests__/ (tests).

  • Next.js intègre automatiquement une protection CSRF via des tokens dans les formulaires ; ajouter une vérification d'auth dans l'action (bonne réponse)
  • Les Server Actions sont sécurisées par défaut
  • Utiliser CORS uniquement
  • Désactiver les Server Actions en production
Explication : Next.js protège automatiquement contre CSRF en exigeant un token dans les requêtes POST des Server Actions. Il faut en plus vérifier l'authentification/autorisation dans chaque Server Action (if (!session) throw new Error("Unauthorized")).
Créez un wrapper authenticatedAction(action) qui vérifie les droits avant d'exécuter l'action métier.

  • Les Client Components sont hydratés indépendamment ; Suspense permet de différer l'hydratation des parties non critiques (bonne réponse)
  • Toute la page est hydratée d'un coup
  • L'hydratation est désactivée dans Next.js
  • Seuls les Server Components sont hydratés
Explication : Avec les Client Components, chaque composant est hydraté indépendamment. Dans un <Suspense>, l'hydratation est différée jusqu'à ce que le contenu soit prêt. Cela permet de prioriser l'hydratation des parties interactives critiques et de réduire le Time to Interactive (TTI).
Pour les composants lourds non critiques (commentaires, chatbots), enveloppez-les dans un Suspense pour ne pas bloquer l'hydratation du reste.

  • Git push → build sur Vercel → déploiement ; ISR on-demand via API de révalidation appelée par le CMS ou un webhook (bonne réponse)
  • FTP manuel du dossier /dist
  • Déploiement via Docker uniquement
  • Pas de CI/CD possible avec Next.js
Explication : Vercel propose un pipeline CI/CD intégré : chaque push Git déclenche un build et déploiement (avec preview deployment pour les PRs). Pour l'ISR on-demand, on expose un endpoint dans app/api/revalidate/route.js qui appelle revalidateTag(), et le CMS/webhook l'appelle après chaque mise à jour de contenu.
Sécurisez l'endpoint de révalidation avec un token secret passé en query param ou header.

  • Connexion directe depuis les Server Components ou Server Actions ; utiliser un ORM comme Prisma/Drizzle avec un singleton de connexion (bonne réponse)
  • Uniquement via des API routes externes
  • Next.js ne supporte pas les bases de données
  • Utiliser REST forcément
Explication : Les Server Components et Server Actions peuvent se connecter directement aux BDD. Meilleures pratiques : utiliser un ORM (Prisma, Drizzle), créer un singleton pour la connexion (éviter les connexions multiples en dev avec HMR), utiliser les DataBase as a Service (Vercel Postgres, Neon, PlanetScale) pour le serverless.
En développement, Next.js peut créer plusieurs instances. Utilisez le pattern singleton : globalThis.prisma ??= new PrismaClient().

  • Middleware sur Edge Runtime qui lit les cookies/en-têtes et réécrit la route vers différentes variantes (bonne réponse)
  • Uniquement avec des if/else dans les composants
  • Avec une base de données externe obligatoirement
  • Le A/B testing n'est pas possible avec Next.js
Explication : Le Middleware sur Edge Runtime est idéal : rapide, proche de l'utilisateur. Il peut lire un cookie de bucket, et réécrire /page vers /page-variant-a ou /page-variant-b de manière transparente pour l'utilisateur.
Stockez le bucket dans un cookie (via request.cookies.set()) pour assurer la persistance de la variante pendant la session.

  • Les fonctions comme cookies() ou headers() rendent automatiquement la route dynamique (SSR) au lieu de statique (bonne réponse)
  • Dynamic IO est un type de base de données
  • Ces fonctions n'affectent pas le rendu
  • Elles sont disponibles uniquement dans les Client Components
Explication : Les fonctions dynamiques (cookies(), headers(), searchParams) marquent automatiquement la route comme dynamique (SSR). Next.js ne peut pas pré-rendre une page qui dépend de données de requête. Le "Dynamic IO" (en cours de développement) permettra un contrôle plus fin.
Si vous utilisez ces fonctions, la page ne sera pas statique, même avec cache: "force-cache". Structurez votre application pour isoler ces dépendances.

  • Parallel Routes avec le dossier @nom pour des slots ; Intercepting Routes avec (.) pour intercepter la navigation (bonne réponse)
  • Des configurations dans next.config.js uniquement
  • Avec React Router uniquement
  • Ces fonctionnalités n'existent pas dans Next.js
Explication : Les Parallel Routes utilisent des "slots" nommés avec @ : app/@sidebar/page.js. Les Intercepting Routes utilisent (.) (même niveau), (..) (parent), (...) (racine) pour intercepter la navigation vers une route et l'afficher dans un modal par exemple.
Cas d'usage classique : galerie photo. Clic sur une photo → affichage dans un modal (intercepting), mais rafraîchissement → page dédiée.

  • Next.js fait du tree-shaking automatique ; utiliser dynamic() avec ssr:false, analyser avec @next/bundle-analyzer (bonne réponse)
  • Minimiser manuellement tous les fichiers
  • Supprimer node_modules
  • Le bundle ne peut pas être optimisé
Explication : Next.js élimine automatiquement le code mort (tree-shaking) lors du build. Optimisations supplémentaires : dynamic(() => import(...), { ssr: false }) pour les bibliothèques client-only, @next/bundle-analyzer pour visualiser les dépendances, et modulariser les imports (importer uniquement ce qui est utilisé).
Activez l'analyseur : ANALYZE=true npm run build. Surveillez les grosses dépendances et remplacez-les par des alternatives plus légères.

  • Middleware pour détecter la locale, dossier [lang] pour les routes, et next-intl ou un système de dictionnaires (bonne réponse)
  • next-i18next uniquement
  • Traduction manuelle de chaque page
  • Next.js ne supporte pas l'i18n dans l'App Router
Explication : L'App Router n'a pas de solution i18n intégrée (contrairement au Pages Router). L'approche recommandée : Middleware pour détecter/rediriger selon la locale, structure de routes app/[lang]/page.js, et bibliothèque comme next-intl qui supporte les Server Components.
next-intl est la solution la plus populaire pour l'App Router. Elle supporte les Server Components, les messages async, et la négociation de locale.

  • La possibilité de composer l'UI à partir de composants indépendants déployables séparément (micro-frontends via Module Federation) (bonne réponse)
  • Un seul composant pour toute l'application
  • Utiliser uniquement des Server Components
  • La composabilité n'est pas un concept de Next.js
Explication : Next.js permet une architecture composable où différentes parties de l'application peuvent être développées, testées et déployées indépendamment. Via Turbopack/Webpack Module Federation, on peut même charger des micro-frontends distants.
Pour les grandes équipes, les monorepos (Turborepo) avec Next.js permettent de partager des composants entre applications tout en maintenant l'indépendance des déploiements.

  • Les plugins sont des fonctions qui reçoivent la config et retournent une config modifiée ; ex: next-pwa, next-mdx (bonne réponse)
  • Un système de plugins comme WordPress
  • Des modules npm quelconques
  • Next.js n'a pas de système de plugins
Explication : Les plugins Next.js suivent le pattern (nextConfig) => nextConfig. Ils modifient la configuration Webpack, ajoutent des fonctionnalités. Exemples : next-pwa (PWA), @next/mdx (MDX), next-sitemap. S'utilisent avec withPlugins() ou en chaînant.
Pattern standard : const withPWA = require("next-pwa"); module.exports = withPWA({ ...nextConfig }).

  • Protection contre les incohérences quand le JS client est d'une version différente des assets serveur pendant un déploiement (bonne réponse)
  • Une protection contre les attaques XSS
  • Un système de backup de version
  • Une technique d'optimisation CSS
Explication : Le Skew Protection évite les erreurs quand un utilisateur a chargé une ancienne version de la page (avec d'anciens liens vers des assets) mais que le serveur a été mis à jour entre-temps. Next.js gère cela en versionnant les assets et en maintenant les anciennes versions accessibles temporairement.
Sur Vercel, les anciens déploiements restent accessibles, garantissant que les utilisateurs sur d'anciennes sessions ne rencontrent pas d'erreurs 404 sur les assets.

  • Utiliser @vercel/otel (OpenTelemetry) pour le tracing distribué, Vercel Analytics pour les Web Vitals, et des logs structured JSON (bonne réponse)
  • Uniquement des console.log
  • Payer un service externe sans intégration
  • Next.js ne supporte pas le monitoring
Explication : Next.js supporte OpenTelemetry (@vercel/otel) pour le tracing distribué (traces, spans, métriques). Vercel Analytics offre les Web Vitals (LCP, CLS, INP). Pour les logs, utiliser des logs structurés (JSON) avec des niveaux (info, warn, error) et une plateforme de log management.
Activez OpenTelemetry : experimental: { instrumentationHook: true } puis instrumentation.ts à la racine.

  • Tests E2E avec Playwright, tests d'intégration serveur avec Vitest, tests de composants avec Testing Library + Jest (bonne réponse)
  • Uniquement des tests manuels
  • Pas de tests nécessaires pour Next.js
  • Un seul type de test suffit
Explication : Stratégie complète : Tests unitaires (Jest/Vitest pour les fonctions pures), Tests de composants (Testing Library + mocks pour les Server Components), Tests d'intégration (tester les Server Actions et API routes), Tests E2E (Playwright pour les parcours utilisateur complets).
Playwright est recommandé par Vercel. Utilisez @playwright/test avec le mode headless pour la CI/CD.

  • Détection automatique de la plateforme (Vercel, Netlify, Docker) et optimisation de la sortie (build output) en conséquence (bonne réponse)
  • Aucune configuration nécessaire, jamais
  • Un déploiement sans serveur du tout
  • Uniquement pour Vercel
Explication : Next.js détecte la plateforme de déploiement (Vercel, Netlify, Node.js, Docker) via les variables d'environnement et optimise automatiquement la sortie. Le output: "standalone" dans next.config.js crée un bundle autonome pour Docker. Next.js s'adapte au serverless, edge, ou serveur traditionnel.
Pour Docker : output: "standalone" dans next.config.js. Le dossier .next/standalone contiendra tout le nécessaire pour exécuter l'application.