BackRetour au blog

Next.js 15 RC 2

La deuxième version candidate (RC) de Next.js 15 est désormais disponible. Cette version vous permet de tester les dernières fonctionnalités avant la prochaine version stable.

Suite à l'annonce de la première version candidate de Next.js 15 en mai dernier, nous avons préparé une deuxième version candidate basée sur vos retours. Voici ce sur quoi nous avons travaillé :

Essayez dès maintenant la version candidate de Next.js 15 (RC2) :

# Utilisez le nouveau CLI de mise à jour automatisée
npx @next/codemod@canary upgrade rc
 
# ...ou mettez à jour manuellement
npm install next@rc react@rc react-dom@rc

Note : Cette version candidate inclut toutes les modifications de la RC précédente.

Mises à jour simplifiées avec le CLI codemod

Nous incluons des codemods (transformations de code automatisées) avec chaque version majeure de Next.js pour faciliter la migration des changements majeurs.

Pour rendre les mises à jour encore plus fluides, nous avons publié un CLI codemod amélioré :

npx @next/codemod@canary upgrade rc

Cet outil vous aide à mettre à jour votre codebase vers les dernières versions stables ou préliminaires. Le CLI mettra à jour vos dépendances, affichera les codemods disponibles et vous guidera pour les appliquer. Le tag de distribution spécifié dans la commande (@rc, @canary, etc.) détermine la version cible.

En savoir plus sur les codemods Next.js.

Turbopack pour le développement

Turbopack pour le développement local deviendra stable dans la version générale de Next.js 15, tout en restant optionnel. Vous pouvez l'essayer dès maintenant avec :

next dev --turbo

Grâce aux milliers de développeurs ayant participé aux tests, signalé des problèmes et validé des corrections durant les phases bêta et candidate de Turbopack, nous avons résolu 54 problèmes GitHub depuis la première version candidate de Next.js 15. En complément de cet effort communautaire, nos tests internes sur vercel.com, v0.dev et nextjs.org ont permis d'identifier de nombreuses améliorations supplémentaires.

Ces trois derniers mois, nous nous sommes concentrés sur l'optimisation des performances de compilation à froid. Par rapport à la version précédente, nous observons :

  • 25–35% de réduction de l'utilisation mémoire.
  • 30–50% plus rapide pour la compilation de pages volumineuses avec des milliers de modules.

Nous continuerons à optimiser ces aspects dans les futures versions.

Pour l'avenir, l'équipe Turbopack progresse significativement sur le cache persistant, la réduction d'utilisation mémoire et Turbopack pour next build — avec 96% des tests passants.

Note : Consultez toutes les fonctionnalités prises en charge et non prises en charge de Turbopack.

API de requête asynchrones (Changement majeur)

Dans le rendu côté serveur traditionnel, le serveur attend une requête avant de générer du contenu. Cependant, tous les composants ne dépendent pas de données spécifiques à la requête, il est donc inutile d'attendre la requête pour les rendre. Idéalement, le serveur préparerait autant que possible avant l'arrivée d'une requête. Pour permettre cela et préparer le terrain pour des optimisations futures, nous devons savoir quand attendre la requête.

Par conséquent, nous transitionnons les API qui dépendent de données spécifiques à la requête — comme headers, cookies, params et searchParams — pour qu'elles soient asynchrones.

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

Ceci est un changement majeur qui affecte les API suivantes :

  • cookies
  • headers
  • draftMode
  • params dans layout.js, page.js, route.js, default.js, generateMetadata et generateViewport
  • searchParams dans page.js

Pour faciliter la migration, ces API peuvent temporairement être accédées de manière synchrone, mais afficheront des avertissements en développement et en production jusqu'à la prochaine version majeure. Un codemod est disponible pour automatiser la migration :

npx @next/codemod@canary next-async-request-api .

Pour les cas où le codemod ne peut pas migrer entièrement votre code, veuillez consulter le guide de mise à jour. Nous avons également fourni un exemple de migration d'une application Next.js vers les nouvelles API.

Sécurité renforcée pour les actions serveur

