BackRetour au blog

Next.js 9.5

Next.js 9.5 introduit la Régénération Statique Incrémentielle Stable, le Chemin de Base Personnalisable, les Redirections et Réécritures, Webpack 5 en version bêta, et bien plus encore !

Nous sommes ravis de vous présenter aujourd'hui Next.js 9.5, qui inclut :

Régénération Statique Incrémentielle Stable

Next.js a introduit les méthodes de Génération de Site Statique dans la version 9.3 avec un objectif clair en tête : nous devrions obtenir les avantages du statique (toujours rapide, toujours en ligne, répliqué globalement), mais avec un excellent support pour les données dynamiques, pour lesquelles Next.js est connu.

Pour obtenir le meilleur des deux mondes, Next.js a introduit la Génération Statique Incrémentielle, mettant à jour le contenu statique après avoir déjà construit votre site. En utilisant l'option fallback: true dans getStaticPaths, vous pouvez enregistrer de nouvelles pages statiques à l'exécution.

Next.js peut ainsi pré-rendre statiquement un nombre infini de pages, à la demande, quelle que soit la taille de votre ensemble de données.

Aujourd'hui, nous annonçons la disponibilité générale de la Re-génération Statique Incrémentielle, qui est un mécanisme pour mettre à jour des pages existantes, en les re-rendant en arrière-plan lors de l'arrivée du trafic.

Inspiré par stale-while-revalidate, la régénération en arrière-plan garantit que le trafic est servi sans interruption, toujours à partir du stockage statique, et que la nouvelle page construite est poussée uniquement après avoir fini de se générer.

export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // nous tenterons de re-générer la page :
    // - lorsqu'une requête arrive
    // - au maximum une fois par seconde
    revalidate: 1,
  };
}

Le flag revalidate est le nombre de secondes pendant lesquelles au maximum une génération aura lieu, pour éviter un https://en.wikipedia.org/wiki/Cache_stampede.

Contrairement au SSR traditionnel, la Régénération Statique Incrémentielle garantit que vous conservez les avantages du statique :

  • Pas de pics de latence. Les pages sont servies de manière constante et rapide.
  • Les pages ne tombent jamais hors ligne. Si la re-génération de page en arrière-plan échoue, l'ancienne page reste inchangée.
  • Faible charge sur la base de données et le backend. Les pages sont re-calculées au maximum une fois `concurrentiellement.

Les deux fonctionnalités incrémentielles (ajout de pages et mise à jour différée), ainsi que le mode prévisualisation, sont maintenant stables et déjà entièrement supportés à la fois par next start et la plateforme edge de Vercel dès maintenant.

Pour illustrer cette nouvelle fonctionnalité, nous avons créé un exemple montrant la re-génération d'une page statique qui affiche le compte des différentes réactions GitHub d'un problème spécifique : https://reactions-demo.vercel.app/

Après la première visite suivant notre réaction emoji, une nouvelle génération de page démarre en arrière-plan. Chaque requête est servie à partir du cache statique.

Après la première visite suivant notre réaction emoji, une nouvelle génération de page démarre en arrière-plan. Chaque requête est servie à partir du cache statique.

Prochainement, nous travaillerons sur un RFC complémentaire pour aborder deux capacités supplémentaires de génération statique incrémentielle :

  • Re-générer et invalider plusieurs pages à la fois (comme votre index de blog et un certain article de blog)
  • Re-générer en écoutant des événements (comme les webhooks d'un CMS), avant le trafic utilisateur

Pour plus de détails, consultez la documentation de getStaticProps.

Chemin de Base Personnalisable

Les projets Next.js ne sont pas toujours servis depuis la racine d'un domaine. Parfois, vous pourriez vouloir héberger votre projet Next.js sous un sous-chemin comme /docs afin que le projet Next.js ne couvre que cette sous-section du domaine.

Bien que cela ait été possible jusqu'à présent, c'était au prix d'une configuration supplémentaire assez importante. Par exemple, ajouter le préfixe à chaque <Link> et s'assurer que Next.js servait les bundles JavaScript depuis le bon chemin.

Pour résoudre ce problème, nous introduisons une nouvelle option de configuration. basePath vous permet d'héberger facilement votre projet Next.js sur un sous-chemin de votre domaine.

Pour commencer à utiliser basePath, vous pouvez l'ajouter à next.config.js :

next.config.js
module.exports = {
  basePath: '/docs',
};

Après avoir configuré le basePath, votre projet sera automatiquement routé depuis le chemin fourni. Dans ce cas, /docs.

Lors de la liaison vers d'autres pages du projet avec next/link ou next/router, le basePath sera automatiquement préfixé. Cela vous permet de changer le basePath sans modifier votre projet.

Un exemple de cela serait l'utilisation de next/link pour router vers une autre page :

import Link from 'next/link';
 
export default function HomePage() {
  return (
    <>
      <Link href="/documentation-page">
        <a>Page de documentation</a>
      </Link>
    </>
  );
}

L'utilisation de next/link de cette manière donnera le HTML suivant rendu dans le navigateur web :

<a href="/docs/documentation-page">Page de documentation</a>

Pour plus de détails, consultez la documentation de basePath.

Prise en charge des Réécritures, Redirections et En-têtes

Réécritures

Lors de la construction d'un projet Next.js, vous pourriez vouloir proxifier certaines routes vers une autre URL. Par exemple, si vous souhaitez adopter progressivement Next.js dans votre stack, vous voudriez router les pages qui existent dans votre projet Next.js et ensuite tout ce qui n'a pas été matché vers l'ancien projet que vous migrez.

Avec Next.js 9.5, nous introduisons une nouvelle option de configuration nommée rewrites, qui vous permet de mapper un chemin de requête entrant vers un chemin de destination différent, y compris des URLs externes.

Par exemple, vous pourriez vouloir réécrire une certaine route vers example.com :

next.config.js
module.exports = {
  async rewrites() {
    return [
      { source: '/backend/:path*', destination: 'https://example.com/:path*' },
    ];
  },
};

Dans ce cas, tous les chemins sous /backend seraient routés vers example.com.

Vous pouvez également vérifier si les routes de votre projet Next.js correspondent, puis réécrire vers le projet précédent s'il n'y a pas de correspondance. Ceci est incroyablement utile pour l'adoption incrémentielle de Next.js :

module.exports = {
  async rewrites() {
    return [
      // vérifier si les routes du projet Next.js correspondent avant de tenter le proxying
      {
        source: '/:path*',
        destination: '/:path*',
      },
      {
        source: '/:path*',
        destination: `https://example.com/:path*`,
      },
    ];
  },
};

