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

Entretien Next.js Junior : data fetching et middleware

Next-Js Junior Quiz-Nextjs-Junior Data-Fetching Middleware Route-Handlers Server-Actions Isr Dynamic-Routes Questions-Entretien-Nextjs-Junior Qcm-Nextjs-Junior React Metadata Front-End
Junior 🔀 Mixte 20 questions ⏱ 15 min
📝

Entretien Next.js Junior : data fetching et middleware

20 questions Next.js niveau junior : data fetching, middleware, route handlers, server actions, ISR, dynamic routes et metadata pour réussir un entretien.

20 questions ⏱ ~15 min Niveau Junior

Partager

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

Voici l'intégralité des 30 questions de « Entretien Next.js Junior : data fetching et middleware », 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.

  • Le SSR génère le HTML à chaque requête ; la SSG génère le HTML au moment du build (bonne réponse)
  • Le SSR est plus rapide que la SSG
  • La SSG nécessite un serveur Node.js ; le SSR non
  • Il n'y a pas de différence technique
Explication : Le SSR (Server-Side Rendering) génère le HTML dynamiquement à chaque requête utilisateur. La SSG (Static Site Generation) génère le HTML une fois au build, et ce HTML statique est servi instantanément à tous les utilisateurs.
Utilisez la SSG pour les pages qui ne changent pas souvent (blog, documentation). Utilisez le SSR pour les pages avec des données utilisateur spécifiques (dashboard, profil).

  • fetch(url) sans option cache, ou fetch(url, { cache: "force-cache" }) (bonne réponse)
  • fetch(url, { cache: "no-store" })
  • fetch(url, { static: true })
  • Uniquement avec getStaticProps
Explication : Par défaut, fetch() dans un Server Component utilise le cache (cache: "force-cache"), ce qui rend la page statique (SSG). Pour du SSR (dynamique), il faut explicitement cache: "no-store".
Ajoutez next: { revalidate: 3600 } pour de l'ISR : la page sera régénérée toutes les heures.

  • Un mécanisme qui permet de mettre à jour des pages statiques après le build, sans reconstruction complète (bonne réponse)
  • Une technique pour incrémenter le numéro de version du site
  • Un système de cache pour les images uniquement
  • Un type de base de données intégré
Explication : L'ISR permet de régénérer des pages statiques périodiquement ou à la demande. On définit un intervalle de revalidation (revalidate) après lequel la page sera mise à jour en arrière-plan.
Deux types d'ISR : par intervalle de temps (next: { revalidate: 60 }) et on-demand avec revalidatePath() ou revalidateTag().

  • Exporter une fonction POST dans route.js qui lit await request.json() et retourne une Response (bonne réponse)
  • Utiliser app.post() dans le fichier server.js
  • Créer un fichier api.js avec req.body
  • Les routes API POST ne sont pas supportées
Explication : Dans route.js, on exporte export async function POST(request) { const body = await request.json(); ... return Response.json({ success: true }) }. L'API Web standard remplace req.body d'Express.
Pensez à gérer les erreurs avec try/catch et à retourner un statut approprié : return Response.json({ error: "..." }, { status: 400 }).

  • Une fonction asynchrone exécutée côté serveur, idéale pour les mutations de données (formulaires, création, mise à jour) (bonne réponse)
  • Un plugin pour les animations serveur
  • Une configuration du serveur de déploiement
  • Un type de composant React
Explication : Les Server Actions (marquées "use server") sont des fonctions exécutées côté serveur uniquement. Elles simplifient les mutations sans avoir à créer des API routes manuelles. Parfaites pour les formulaires.
Dans un formulaire : <form action={maServerAction}>. La fonction reçoit automatiquement les FormData du formulaire.

  • Un fichier middleware.js à la racine qui intercepte les requêtes avant qu'elles n'atteignent la page (bonne réponse)
  • Un plugin installé via npm
  • Un composant React spécial
  • Une configuration dans next.config.js uniquement
Explication : Le fichier middleware.js (ou .ts) à la racine du projet permet d'intercepter toutes les requêtes entrantes. On peut rediriger, réécrire les URLs, vérifier l'authentification, ajouter des en-têtes.
Le Middleware s'exécute sur l'Edge Runtime par défaut. Utilisez config.matcher pour limiter les routes concernées.

  • Elle marque un composant comme Client Component pour y utiliser des hooks, des événements ou des API navigateur (bonne réponse)
  • Elle indique que le composant est destiné aux utilisateurs
  • Elle active le mode client pour toute l'application
  • Elle est obligatoire dans tous les fichiers