Les actions serveur sont des fonctions côté serveur pouvant être appelées depuis le client. Elles sont définies en ajoutant la directive 'use server' en haut d'un fichier et en exportant une fonction asynchrone.

Même si une action serveur ou une fonction utilitaire n'est pas importée ailleurs dans votre code, il s'agit toujours d'un endpoint HTTP accessible publiquement. Bien que ce comportement soit techniquement correct, il peut conduire à une exposition involontaire de ces fonctions.

Pour améliorer la sécurité, nous avons introduit les améliorations suivantes :

  • Élimination de code mort : Les actions serveur inutilisées n'auront pas leurs IDs exposés dans le bundle JavaScript côté client, réduisant la taille du bundle et améliorant les performances.
  • IDs d'action sécurisés : Next.js crée désormais des IDs imprévisibles et non déterministes pour permettre au client de référencer et d'appeler l'action serveur. Ces IDs sont recalculés périodiquement entre les builds pour une sécurité renforcée.
// app/actions.js
'use server';
 
// Cette action **est** utilisée dans notre application, donc Next.js
// créera un ID sécurisé pour permettre au client de référencer
// et d'appeler l'action serveur.
export async function updateUserAction(formData) {}
 
// Cette action **n'est pas** utilisée dans notre application, donc Next.js
// supprimera automatiquement ce code pendant `next build`
// et ne créera pas d'endpoint public.
export async function deleteUserAction(formData) {}

Vous devez toujours traiter les actions serveur comme des endpoints HTTP publics. En savoir plus sur la sécurisation des actions serveur.

Indicateur de route statique

Next.js affiche désormais un indicateur de route statique pendant le développement pour vous aider à identifier quelles routes sont statiques ou dynamiques. Cet indicateur visuel facilite l'optimisation des performances en comprenant comment vos pages sont rendues.

Vous pouvez également utiliser la sortie de next build pour voir la stratégie de rendu de toutes les routes.

Cette mise à jour fait partie de nos efforts continus pour améliorer l'observabilité dans Next.js, facilitant la surveillance, le débogage et l'optimisation des applications. Nous travaillons également sur des outils dédiés aux développeurs, avec plus de détails à venir.

En savoir plus sur l'indicateur de route statique, qui peut être désactivé.

Composant <Form>

Le nouveau composant <Form> étend l'élément HTML <form> avec la pré-récupération, la navigation côté client et l'amélioration progressive.

Il est utile pour les formulaires qui naviguent vers une nouvelle page, comme un formulaire de recherche menant à une page de résultats.

import Form from 'next/form';
 
export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  );
}

Le composant <Form> inclut :

  • Pré-récupération : Lorsque le formulaire est visible, le layout et l'interface de chargement sont pré-récupérés, rendant la navigation rapide.
  • Navigation côté client : À la soumission, les layouts partagés et l'état côté client sont préservés.
  • Amélioration progressive : Si JavaScript n'est pas encore chargé, le formulaire fonctionne toujours via une navigation complète de page.

Auparavant, implémenter ces fonctionnalités nécessitait beaucoup de code standard manuel. Par exemple :

Exemple

// Note : Ceci est abrégé à des fins de démonstration.
// Non recommandé pour du code de production.
 
'use client'
 
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
 
export default function Form(props) {
  const action = props.action
  const router = useRouter()
 
  useEffect(() => {
    // si la cible du formulaire est une URL, la pré-récupérer
    if (typeof action === 'string') {
      router.prefetch(action)
    }
  }, [action, router])
 
  function onSubmit(event) {
    event.preventDefault()
 
    // récupérer tous les champs du formulaire et déclencher un `router.push` avec les données encodées dans l'URL
    const formData = new FormData(event.currentTarget)
    const data = new URLSearchParams()
 
    for (const [name, value] of formData) {
      data.append(name, value as string)
    }
 
    router.push(`${action}?${data.toString()}`)
  }
 
  if (typeof action === 'string') {
    return <form onSubmit={onSubmit} {...props} />
  }
 
  return <form {...props} />
}

En savoir plus sur le composant <Form>.

Prise en charge de next.config.ts