Dans ce cas, nous matchons d'abord tous les chemins. Si aucun ne correspond, nous proxifions vers example.com qui serait le projet précédent.

Pour en savoir plus sur la fonctionnalité rewrites, consultez la documentation des réécritures.

Redirections

La plupart des sites web ont besoin d'au moins quelques redirections. Surtout lors du changement de la structure des routes de votre projet. Par exemple, lors du passage de /blog à /news ou des transitions similaires.

Auparavant, avoir une liste de redirections dans votre projet Next.js nécessitait la configuration d'un serveur personnalisé ou d'une page _error personnalisée pour vérifier s'il y avait des redirections définies pour la route. Cependant, cela se faisait au détriment de l'invalidation des optimisations statiques et serverless clés (en ayant un serveur) ou n'était pas assez ergonomique.

À partir de Next.js 9.5, vous pouvez maintenant créer une liste de redirections dans next.config.js sous la clé redirects :

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
    ];
  },
};

Pour en savoir plus sur la fonctionnalité redirects, consultez la documentation des redirections.

En-têtes (Headers)

Next.js vous permet de créer des projets hybrides utilisant à la fois la Génération Statique (Static Generation) et le Rendu côté serveur (Server-Side Rendering). Avec le rendu côté serveur, vous pouvez définir des en-têtes pour les requêtes entrantes. Pour les pages statiques, la définition d'en-têtes n'était pas possible jusqu'à présent.

Nous avons maintenant introduit une propriété headers dans next.config.js qui s'applique à toutes les routes Next.js :

next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'Feature-Policy',
            // Désactive le microphone et la géolocalisation
            value: "microphone 'none'; geolocation 'none'",
          },
        ],
      },
    ];
  },
};

L'option headers vous permet de définir des en-têtes couramment nécessaires comme Feature-Policy et Content-Security-Policy.

Pour en savoir plus sur la fonctionnalité headers, consultez la documentation sur les en-têtes.

Barre oblique finale optionnelle dans les URL (Optional Trailing Slash in URLs)

Lorsque Next.js a été introduit il y a 3 ans, son comportement par défaut était que toutes les URL avec une barre oblique finale renvoient toujours une page 404.

Bien qu'efficace, certains utilisateurs ont demandé la possibilité de modifier ce comportement. Par exemple, lors de la migration d'un projet existant vers Next.js qui imposait auparavant toujours des barres obliques finales.

Avec Next.js 9.5, nous avons introduit une nouvelle option appelée trailingSlash dans next.config.js.