Explication : "use client" transforme un composant en Client Component. À utiliser quand le composant a besoin d'interactivité (useState, onClick), d'API navigateur (localStorage, window), ou de hooks React.
Placez la directive le plus bas possible dans l'arbre des composants. Gardez la structure et les données côté serveur, isolez l'interactivité.

  • useParams() de next/navigation (bonne réponse)
  • useRouter().params
  • useRoute()
  • props.params
Explication : Dans un Client Component, on utilise useParams() importé de next/navigation. Dans un Server Component, les params sont directement passés en props.
Exemple Client : const params = useParams(); const slug = params.slug;.

  • Exporter une fonction generateMetadata qui reçoit les params et fetch les données pour construire les métadonnées (bonne réponse)
  • Modifier le head dynamiquement avec JavaScript
  • Utiliser un plugin SEO externe obligatoirement
  • Les métadonnées dynamiques ne sont pas possibles dans Next.js
Explication : La fonction generateMetadata({ params, searchParams }) permet de générer des métadonnées dynamiques. Elle s'exécute côté serveur, peut fetch des données, et retourne un objet metadata.
Exemple : export async function generateMetadata({ params }) { const post = await getPost(params.slug); return { title: post.title } }.

  • fetch(url, { next: { revalidate: 3600 } }) pour régénérer toutes les heures (bonne réponse)
  • fetch(url, { cache: "isr", time: 3600 })
  • fetch(url, { static: false, revalidate: 3600 })
  • ISR n'est pas supporté dans l'App Router
Explication : L'option next: { revalidate: n } (n en secondes) active l'ISR. La page est servie statiquement, puis régénérée en arrière-plan après n secondes quand une requête arrive.
Pour désactiver le cache et forcer le SSR : fetch(url, { cache: "no-store" }).

  • On entoure les composants lents avec et un fallback ; le HTML est envoyé progressivement (bonne réponse)
  • Le streaming nécessite une configuration spéciale du serveur
  • Seuls les fichiers vidéo peuvent être streamés
  • Le streaming n'est disponible qu'en production
Explication : Le streaming envoie le HTML par morceaux. Les parties entourées de <Suspense fallback={<Loader />}> affichent d'abord le fallback, puis le contenu réel est streamé et remplace le fallback quand il est prêt.
Utilisez loading.js pour un Suspense automatique, ou <Suspense> manuellement pour un contrôle plus fin.

  • Dans next.config.js avec la clé redirects() (bonne réponse)
  • Avec window.location.replace()
  • Dans le fichier .htaccess
  • Avec le composant
Explication : Dans next.config.js : async redirects() { return [{ source: "/ancienne", destination: "/nouvelle", permanent: true }] }. On peut aussi utiliser redirect() de next/navigation dans un Server Component.
Pour des redirections conditionnelles (auth), utilisez le Middleware ou redirect() dans un Server Component.

  • revalidatePath() invalide une route spécifique ; revalidateTag() invalide toutes les requêtes fetch avec un tag donné (bonne réponse)
  • revalidatePath() est pour le client ; revalidateTag() pour le serveur
  • Il n'y a pas de différence
  • revalidatePath() est plus lent que revalidateTag()