Next.js prend désormais en charge le type de fichier TypeScript next.config.ts et fournit un type NextConfig pour l'autocomplétion et des options typées :

import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  /* options de configuration ici */
};
 
export default nextConfig;

En savoir plus sur la prise en charge de TypeScript dans Next.js.

instrumentation.js (Stable)

Le fichier instrumentation, avec l'API register(), permet aux utilisateurs d'accéder au cycle de vie du serveur Next.js pour surveiller les performances, tracer la source des erreurs et intégrer profondément avec des bibliothèques d'observabilité comme OpenTelemetry.

Cette fonctionnalité est désormais stable et l'option de configuration experimental.instrumentationHook peut être supprimée.

De plus, nous avons collaboré avec Sentry pour concevoir un nouveau hook onRequestError qui peut être utilisé pour :

  • Capturer un contexte important sur toutes les erreurs levées côté serveur, incluant :
    • Routeur : Pages Router ou App Router
    • Contexte serveur : Composant serveur, Action serveur, Gestionnaire de route ou Middleware
  • Reporter les erreurs à votre fournisseur d'observabilité préféré.
export async function onRequestError(err, request, context) {
  await fetch('https://...', {
    method: 'POST',
    body: JSON.stringify({ message: err.message, request, context }),
    headers: { 'Content-Type': 'application/json' },
  });
}
 
export async function register() {
  // initialiser le SDK de votre fournisseur d'observabilité préféré
}

En savoir plus sur la fonction onRequestError.

Améliorations du développement et de la construction

HMR pour les composants serveur

Pendant le développement, les composants serveur sont ré-exécutés lors de la sauvegarde. Cela signifie que toutes les requêtes fetch vers vos endpoints API ou services tiers sont également appelées.

Pour améliorer les performances en développement local et réduire les coûts potentiels des appels API facturés, nous nous assurons désormais que le Hot Module Replacement (HMR) peut réutiliser les réponses fetch des rendus précédents.

En savoir plus sur le cache HMR des composants serveur.

Génération statique plus rapide pour l'App Router

Nous avons optimisé la génération statique pour améliorer les temps de construction, notamment pour les pages avec des requêtes réseau lentes.

Auparavant, notre processus d'optimisation statique rendait les pages deux fois — une fois pour générer les données pour la navigation côté client et une seconde fois pour générer le HTML pour la visite initiale. Maintenant, nous réutilisons le premier rendu, éliminant la seconde passe, réduisant ainsi la charge de travail et les temps de construction.

De plus, les workers de génération statique partagent désormais le cache fetch entre les pages. Si un appel fetch ne désactive pas la mise en cache, ses résultats sont réutilisés par d'autres pages gérées par le même worker. Cela réduit le nombre de requêtes pour les mêmes données.

Contrôle avancé de la génération statique (expérimental)

Nous avons ajouté un support expérimental pour un contrôle accru du processus de génération statique, destiné aux cas d'utilisation avancés qui bénéficieraient d'une plus grande maîtrise.

Nous recommandons de conserver les paramètres par défaut actuels, sauf si vous avez des besoins spécifiques, car ces options peuvent entraîner une augmentation de l'utilisation des ressources et des erreurs potentielles de mémoire insuffisante en raison d'une concurrence accrue.

const nextConfig = {
  experimental: {
	  // nombre de tentatives de régénération de page en cas d'échec
	  // avant d'abandonner la construction
    staticGenerationRetryCount: 1
    // nombre de pages traitées par worker
    staticGenerationMaxConcurrency: 8
    // nombre minimum de pages avant de créer un nouveau worker d'export
    staticGenerationMinPagesPerWorker: 25
  },
}
 
export default nextConfig;

En savoir plus sur les options de génération statique.

Améliorations pour l'auto-hébergement

Lors de l'auto-hébergement d'applications, vous pourriez avoir besoin d'un meilleur contrôle sur les directives Cache-Control.

Un cas courant est le contrôle de la période stale-while-revalidate envoyée pour les pages ISR. Nous avons implémenté deux améliorations :

  1. Vous pouvez désormais configurer la valeur expireTime dans next.config. Il s'agissait auparavant de l'option experimental.swrDelta.
  2. La valeur par défaut a été mise à jour à un an, garantissant que la plupart des CDN puissent appliquer pleinement la sémantique stale-while-revalidate comme prévu.

