BackRetour au blog

Next.js 14

Next.js 14 inclut des améliorations de performances, une stabilisation des Server Actions, un nouveau cours sur le Router d'application et plus encore.

Comme annoncé lors de la Next.js Conf, Next.js 14 est notre version la plus ciblée avec :

  • Turbopack : 5 000 tests validés pour le Router d'application et des pages
    • 53 % plus rapide au démarrage du serveur local
    • 94 % plus rapide pour les mises à jour de code avec Fast Refresh
  • Server Actions (Stable) : Mutations à amélioration progressive
    • Intégrées avec le cache et la revalidation
    • Appels de fonction simples ou fonctionnement natif avec les formulaires
  • Partial Prerendering (Preview) : Réponse statique initiale rapide + contenu dynamique en streaming
  • Next.js Learn (Nouveau) : Cours gratuit sur le Router d'application, l'authentification, les bases de données et plus.

Mettez à jour dès aujourd'hui ou commencez avec :

Terminal
npx create-next-app@latest

Next.js Compiler : Surpuissant

Depuis Next.js 13, nous travaillons à améliorer les performances en développement local dans Next.js, que ce soit avec le Router d'application ou des pages.

Auparavant, nous réécrivions next dev et d'autres parties de Next.js pour soutenir cet effort. Nous avons depuis adopté une approche plus progressive. Cela signifie que notre compilateur basé sur Rust atteindra bientôt la stabilité, car nous nous concentrons d'abord sur le support de toutes les fonctionnalités de Next.js.

5 000 tests d'intégration pour next dev passent maintenant avec Turbopack, notre moteur Rust sous-jacent. Ces tests incluent 7 ans de corrections de bugs et de reproductions.

Lors de tests sur vercel.com, une grande application Next.js, nous avons observé :

  • Jusqu'à 53,3 % plus rapide au démarrage du serveur local
  • Jusqu'à 94,7 % plus rapide pour les mises à jour de code avec Fast Refresh

Ce benchmark est un résultat pratique des améliorations de performances que vous pouvez attendre avec une grande application (et un grand graphe de modules). Avec 90 % des tests pour next dev maintenant validés, vous devriez voir des performances plus rapides et plus fiables de manière constante lors de l'utilisation de next dev --turbo.

Une fois que 100 % des tests seront validés, nous ferons passer Turbopack en stable dans une prochaine version mineure. Nous continuerons également à supporter webpack pour les configurations personnalisées et les plugins de l'écosystème.

Vous pouvez suivre le pourcentage de tests validés sur areweturboyet.com.

Formulaires et Mutations

Next.js 9 a introduit les API Routes — un moyen de créer rapidement des endpoints backend aux côtés de votre code frontend.

Par exemple, vous pourriez créer un nouveau fichier dans le répertoire api/ :

pages/api/submit.ts
import type { NextApiRequest, NextApiResponse } from 'next';
 
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse,
) {
  const data = req.body;
  const id = await createItem(data);
  res.status(200).json({ id });
}

Puis, côté client, vous pourriez utiliser React et un gestionnaire d'événements comme onSubmit pour faire un fetch vers votre API Route.

pages/index.tsx
import { FormEvent } from 'react';
 