Explication : revalidatePath("/blog") régénère la page à cette route. revalidateTag("posts") invalide toutes les requêtes fetch qui ont été taguées avec fetch(url, { next: { tags: ["posts"] } }), quel que soit l'endroit où elles sont utilisées.
Utilisez les tags pour invalider des données partagées entre plusieurs pages (ex: mise à jour d'un article → invalider la liste et le détail).

  • Dans un Server Component via props.searchParams ; dans un Client Component via useSearchParams() (bonne réponse)
  • Uniquement avec window.location.search
  • Avec le hook useQuery()
  • Les query strings ne sont pas supportés dans Next.js
Explication : Dans un Server Component (page.js), les searchParams sont passés en props. Dans un Client Component, on utilise useSearchParams() de next/navigation.
Attention : useSearchParams() nécessite un Client Component ou un Suspense boundary.

  • Next.js divise automatiquement le code par route : chaque page charge uniquement son JavaScript nécessaire (bonne réponse)
  • Le développeur doit manuellement diviser chaque composant
  • Le code splitting n'existe pas dans Next.js
  • C'est une fonctionnalité de React uniquement
Explication : Next.js fait du code splitting automatique par route. Chaque page ne charge que le JavaScript nécessaire à son fonctionnement. On peut aussi utiliser dynamic() pour du lazy loading de composants spécifiques.
Pour charger un composant lourd uniquement quand nécessaire : const HeavyComponent = dynamic(() => import("./HeavyComponent")).

  • Avec la fonction cookies() de next/headers (bonne réponse)
  • Avec document.cookie
  • Avec localStorage
  • Les cookies ne sont pas accessibles côté serveur
Explication : Dans un Server Component, on utilise cookies() importé de next/headers. C'est une fonction synchrone qui retourne l'objet cookies. Exemple : const cookieStore = cookies(); const token = cookieStore.get("token").
cookies() est une fonction dynamique : son utilisation rend toute la route dynamique (SSR).

  • Avec un bloc try/catch dans le composant async, ou en utilisant le fichier error.js (bonne réponse)
  • Avec un useEffect côté client
  • Les erreurs de fetch n'arrivent jamais côté serveur
  • Uniquement avec un middleware
Explication : Dans un Server Component async, on peut utiliser try/catch pour gérer les erreurs de fetch. Pour une gestion déclarative, le fichier error.js (Error Boundary) capture les erreurs non gérées.
Combinez les deux : try/catch pour des comportements spécifiques, error.js comme filet de sécurité global.

  • Via les props : le Server Component fetch les données et les passe en props au Client Component (bonne réponse)
  • Via un state global comme Redux
  • Via localStorage
  • On ne peut pas communiquer entre Server et Client Components
Explication : Un Server Component peut fetch des données et les passer comme props à un Client Component enfant. Le Server Component s'exécute d'abord, puis les données sérialisées sont transmises au Client Component.
Les données passées doivent être sérialisables (pas de fonctions, pas de classes). Privilégiez les types simples : string, number, object, array.

  • Séparer le code applicatif des fichiers de configuration pour une meilleure organisation (bonne réponse)
  • C'est obligatoire pour le déploiement
  • Cela rend l'application plus rapide
  • Le dossier src/ n'est pas supporté
Explication : Le dossier src/ (optionnel) permet de placer app/ (ou pages/) à l'intérieur, séparant le code source des fichiers de config racine (next.config.js, package.json, tsconfig.json).
Proposé lors du create-next-app. Utile pour les grands projets avec beaucoup de fichiers de configuration.

  • La page liée est préchargée automatiquement quand le entre dans le viewport (bonne réponse)
  • Toutes les pages sont préchargées au chargement initial
  • Le préchargement doit être configuré manuellement
  • Le préchargement ne fonctionne qu'en développement
Explication : En production, <Link> précharge automatiquement la route cible dès que le lien apparaît dans le viewport (intersection observer). Cela rend la navigation quasi-instantanée.
Pour désactiver ce comportement sur un lien spécifique : <Link href="/route" prefetch={false}>.

  • Une fonction qui déclenche la page 404 depuis un Server Component quand une ressource n'existe pas (bonne réponse)
  • Une fonction qui supprime une page
  • Une fonction pour le débogage
  • Un alias pour redirect()
Explication : notFound() (importée de next/navigation) permet de déclencher programmatiquement la page 404. À utiliser dans un Server Component quand une ressource fetchée n'existe pas.
Pattern typique : const post = await getPost(slug); if (!post) notFound();.

  • Dans next.config.js avec la fonction headers() (bonne réponse)
  • Dans le fichier .htaccess
  • Avec les balises dans le HTML
  • Uniquement via le serveur de déploiement
Explication : La fonction headers() dans next.config.js permet de définir des en-têtes HTTP personnalisés pour certaines routes. Exemple : ajouter des headers de sécurité (CSP, CORS, HSTS).
Exemple : async headers() { return [{ source: "/(.*)", headers: [{ key: "X-Frame-Options", value: "DENY" }] }] }.

  • Les routes API exposent des endpoints HTTP publics ; les Server Actions sont des fonctions serveur appelables depuis le client pour des mutations (bonne réponse)
  • Les Server Actions remplacent complètement les routes API
  • Il n'y a pas de différence
  • Les routes API sont plus rapides
Explication : Les Route Handlers (route.js) créent des endpoints API RESTful standards accessibles via HTTP. Les Server Actions sont des fonctions appelées directement depuis des Client Components, sans créer de route API explicite.
Utilisez les Server Actions pour les formulaires et mutations internes. Utilisez les Route Handlers pour des API publiques, des webhooks, ou l'intégration avec des services tiers.

  • const MonComposant = dynamic(() => import("./MonComposant"), { loading: () => }) (bonne réponse)
  • const MonComposant = lazy(() => import("./MonComposant"))
  • import { lazy } from "next/dynamic"
  • Le lazy loading est automatique
Explication : next/dynamic permet de charger un composant uniquement quand il est nécessaire. Options : loading (composant de fallback), ssr: false (désactiver le SSR pour ce composant).
Utile pour les composants lourds (éditeurs, visualiseurs) ou les bibliothèques qui utilisent window et ne fonctionnent pas côté serveur.

  • Middlewares pour protéger les routes, Server Actions pour login/logout, cookies httpOnly sécurisés (bonne réponse)
  • Uniquement avec des API routes externes
  • L'authentification n'est pas gérée par Next.js
  • Avec localStorage dans le navigateur uniquement
Explication : L'approche recommandée : Middleware pour vérifier les sessions côté serveur, Server Actions pour les opérations login/logout (le token reste côté serveur), cookies httpOnly pour stocker les sessions. NextAuth.js/Auth.js simplifie tout cela.
Ne stockez jamais de tokens sensibles dans localStorage. Préférez les cookies httpOnly gérés par le serveur.

  • En créant un dossier entre parenthèses, ex: app/(marketing)/page.js (bonne réponse)
  • En utilisant un fichier de configuration de groupes
  • En créant des sous-domaines
  • Les groupes de routes ne sont pas supportés
Explication : Les Route Groups utilisent des dossiers nommés entre parenthèses : app/(marketing)/page.js. Le nom entre parenthèses n'affecte pas l'URL. Utile pour organiser les routes sans modifier les chemins.
Utile pour appliquer différents layouts à des groupes de pages : app/(marketing)/layout.js et app/(dashboard)/layout.js.

  • Utiliser Promise.all() pour lancer les requêtes en parallèle (bonne réponse)
  • Faire les fetch les uns après les autres avec await
  • Les requêtes parallèles ne sont pas possibles
  • Utiliser useEffect
Explication : Avec Promise.all(), on lance plusieurs fetch simultanément : const [data1, data2] = await Promise.all([fetch(url1), fetch(url2)]). Évitez d'attendre chaque fetch séquentiellement.
Le séquentiel : const a = await fetch1(); const b = await fetch2(); est plus lent. Préférez Promise.all quand les requêtes sont indépendantes.

  • Les params sont accessibles via la prop params dans le layout (bonne réponse)
  • Avec le hook useParams()
  • Les layouts n'ont pas accès aux params
  • Avec useContext()
Explication : Depuis Next.js 14, les params sont passés au layout.js en props. Exemple : export default function Layout({ params, children }) { return <div>Article {params.slug}{children}</div> }.
Utile pour afficher le titre de la page courante dans une barre de navigation ou un fil d'Ariane.

  • next/image réserve automatiquement l'espace avec width/height et utilise le lazy loading pour éviter le CLS (bonne réponse)
  • Il faut manuellement définir les dimensions dans le CSS
  • Le CLS n'est pas un problème avec Next.js
  • next/image ne gère pas le CLS
Explication : Le composant <Image> utilise les attributs width et height pour calculer le ratio et réserver l'espace dans le layout. Le fill avec sizes évite aussi le CLS.
Ajoutez toujours width et height (ou utilisez fill avec un conteneur positionné) pour éviter le saut de mise en page.

  • Exporter une fonction generateStaticParams qui retourne la liste des slugs à pré-générer au build (bonne réponse)
  • Configurer manuellement chaque route dans next.config.js
  • Utiliser getStaticPaths dans l'App Router
  • Les routes dynamiques ne peuvent pas être pré-générées
Explication : generateStaticParams() est utilisée dans les pages dynamiques pour définir quels paramètres doivent être pré-générés au build (SSG). Exemple : export async function generateStaticParams() { const posts = await getPosts(); return posts.map(p => ({ slug: p.slug })) }.
Si un paramètre n'est pas retourné par generateStaticParams, la page sera rendue en SSR (dynamique) à la première requête, puis mise en cache.