Cette nouvelle option garantit que Next.js gère automatiquement le comportement de la barre oblique finale :

  • Redirige automatiquement les URL avec barre oblique finale vers l'URL sans la barre oblique, par exemple : /about/ vers /about
  • Lorsque trailingSlash est défini sur true, l'URL sans barre oblique sera redirigée vers l'URL avec une barre oblique, par exemple : /about vers /about/
  • Garantit que next/link applique/supprime automatiquement la barre oblique pour éviter des redirections inutiles.
next.config.js
module.exports = {
  // Force une barre oblique finale, la valeur par défaut est sans barre oblique (false)
  trailingSlash: true,
};

Pour en savoir plus sur la fonctionnalité trailingSlash, consultez la documentation sur trailingSlash

Mise en cache persistante des bundles de pages (Persistent Caching for Page Bundles)

Lors de l'écriture de pages Next.js, la création de tous les bundles de scripts, feuilles de style CSS et HTML est entièrement automatique et abstraite pour vous. Si vous inspectez les balises <script> générées avant Next.js 9.5, vous remarquerez que leurs URL suivent un modèle comme celui-ci :

/_next/static/ovgxWYrvKyjnlM15qtz7h/pages/about.js

Le segment de chemin ovgxWYrvKyjnlM15qtz7h ci-dessus est ce que nous appelions l'ID de build. Bien que ces fichiers étaient facilement mis en cache au niveau du edge et sur la machine de l'utilisateur, après une reconstruction de votre application, l'ID de build changeait et tous les caches étaient invalidés.

Pour la plupart des projets, ce compromis était acceptable, mais nous voulions optimiser encore ce comportement en ne invalidant plus le cache du navigateur pour les pages qui n'avaient pas été modifiées.

L'introduction de la stratégie améliorée de découpage de code dans Next.js 9.2, développée en collaboration avec l'équipe Google Chrome, a posé les bases de ces améliorations pour la génération de bundles de pages Next.js.

À partir de Next.js 9.5, tous les bundles JavaScript de pages utiliseront des hachages de contenu au lieu de l'ID de build. Cela permet aux pages qui n'ont pas changé entre les déploiements de rester dans le cache du navigateur et du edge sans avoir besoin d'être téléchargées à nouveau.

En revanche, le modèle d'URL après ces modifications ressemble à quelque chose comme :

/_next/static/chunks/pages/about.qzfS4o5gIEXRME6sTEahL.js

Au lieu d'un ID de build global, la partie qzfS4o5gIEXRME6sTEahL est un hachage déterministe du bundle about.js, qui sera stable tant que le code de cette section de votre site ne change pas. De plus, il est maintenant mis en cache à long terme entre les redéploiements via Cache-Control: public,max-age=31536000,immutable que Next.js définit automatiquement pour vous.

Améliorations du Fast Refresh (Fast Refresh Enhancements)

Nous avons introduit le Fast Refresh dans Next.js 9.4, une nouvelle expérience de rechargement à chaud qui vous donne un retour instantané sur les modifications apportées à vos composants React.

Next.js 9.5 affine davantage notre implémentation du Fast Refresh et vous donne les outils dont vous avez besoin pour réussir :

  • Erreurs faciles à comprendre : Toutes les erreurs de compilation et d'exécution ont été mises à jour pour ne montrer que les informations pertinentes, y compris un cadre de code (code frame) du code ayant causé l'erreur.
  • Conseils de développement pour conserver l'état du composant : Next.js vous fournit maintenant des conseils utiles pour garantir que le Fast Refresh conservera l'état de votre composant dans autant de scénarios que possible. Chaque conseil fourni par Next.js est entièrement actionnable et accompagné d'un exemple avant et après !
  • Avertissements lorsque l'état du composant est réinitialisé : Nous afficherons maintenant un avertissement détaillé lorsque Next.js ne peut pas conserver l'état du composant après la modification d'un fichier. Cet avertissement vous aidera à diagnostiquer pourquoi le projet a dû réinitialiser l'état du composant, vous permettant de le corriger et d'utiliser le Fast Refresh à son plein potentiel.
  • Nouvelle documentation : Nous avons ajouté une documentation détaillée qui explique ce qu'est le Fast Refresh, comment il fonctionne et à quoi s'attendre ! La documentation vous apprendra également à mieux tirer parti du Fast Refresh en expliquant comment fonctionne sa récupération d'erreurs.
  • Guide de dépannage pour le code utilisateur : La nouvelle documentation comprend également des étapes de dépannage courantes et des conseils sur la façon de tirer le meilleur parti du Fast Refresh en développement.