Nous ne remplaçons plus non plus les valeurs personnalisées de Cache-Control par nos valeurs par défaut, permettant un contrôle total et assurant une compatibilité avec toute configuration de CDN.

Enfin, nous avons amélioré l'optimisation des images lors de l'auto-hébergement. Auparavant, nous recommandions d'installer sharp pour optimiser les images sur votre serveur Next.js. Cette recommandation était parfois oubliée. Avec Next.js 15, vous n'avez plus besoin d'installer manuellement sharp — Next.js utilisera automatiquement sharp lors de l'utilisation de next start ou de l'exécution en mode de sortie autonome.

Pour en savoir plus, consultez notre nouvelle démo et vidéo tutorielle sur l'auto-hébergement de Next.js.

Support d'ESLint 9

Next.js 15 introduit également le support d'ESLint 9, suite à la fin de vie d'ESLint 8 le 5 octobre 2024.

Pour assurer une transition en douceur, Next.js reste rétrocompatible, ce qui signifie que vous pouvez continuer à utiliser ESLint 8 ou 9.

Si vous passez à ESLint 9 et que nous détectons que vous n'avez pas encore adopté le nouveau format de configuration, Next.js appliquera automatiquement l'échappatoire ESLINT_USE_FLAT_CONFIG=false pour faciliter la migration.

De plus, les options obsolètes comme —ext et —ignore-path seront supprimées lors de l'exécution de next lint. Notez qu'ESLint finira par interdire ces anciennes configurations dans ESLint 10, nous vous recommandons donc de commencer votre migration dès que possible.

Pour plus de détails sur ces changements, consultez le guide de migration.

Dans le cadre de cette mise à jour, nous avons également mis à niveau eslint-plugin-react-hooks vers v5.0.0, qui introduit de nouvelles règles pour l'utilisation des Hooks React. Vous pouvez consulter tous les changements dans le changelog de [email protected].

Autres changements

  • Tous les changements précédemment décrits dans l'article de blog RC 1
  • [Cassant] Nous avons déprécié l'exportation de export const runtime = "experimental-edge" dans l'App Router. Les utilisateurs doivent maintenant passer à export const runtime = "edge". Nous avons ajouté un codemod pour effectuer cette opération (PR)
  • [Cassant] L'appel à revalidateTag et revalidatePath pendant le rendu générera désormais une erreur (PR)
  • [Cassant] Les fichiers instrumentation.js et middleware.js utiliseront désormais les packages React fournis (PR)
  • [Cassant] La version minimale requise de Node.js a été mise à jour vers 18.18.0 (PR)
  • [Cassant] next/dynamic : la prop dépréciée suspense a été supprimée et lorsque le composant est utilisé dans l'App Router, il n'insérera plus de limite Suspense vide (PR)
  • [Cassant] Lors de la résolution de modules sur l'Edge Runtime, la condition de module worker ne sera pas appliquée (PR)
  • [Cassant] Interdiction d'utiliser l'option ssr: false avec next/dynamic dans les composants serveur (PR)
  • [Amélioration] Les options outputFileTracingRoot, outputFileTracingIncludes et outputFileTracingExcludes ont été promues du statut expérimental et sont maintenant stables (PR)
  • [Amélioration] Évite la fusion des fichiers CSS globaux avec les fichiers de modules CSS plus profonds dans l'arborescence (PR)
  • [Amélioration] Le gestionnaire de cache peut désormais être spécifié via la variable d'environnement NEXT_CACHE_HANDLER_PATH (PR)
  • [Amélioration] Le Pages Router supporte désormais React 18 et React 19 (PR)
  • [Amélioration] L'overlay d'erreur affiche désormais un bouton pour copier l'URL de l'inspecteur Node.js si celui-ci est activé (PR)
  • [Amélioration] Les préchargements clients sur l'App Router utilisent désormais l'attribut priority (PR)
  • [Amélioration] Next.js fournit désormais une fonction unstable_rethrow pour relancer les erreurs internes de Next.js dans l'App Router (PR)
  • [Amélioration] unstable_after peut désormais être utilisé dans les pages statiques (PR)
  • [Amélioration] Si un composant next/dynamic est utilisé pendant le SSR, le chunk sera préchargé (PR)
  • [Amélioration] L'option esmExternals est désormais supportée sur l'App Router (PR)
  • [Amélioration] L'option experimental.allowDevelopmentBuild peut être utilisée pour autoriser NODE_ENV=development avec next build à des fins de débogage (PR)
  • [Amélioration] Les transformations de Server Action sont désormais désactivées dans le Pages Router (PR)
  • [Amélioration] Les workers de build empêcheront désormais le build de rester bloqué lorsqu'ils se terminent (PR)
  • [Amélioration] Lors d'une redirection depuis une Server Action, les revalidations s'appliqueront correctement (PR)
  • [Amélioration] Les paramètres dynamiques sont désormais correctement gérés pour les routes parallèles sur l'Edge Runtime (PR)
  • [Amélioration] Les pages statiques respecteront désormais staleTime après le chargement initial (PR)
  • [Amélioration] vercel/og mis à jour avec un correctif de fuite mémoire (PR)
  • [Amélioration] Les timings des patches mis à jour pour permettre l'utilisation de packages comme msw pour le mocking d'APIs (PR)