export default function Page() {
  async function onSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
 
    const formData = new FormData(event.currentTarget);
    const response = await fetch('/api/submit', {
      method: 'POST',
      body: formData,
    });
 
    // Gérer la réponse si nécessaire
    const data = await response.json();
    // ...
  }
 
  return (
    <form onSubmit={onSubmit}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

Avec Next.js 14, nous voulons simplifier l'expérience développeur pour créer des mutations de données. De plus, nous voulons améliorer l'expérience utilisateur lorsque l'utilisateur a une connexion réseau lente, ou lorsqu'il soumet un formulaire depuis un appareil moins performant.

Server Actions (Stable)

Et si vous n'aviez pas besoin de créer manuellement une API Route ? À la place, vous pourriez définir une fonction qui s'exécute de manière sécurisée sur le serveur, appelée directement depuis vos composants React.

Le Router d'application est construit sur le canal canary de React, qui est stable pour les frameworks pour adopter de nouvelles fonctionnalités. Depuis la v14, Next.js a été mis à jour vers la dernière version canary de React, qui inclut les Server Actions stables.

L'exemple précédent du Router des pages peut être simplifié en un seul fichier :

app/page.tsx
export default function Page() {
  async function create(formData: FormData) {
    'use server';
    const id = await createItem(formData);
  }
 
  return (
    <form action={create}>
      <input type="text" name="name" />
      <button type="submit">Submit</button>
    </form>
  );
}

Les Server Actions devraient sembler familières aux développeurs ayant déjà utilisé des frameworks centrés serveur par le passé. C'est construit sur des fondamentaux web comme les formulaires et l'API FormData Web.

Bien que l'utilisation des Server Actions via un formulaire soit utile pour l'amélioration progressive, ce n'est pas une obligation. Vous pouvez aussi les appeler directement comme une fonction, sans formulaire. Avec TypeScript, cela vous donne une sécurité de type complète de bout en bout entre le client et le serveur.

La mutation de données, le re-rendu de la page ou la redirection peuvent se faire en un seul aller-retour réseau, garantissant que les bonnes données sont affichées côté client, même si le fournisseur en amont est lent. De plus, vous pouvez composer et réutiliser différentes actions, y compris plusieurs actions différentes dans la même route.

Cache, Revalidation, Redirection et plus

Les Server Actions sont profondément intégrées dans tout le modèle du Router d'application. Vous pouvez :

  • Revalider les données en cache avec revalidatePath() ou revalidateTag()
  • Rediriger vers différentes routes via redirect()
  • Définir et lire les cookies via cookies()
  • Gérer les mises à jour optimistes de l'UI avec useOptimistic()
  • Capturer et afficher les erreurs du serveur avec useFormState()
  • Afficher les états de chargement côté client avec useFormStatus()

Apprenez-en plus sur les Formulaires et Mutations avec Server Actions ou sur le modèle de sécurité et les bonnes pratiques pour les Server Components et Server Actions.

Partial Prerendering (Preview)

Nous souhaitons partager un aperçu du Partial Prerendering — une optimisation du compilateur pour le contenu dynamique avec une réponse statique initiale rapide — sur lequel nous travaillons pour Next.js.

Le Partial Prerendering s'appuie sur une décennie de recherche et développement sur le rendu côté serveur (SSR), la génération de sites statiques (SSG) et la revalidation statique incrémentale (ISR).

Motivation

Nous avons entendu vos retours. Il y a actuellement trop de runtimes, options de configuration et méthodes de rendu à considérer. Vous voulez la vitesse et la fiabilité du statique, tout en supportant des réponses entièrement dynamiques et personnalisées.

Avoir d'excellentes performances globales et de la personnalisation ne devrait pas se faire au prix de la complexité.

Notre défi était de créer une meilleure expérience développeur, simplifiant le modèle existant sans introduire de nouvelles APIs à apprendre. Bien qu'un cache partiel du contenu côté serveur existe déjà, ces approches ne répondent pas encore aux objectifs d'expérience développeur et de composabilité que nous visons.

Le Partial Prerendering ne nécessite aucune nouvelle API à apprendre.

Construit sur React Suspense

Le Partial Prerendering est défini par vos limites Suspense. Voici comment cela fonctionne. Prenons l'exemple de cette page e-commerce :

app/page.tsx
export default function Page() {
  return (
    <main>
      <header>
        <h1>My Store</h1>
        <Suspense fallback={<CartSkeleton />}>
          <ShoppingCart />
        </Suspense>
      </header>
      <Banner />
      <Suspense fallback={<ProductListSkeleton />}>
        <Recommendations />
      </Suspense>
      <NewProducts />
    </main>
  );
}

Avec le Partial Prerendering activé, cette page génère une enveloppe statique basée sur vos limites <Suspense />. Le fallback de React Suspense est prérendu.

Les fallbacks Suspense dans l'enveloppe sont ensuite remplacés par des composants dynamiques, comme la lecture des cookies pour déterminer le panier, ou l'affichage d'une bannière basée sur l'utilisateur.

Lorsqu'une requête est faite, l'enveloppe HTML statique est servie immédiatement :

<main>
  <header>
    <h1>My Store</h1>
    <div class="cart-skeleton">
      <!-- Trou -->
    </div>
  </header>
  <div class="banner" />
  <div class="product-list-skeleton">
    <!-- Trou -->
  </div>
  <section class="new-products" />
</main>

Comme <ShoppingCart /> lit les cookies pour examiner la session utilisateur, ce composant est ensuite streamé dans le cadre de la même requête HTTP que l'enveloppe statique. Aucun aller-retour réseau supplémentaire n'est nécessaire.

app/cart.tsx
import { cookies } from 'next/headers'
 
export default function ShoppingCart() {
  const cookieStore = cookies()
  const session = cookieStore.get('session')
  return ...
}

Pour avoir l'enveloppe statique la plus granulaire, cela peut nécessiter d'ajouter des limites Suspense supplémentaires. Cependant, si vous utilisez déjà loading.js aujourd'hui, c'est une limite Suspense implicite, donc aucune modification ne serait nécessaire pour générer l'enveloppe statique.

Bientôt disponible

Le prérendu partiel est en cours de développement actif. Nous partagerons plus de mises à jour dans une prochaine version mineure.

Améliorations des métadonnées

Avant que le contenu de votre page puisse être streamé depuis le serveur, il y a des métadonnées importantes concernant la viewport, le schéma de couleurs et le thème qui doivent d'abord être envoyées au navigateur.

Assurer que ces balises meta sont envoyées avec le contenu initial de la page permet une expérience utilisateur fluide, évitant les scintillements dus aux changements de couleur de thème ou les décalages de mise en page causés par les modifications de la viewport.

Dans Next.js 14, nous avons découplé les métadonnées bloquantes et non bloquantes. Seul un petit sous-ensemble d'options de métadonnées est bloquant, et nous voulons nous assurer que les métadonnées non bloquantes n'empêcheront pas une page partiellement prérendue de servir l'enveloppe statique.

Les options de métadonnées suivantes sont désormais dépréciées et seront supprimées de metadata dans une future version majeure :

  • viewport : Définit le zoom initial et d'autres propriétés de la viewport
  • colorScheme : Définit les modes de support (clair/sombre) pour la viewport
  • themeColor : Définit la couleur que le chrome autour de la viewport doit utiliser

À partir de Next.js 14, il y a de nouvelles options viewport et generateViewport pour remplacer ces options. Toutes les autres options de metadata restent inchangées.

Vous pouvez commencer à adopter ces nouvelles APIs dès aujourd'hui. Les options existantes de metadata continueront à fonctionner.

Cours Next.js Learn

Aujourd'hui, nous publions un tout nouveau cours gratuit sur Next.js Learn. Ce cours enseigne :

  • Le routeur d'application Next.js
  • Le style et Tailwind CSS
  • L'optimisation des polices et images
  • La création de mises en page et pages
  • La navigation entre les pages
  • La configuration de votre base de données Postgres
  • La récupération de données avec les composants serveur
  • Le rendu statique et dynamique
  • Le streaming
  • Le prérendu partiel (optionnel)
  • L'ajout de recherche et pagination
  • La mutation de données
  • La gestion des erreurs
  • L'amélioration de l'accessibilité
  • L'ajout d'authentification
  • L'ajout de métadonnées

Next.js Learn a enseigné les bases du framework à des millions de développeurs, et nous avons hâte d'entendre vos retours sur notre nouvel ajout. Rendez-vous sur nextjs.org/learn pour suivre le cours.

Autres changements

  • [Cassant] La version minimale de Node.js est maintenant 18.17
  • [Cassant] Suppression de la cible WASM pour la construction next-swc (PR)
  • [Cassant] Abandon du support pour @next/font en faveur de next/font (Codemod)
  • [Cassant] Changement de l'import ImageResponse de next/server vers next/og (Codemod)
  • [Cassant] La commande next export a été supprimée en faveur de la config output: 'export' (Docs)
  • [Dépréciation] onLoadingComplete pour next/image est déprécié en faveur de onLoad
  • [Dépréciation] domains pour next/image est déprécié en faveur de remotePatterns
  • [Fonctionnalité] Un logging plus verbeux autour du cache fetch peut être activé (Docs)
  • [Amélioration] Taille de fonction réduite de 80% pour une application de base create-next-app
  • [Amélioration] Gestion de la mémoire améliorée lors de l'utilisation du runtime edge en développement

Contributeurs

Next.js est le résultat du travail combiné de plus de 2 900 développeurs individuels, de partenaires industriels comme Google et Meta, et de notre équipe principale chez Vercel. Rejoignez la communauté sur GitHub Discussions, Reddit, et Discord.

Cette version vous est proposée par :

Et les contributions de : @05lazy, @0xadada, @2-NOW, @aarnadlr, @aaronbrown-vercel, @aaronjy, @abayomi185, @abe1272001, @abhiyandhakal, @abstractvector, @acdlite, @adamjmcgrath, @AdamKatzDev, @adamrhunter, @ademilter, @adictonator, @adilansari, @adtc, @afonsojramos, @agadzik, @agrattan0820, @akd-io, @AkifumiSato, @akshaynox, @alainkaiser, @alantoa, @albertothedev, @AldeonMoriak, @aleksa-codes, @alexanderbluhm, @alexkirsz, @alfred-mountfield, @alpha-xek, @andarist, @Andarist, @andrii-bodnar, @andykenward, @angel1254mc, @anonrig, @anthonyshew, @AntoineBourin, @anujssstw, @apeltop, @aralroca, @aretrace, @artdevgame, @artechventure, @arturbien, @Aryan9592, @AviAvinav, @aziyatali, @BaffinLee, @Banbarashik, @bencmbrook, @benjie, @bennettdams, @bertho-zero, @bigyanse, @Bitbbot, @blue-devil1134, @bot08, @bottxiang, @Bowens20832, @bre30kra69cs, @BrennanColberg, @brkalow, @BrodaNoel, @Brooooooklyn, @brunoeduardodev, @brvnonascimento, @carlos-menezes, @cassidoo, @cattmote, @cesarkohl, @chanceaclark, @charkour, @charlesbdudley, @chibicode, @chrisipanaque, @ChristianIvicevic, @chriswdmr, @chunsch, @ciruz, @cjmling, @clive-h-townsend, @colinhacks, @colinking, @coreyleelarson, @Cow258, @cprussin, @craigwheeler, @cramforce, @cravend, @cristobaldominguez95, @ctjlewis, @cvolant, @cxa, @danger-ahead, @daniel-web-developer, @danmindru, @dante-robinson, @darshanjain-entrepreneur, @darshkpatel, @davecarlson, @David0z, @davidnx, @dciug, @delbaoliveira, @denchance, @DerTimonius, @devagrawal09, @DevEsteves, @devjiwonchoi, @devknoll, @DevLab2425, @devvspaces, @didemkkaslan, @dijonmusters, @dirheimerb, @djreillo, @dlehmhus, @doinki, @dpnolte, @Drblessing, @dtinth, @ducanhgh, @DuCanhGH, @ductnn, @duncanogle, @dunklesToast, @DustinsCode, @dvakatsiienko, @dvoytenko, @dylanjha, @ecklf, @EndangeredMassa, @eps1lon, @ericfennis, @escwxyz, @Ethan-Arrowood, @ethanmick, @ethomson, @fantaasm, @feikerwu, @ferdingler, @FernandVEYRIER, @feugy, @fgiuliani, @fomichroman, @Fonger, @ForsakenHarmony, @franktronics, @FSaldanha, @fsansalvadore, @furkanmavili, @g12i, @gabschne, @gaojude, @gdborton, @gergelyke, @gfgabrielfranca, @gidgudgod, @Gladowar, @Gnadhi, @gnoff, @goguda, @greatSumini, @gruz0, @Guilleo03, @gustavostz, @hanneslund, @HarshaVardhanReddyDuvvuru, @haschikeks, @Heidar-An, @heyitsuzair, @hiddenest, @hiro0218, @hotters, @hsrvms, @hu0p, @hughlilly, @HurSungYun, @hustLer2k, @iamarpitpatidar, @ianldgs, @ianmacartney, @iaurg, @ibash, @ibrahemid, @idoob, @iiegor, @ikryvorotenko, @imranbarbhuiya, @ingovals, @inokawa, @insik-han, @isaackatayev, @ishaqibrahimbot, @ismaelrumzan, @itsmingjie, @ivanhofer, @IvanKiral, @jacobsfletch, @jakemstar, @jamespearson, @JanCizmar, @janicklas-ralph, @jankaifer, @JanKaifer, @jantimon, @jaredpalmer, @javivelasco, @jayair, @jaykch, @Jeffrey-Zutt, @jenewland1999, @jeremydouglas, @JesseKoldewijn, @jessewarren-aa, @jimcresswell, @jiwooIncludeJeong, @jocarrd, @joefreeman, @JohnAdib, @JohnAlbin, @JohnDaly, @johnnyomair, @johnta0, @joliss, @jomeswang, @joostdecock, @Josehower, @josephcsoti, @josh, @joshuabaker, @JoshuaKGoldberg, @joshuaslate, @joulev, @jsteele-stripe, @JTaylor0196, @JuanM04, @jueungrace, @juliusmarminge, @Juneezee, @Just-Moh-it, @juzhiyuan, @jyunhanlin, @kaguya3222, @karlhorky, @kevinmitch14, @keyz, @kijikunnn, @kikobeats, @Kikobeats, @kleintorres, @koba04, @koenpunt, @koltong, @konomae, @kosai106, @krmeda, @kvnang, @kwonoj, @ky1ejs, @kylemcd, @labyrinthitis, @lachlanjc, @lacymorrow, @laityned, @Lantianyou, @leerob, @leodr, @leoortizz, @li-jia-nan, @loettz, @lorenzobloedow, @lubakravche, @lucasassisrosa, @lucasconstantino, @lucgagan, @LukeSchlangen, @LuudJanssen, @lycuid, @M3kH, @m7yue, @manovotny, @maranomynet, @marcus-rise, @MarDi66, @MarkAtOmniux, @martin-wahlberg, @masnormen, @matepapp, @matthew-heath, @mattpr, @maxleiter, @MaxLeiter, @maxproske, @meenie, @meesvandongen, @mhmdrioaf, @michaeloliverx, @mike-plummer, @MiLk, @milovangudelj, @Mingyu-Song, @mirismaili, @mkcy3, @mknichel, @mltsy, @mmaaaaz, @mnajdova, @moetazaneta, @mohanraj-r, @molebox, @morganfeeney, @motopods, @mPaella, @mrkldshv, @mrxbox98, @nabsul, @nathanhammond, @nbouvrette, @nekochantaiwan, @nfinished, @Nick-Mazuk, @nickmccurdy, @niedziolkamichal, @niko20, @nikolovlazar, @nivak-monarch, @nk980113, @nnnnoel, @nocell, @notrab, @nroland013, @nuta, @nutlope, @obusk, @okcoker, @oliviertassinari, @omarhoumz, @opnay, @orionmiz, @ossan-engineer, @patrick91, @pauek, @peraltafederico, @Phiction, @pn-code, @pyjun01, @pythagoras-yamamoto, @qrohlf, @raisedadead, @reconbot, @reshmi-sriram, @reyrodrigez, @ricardofiorani, @rightones, @riqwan, @rishabhpoddar, @rjsdnql123, @rodrigofeijao, @runjuu, @Ryan-Dia, @ryo-manba, @s0h311, @sagarpreet-xflowpay, @sairajchouhan, @samdenty, @samsisle, @sanjaiyan-dev, @saseungmin, @SCG82, @schehata, @Schniz, @sepiropht, @serkanbektas, @sferadev, @ShaunFerris, @shivanshubisht, @shozibabbas, @silvioprog, @simonswiss, @simPod, @sivtu, @SleeplessOne1917, @smaeda-ks, @sonam-serchan, @SonMooSans, @soonoo, @sophiebits, @souporserious, @sp00ls, @sqve, @sreetamdas, @stafyniaksacha, @starunaway, @steebchen, @stefanprobst, @steppefox, @steven-tey, @suhaotian, @sukkaw, @SukkaW, @superbahbi, @SuttonJack, @svarunid, @swaminator, @swarnava, @syedtaqi95, @taep96, @taylorbryant, @teobler, @Terro216, @theevilhead, @thepatrick00, @therealrinku, @thomasballinger, @thorwebdev, @tibi1220, @tim-hanssen, @timeyoutakeit, @tka5, @tknickman, @tomryanx, @trigaten, @tristndev, @tunamagur0, @tvthatsme, @tyhopp, @tyler-lutz, @UnknownMonk, @v1k1, @valentincostam, @valentinh, @valentinpolitov, @vamcs, @vasucp1207, @vicsantizo, @vinaykulk621, @vincenthongzy, @visshaljagtap, @vladikoff, @wherehows, @WhoAmIRUS, @WilderDev, @Willem-Jaap, @williamli, @wiredacorn, @wiscaksono, @wojtekolek, @ws-jm, @wxh06, @wyattfry, @wyattjoh, @xiaolou86, @y-tsubuku, @yagogmaisp, @yangshun, @yasath, @Yash-Singh1, @yigithanyucedag, @ykzts, @Yovach, @yutsuten, @yyuemii, @zek, @zekicaneksi, @zignis, et @zlrlyy