Profilage React en production (Production React Profiling)

React a introduit l'API Profiler il y a quelque temps, ce qui vous permet de détecter les problèmes de performance dans vos composants React. Bien que cette fonctionnalité fonctionne automatiquement en développement, elle nécessite une version séparée de ReactDOM pour être utilisée en production.

Avec Next.js 9.5, vous pouvez maintenant activer le profilage React en production avec le flag --profile dans next build :

next build --profile

Après cela, vous pouvez utiliser le profileur de la même manière qu'en développement.

Pour en savoir plus sur le profilage React, vous pouvez lire l'article sur le profileur React par l'équipe React. Un grand merci à TODOrTotev et @darshkpatel pour avoir contribué à cette fonctionnalité.

Routes attrape-tout optionnelles (Optional Catch All Routes)

Next.js 9.2 a ajouté la prise en charge des routes dynamiques attrape-tout (catch-all dynamic routes) qui ont été largement adoptées par la communauté pour divers cas d'utilisation. Les routes attrape-tout vous offrent la flexibilité de créer des structures de routage hautement dynamiques alimentées par des CMS Headless, des API GraphQL, des systèmes de fichiers, etc.

En écoutant les retours, nous avons entendu que les utilisateurs souhaitaient avoir encore plus de flexibilité pour correspondre au niveau racine d'une route. Aujourd'hui, nous sommes heureux de dévoiler les routes dynamiques attrape-tout optionnelles pour ces scénarios avancés.

Pour créer une route attrape-tout optionnelle, vous pouvez créer une page en utilisant la syntaxe [[...slug]].

Par exemple, pages/blog/[[...slug]].js correspondra à /blog, ainsi qu'à toute route en dessous, comme : /blog/a, /blog/a/b/c, etc.

Comme pour les routes attrape-tout, slug sera fourni dans l'objet de requête du routeur sous forme de tableau de parties de chemin. Ainsi, pour le chemin /blog/foo/bar, l'objet de requête sera { slug: ['foo', 'bar'] }. Pour le chemin /blog, l'objet de requête omettra la clé slug : { }.

Vous pouvez en savoir plus sur les routes attrape-tout optionnelles dans notre documentation.

Support de Webpack 5 (bêta) (Webpack 5 Support (beta))

Webpack 5 est actuellement en version bêta. Il inclut quelques améliorations majeures :

Nous sommes ravis d'annoncer aujourd'hui la disponibilité bêta de webpack 5 pour Next.js.

Pour essayer webpack 5, vous pouvez utiliser Yarn resolutions dans votre package.json :

package.json
{
  "resolutions": {
    "webpack": "^5.0.0-beta.30"
  }
}

La bêta de Webpack 5 a déjà été déployée en production sur nextjs.org et vercel.com. Nous vous encourageons à l'essayer de manière progressive et à nous faire part de vos retours sur GitHub.

Améliorations de l'infrastructure de compilation (Compilation infrastructure improvements)

Pour supporter webpack 5, nous avons réécrit une grande partie du pipeline de compilation pour qu'il soit plus adapté à Next.js :

  • Next.js ne dépend plus de webpack-hot-middleware et webpack-dev-middleware, nous utilisons maintenant webpack directement et optimisons spécifiquement pour les projets Next.js. Cela se traduit par une architecture plus simple et une compilation de développement plus rapide.
  • On-demand-entries, qui est le système que Next.js utilise pour compiler les pages que vous visitez à un moment donné pendant le développement, a également été réécrit et est maintenant encore plus fiable en tirant parti du nouveau comportement de webpack spécifiquement adapté à notre cas d'utilisation.
  • React Fast Refresh et l'overlay d'erreur Next.js sont maintenant entièrement compatibles avec webpack 5
  • Le cache disque sera activé dans une future version bêta.

Compatibilité ascendante (Backwards compatibility)

Nous nous engageons toujours à garantir que Next.js est compatible avec les versions précédentes.

Webpack 4 continuera à être entièrement pris en charge. Nous travaillons en étroite collaboration avec l'équipe webpack pour garantir que la migration de webpack 4 à 5 soit aussi fluide que possible.

Si votre projet Next.js n'a pas de configuration webpack personnalisée, aucune modification de projet ne sera nécessaire pour tirer pleinement parti de webpack 5.

Important : si votre projet a une configuration webpack personnalisée, certaines modifications pourraient être nécessaires pour passer à webpack 5. Nous vous recommandons de surveiller nos instructions de migration ou de minimiser votre utilisation des extensions webpack pour des mises à niveau futures transparentes.