Contributeurs

Next.js est le fruit du travail combiné de plus de 3 000 développeurs individuels et de notre équipe principale chez Vercel. Cette version a été rendue possible par :

Un grand merci à @huozhi, @shuding, @wyattjoh, @PaulAsjes, @mcnaveen, @timneutkens, @stipsan, @aktoriukas, @sirTangale, @greatvivek11, @sokra, @anatoliik-lyft, @wbinnssmith, @coltonehrman, @hungdoansy, @kxlow, @ztanner, @manovotny, @leerob, @ryota-murakami, @ijjk, @pnutmath, @feugy, @Jeffrey-Zutt, @wiesson, @eps1lon, @devjiwonchoi, @Ethan-Arrowood, @kenji-webdev, @domdomegg, @samcx, @Jaaneek, @evanwinter, @kdy1, @balazsorban44, @feedthejim, @ForsakenHarmony, @kwonoj, @delbaoliveira, @xiaohanyu, @dvoytenko, @bobaaaaa, @bgw, @gaspar09, @souporserious, @unflxw, @kiner-tang, @Ehren12, @EffectDoplera, @IAmKushagraSharma, @Auxdible, @sean-rallycry, @jeanmax1me, @unstubbable, @NilsJacobsen, @adiguno, @ryan-nauman, @zsh77, @KagamiChan, @steveluscher, @MehfoozurRehman, @vkryachko, @chentsulin, @samijaber, @begalinsaf, @FluxCapacitor2, @lukahartwig, @brianshano, @pavelglac, @styfle, @symant233, @HristovCodes, @karlhorky, @jonluca, @jonathan-ingram, @mknichel, @sopranopillow, @Gomah, @imddc, @notrab, @gabrielrolfsen, @remorses, @AbhiShake1, @agadzik, @rishabhpoddar, @rezamauliadi, @IncognitoTGT, @webtinax, @BunsDev, @nisabmohd, @z0n, @bennettdams, @joeshub, @n1ckoates, @srkirkland, @RiskyMH, @coopbri, @okoyecharles, @diogocapela, @dnhn, @typeofweb, @davidsa03, @imranolas, @lubieowoce, @maxhaomh, @mirasayon, @blvdmitry, @hwangstar156, @lforst, @emmerich, @christian-bromann, @Lsnsh, @datner, @hiro0218, @flybayer, @ianmacartney, @ypessoa, @ryohidaka, @icyJoseph, @Arinji2, @lovell, @nsams, @Nayeem-XTREME, @JamBalaya56562, @Arindam200, @gaojude, @qqww08, @todor0v, @tokkiyaa, @arlyon, @lorensr, @Juneezee, @Sayakie, @IGassmann, @bosconian-dynamics, @phryneas, @akazwz, @atik-persei, @shubh73, @alpedia0, @chogyejin, @notomo, @ArnoldVanN, @dhruv-kaushik, @kevva, @Kahitar, @anay-208, @boris-szl, @devnyxie, @LorisSigrist, @M-YasirGhaffar, @Lada496, @kippmr, @torresgol10, @pkiv, @Netail, @jontewks, @ArnaudFavier, @chrisjstott, @mratlamwala, @mayank1513, @karlkeefer, @kshehadeh, @Marukome0743, @a89529294, @anku255, @KeisukeNagakawa, @andrii-bodnar, @aldosch, @versecafe, @steadily-worked, @cfrank, @QiuranHu, @farsabbutt, @joostmeijles, @saltcod, @archanaagivale30, @crutchcorn, @crebelskydico, @Maaz-Ahmed007, @jophy-ye, @remcohaszing, @JoshuaKGoldberg, @creativoma, @GyoHeon, @SukkaW, @MaxLeiter, @neila-a, @stylessh, @Teddir, @ManuLpz4, @Julian-Louis, @syi0808, @mert-duzgun, @amannn, @MonstraG, @hamirmahal, @tariknh, @Kikobeats, @LichuAcu, @Kuboczoch, @himself65, @Sam-Phillemon9493, @Shruthireddy04, @Hemanshu-Upadhyay, @timfuhrmann, @controversial, @pathliving, @mischnic, @mauroaccornero, @NavidNourani, @allanchau, @ekremkenter, @yurivangeffen, @gnoff, @darthmaim, @gdborton, @Willem-Jaap, @KentoMoriwaki, @TrevorSayre, @marlier, @Luluno01, @xixixao, @domin-mnd, @niketchandivade, @N2D4, @kjugi, @luciancah, @mud-ali, @codeSTACKr, @luojiyin1987, @mehmetozguldev, @ronanru, @tknickman, @joelhooks, @khawajaJunaid, @rubyisrust, @abdull-haseeb, @bewinsnw, @housseindjirdeh, @li-jia-nan, @aralroca, @s-ekai, @ah100101, @jantimon, @jordienr, @iscekic, @Strift, @slimbde, @nauvalazhar, @HughHzyb, @guisehn, @wesbos, @OlyaPolya, @paarthmadan, @AhmedBaset, @dineshh-m, @avdeev, @Bhavya031, @MildTomato, @Bjornnyborg, @amikofalvy, @yosefbeder, @kjac, @woutvanderploeg, @Ocheretovich, @ProchaLu, @luismiramirez, @omahs, @theoludwig, @abhi12299, @sommeeeer, @lumirlumir, @royalfig, @iampoul, @molebox, @txxxxc, @zce, @mamuso, @kahlstrm, @vercel-release-bot, @zhawtof, @PapatMayuri, @PlagueFPS, @IDNK2203, @jericopulvera, @liby, @CannonLock, @timfish, @whatisagi, @none23, @haouvw, @Pyr33x, @SouthLink, @frydj, @CrutchTheClutch, @sleevezip, @r34son, @yunsii, @md-rejoyan-islam, @kartheesan05, @nattui, @KonkenBonken, @weicheng95, @brekk, @Francoscopic, @B33fb0n3, @ImDR, @nurullah, @hdodov, @ebCrypto, @soedirgo, @floriangosse, @Tim-Zj, @raeyoung-kim, @erwannbst, @DerTimonius, @hirotomoyamada, @Develliot, @chandanpasunoori, @vicb, @ankur-dwivedi, @kidonng, @baeharam, @AnaTofuZ, @coderfin, @xugetsu, @alessiomaffeis, @kutsan, @jordyfontoura, @sebmarkbage, @tranvanhieu01012002, @jlbovenzo, @Luk-z, @jaredhan418, @bangseongbeom, @penicillin0, @neoFinch, @DeepakBalaraman, @Manoj-M-S, @Unsleeping, @lonr, @Aerilym, @ytori, @acdlite, @actopas, @n-ii-ma, @adcichowski, @mobeigi, @JohnGemstone, et @jjm2317 pour leur aide !