Amélioration de la surveillance des fichiers sur macOS (Improved file watching on macOS)

Nous avons récemment découvert un problème avec webpack où la surveillance des fichiers sur macOS s'arrêtait après quelques modifications de votre code. Vous deviez redémarrer votre projet manuellement pour voir les mises à jour. Après quelques modifications, le cycle se répétait.

De plus, nous avons constaté que ce problème ne se produisait pas seulement dans les projets Next.js mais dans tous les projets et frameworks basés sur webpack.

Après plusieurs jours de débogage, nous avons identifié la cause racine comme étant l'implémentation de la surveillance des fichiers utilisée par webpack appelée chokidar, qui est une implémentation largement utilisée dans l'écosystème Node.js.

Nous avons envoyé un correctif à chokidar pour résoudre le problème. Après la sortie du correctif, nous avons travaillé avec Tobias Koppers pour déployer ce correctif dans une nouvelle version de webpack.

Cette version corrigée de webpack est automatiquement utilisée lorsque vous mettez à jour vers Next.js 9.5.

Conclusion

Nous sommes ravis de voir la croissance continue de l'adoption de Next.js :

  • Nous avons eu plus de 1 200 contributeurs indépendants, avec plus de 135 nouveaux contributeurs depuis la version 9.4.
  • Sur GitHub, le projet a été mis en favoris plus de 51 100 fois.

Rejoignez la communauté Next.js sur GitHub Discussions. Discussions est un espace communautaire qui vous permet de vous connecter avec d'autres utilisateurs de Next.js et de poser librement des questions ou de partager votre travail.

Par exemple, vous pourriez commencer par partager l'URL de votre projet avec tout le monde.

Si vous souhaitez contribuer mais ne savez pas comment, nous vous encourageons à essayer des fonctionnalités expérimentales comme notre support Webpack et à nous faire part de vos retours !

Crédits (Credits)

Nous remercions notre communauté, y compris tous les retours externes et contributions qui ont aidé à façonner cette version.

Un grand merci à Jan Potoms, un membre de longue date de la communauté Next.js qui a contribué à plusieurs fonctionnalités de cette version.

Un grand merci à Tobias Koppers, l'auteur de webpack, qui a aidé à intégrer le support de webpack 5 dans Next.js.

Cette version a été rendue possible grâce aux contributions de : @chandan-reddy-k, @Timer, @aralroca, @artemisart, @sospedra, @prateekbh, @Prioe, @Janpot, @merceyz, @ijjk, @PavelK27, @marbiano, @MichelleLucero, @thorsten-stripe, @TODOrTotev, @Skn0tt, @lfades, @timneutkens, @akhila-ariyachandra, @chibicode, @rafaelalmeidatk, @kirill-konshin, @jamesvidler, @JeffersonBledsoe, @tylev, @jamesmosier, @filipemarins, @Remeic, @vvo, @timothyis, @jazibsawar, @coetry, @adam-zacharski, @danwilliams, @tywmick, @matamatanot, @goldins, @mvllow, @its-tayo, @sshyam-gupta, @wilbert-abreu, @sebastianbenz, @jaydenseric, @developit, @dylanjha, @darshkpatel, @spinks, @stefanprobst, @moh12594, @jasonmerino, @cristiand391, @HyunSangHan, @mcsdevv, @M1ck0, @hydRAnger, @alexej-d, @valmassoi, @motleydev, @eKhattak, @jpedroschmitz, @JerryGoyal, @bowen31337, @phillip055, @balazsorban44, @chuabingquan, @youhosi, @andresz1, @bell-steven, @areai51, @Wssn, @ndom91, @anthonyshort, @zxzl, @jbowes, @IamLizu, @PascalPixel, @ralphilius, @ysun62, @muslax, @elsigh, @AsherFoster, @botv, @tomdohnal, @christianalfoni, @tomasztunik, @gsimone, @illuminist, @jplew, @OskarKaminski, @RickyAbell, @steph-query, @ericgoe, @MalvinJay, @cristianbote, @Ashikpaul, @jensmeindertsma, @amorriscode, @abhik-b, @awareness481, @LukasPolak, @arvigeus, @romMidnight, @jackyef, @drumm2k, @kuldeepkeshwar, @bogy0, @Belco90, @wawjr3d, @tanmaylaud, @SarKurd, @kevinsproles, @dstotijn, @styfle, @blackwright, @BrunoBernardino, @heyAyushh, @Necmttn, @TrySound, @obedparla, @NyashaNziramasanga, @tonyspiro, @kukicado, @ceorourke, @MehediH, @robintom, @karlhorky, et @tcK1 !