BackRetour au blog

Next.js 9.2

Next.js 9.2 introduit le support natif du CSS, un découpage de code agressif, des routes dynamiques attrape-tout et bien plus encore !

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

Tous ces avantages sont non-breaking et entièrement rétrocompatibles. Pour mettre à jour, il vous suffit d'exécuter :

Terminal
npm i next@latest react@latest react-dom@latest

Support natif des feuilles de style CSS globales

Next.js 5 avait introduit le support de l'import CSS via un plugin custom appelé next-css qui étendait le comportement de Next.js.

Au fil du temps, nous avons reçu des retours constants d'entreprises et d'utilisateurs de Next.js, mentionnant qu'ils finissaient souvent par ajouter next-css à leur application.

De plus, next-css avait quelques contraintes manquantes lors de l'import de CSS. Par exemple, vous pouviez importer un fichier CSS dans chaque fichier du projet, mais ce fichier CSS importé serait global pour toute l'application.

Afin d'améliorer l'expérience développeur et de résoudre ces incohérences, nous avons commencé à travailler sur l'intégration du support des imports CSS directement dans Next.js.

Nous sommes heureux d'annoncer que Next.js dispose maintenant d'un support natif pour importer des feuilles de style dans votre application.

Pour commencer à utiliser les imports CSS dans votre application, importez le fichier CSS dans pages/_app.js.

Par exemple, considérez la feuille de style suivante nommée styles.css à la racine de votre projet :

body {
  padding: 20px 20px 60px;
  margin: 0;
}

Créez un fichier pages/_app.js s'il n'est pas déjà présent.

Puis, importez le fichier styles.css :

pages/_app.js
import '../styles.css';
 
// Cet export par défaut est requis dans un nouveau fichier `pages/_app.js`.
export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

Comme les feuilles de style sont globales par nature, elles doivent être importées dans le composant <App> personnalisé. Ceci est nécessaire pour éviter les conflits de noms de classe et d'ordre pour les styles globaux.

En développement, cette façon d'exprimer les feuilles de style permet à vos styles d'être automatiquement mis à jour sur la page pendant que vous les éditez.

En production, tous les fichiers CSS seront automatiquement concaténés en un seul fichier .css minifié. Ce fichier CSS sera chargé via une balise <link> et automatiquement injecté dans le markup HTML généré par défaut par Next.js.

Cette nouvelle fonctionnalité est entièrement rétrocompatible. Si vous utilisez @zeit/next-css ou d'autres plugins liés au CSS, la fonctionnalité est désactivée pour éviter les conflits.

Si vous utilisez actuellement @zeit/next-css, nous vous recommandons de supprimer le plugin de votre next.config.js et package.json, passant ainsi au support CSS natif lors de la mise à jour.

Support natif des modules CSS pour les styles au niveau composant

Next.js supporte maintenant les modules CSS en utilisant la convention de nommage [name].module.css.

Contrairement au support précédemment disponible dans Next.js 5 avec next-css, le CSS global et les modules CSS peuvent maintenant coexisternext-css nécessitait que tous les fichiers .css de votre application soient traités comme globaux ou locaux, mais pas les deux.

Les modules CSS limitent la portée du CSS en créant automatiquement des noms de classe uniques. Cela vous permet d'utiliser le même nom de classe CSS dans différents fichiers sans craindre de collisions.

Ce comportement fait des modules CSS le moyen idéal pour inclure du CSS au niveau composant. Les fichiers de modules CSS peuvent être importés n'importe où dans votre application.

Par exemple, considérez un composant réutilisable Button dans le dossier components/ :

D'abord, créez components/Button.module.css avec le contenu suivant :

/*
Vous n'avez pas à vous soucier que .error {} entre en conflit avec d'autres fichiers
`.css` ou `.module.css` !
*/
.error {
  color: white;
  background-color: red;
}

Puis, créez components/Button.js, en important et utilisant le fichier CSS ci-dessus :

components/Button.js
import styles from './Button.module.css';
 
export function Button() {
  return (
    <button
      type="button"
      // Notez comment la classe "error" est accessible comme une propriété de l'objet
      // `styles` importé.
      className={styles.error}
    >
      Destroy
    </button>
  );
}

Les modules CSS sont une fonctionnalité optionnelle et ne sont activés que pour les fichiers avec l'extension .module.css. Les feuilles de style <link> classiques et les fichiers CSS globaux sont toujours supportés.

En production, tous les fichiers de modules CSS sont automatiquement concaténés en plusieurs fichiers .css minifiés et découpés. Ces fichiers .css représentent les chemins d'exécution critiques de votre application, garantissant que la quantité minimale de CSS est chargée par page pour que votre application s'affiche.

Comme ci-dessus, cette nouvelle fonctionnalité est entièrement rétrocompatible. Si vous utilisez @zeit/next-css ou d'autres plugins liés au CSS, la fonctionnalité est désactivée pour éviter les conflits.

Si vous utilisez actuellement @zeit/next-css, nous vous recommandons de supprimer le plugin de votre next.config.js et package.json, passant ainsi au support CSS natif.

Stratégie améliorée de découpage de code

Les versions de Next.js antérieures à 9.2 avaient un ensemble fixe de bundles JavaScript requis pour charger et rendre une page interactive :

  • Le fichier JavaScript de la page
  • Un fichier avec le JavaScript commun
  • Le bundle runtime client-side de Next.js
  • Le bundle runtime client-side de Webpack
  • Les imports dynamiques (ajoutés via next/dynamic, quand utilisés)

Pour rendre la page interactive, tous ces bundles doivent être chargés car ils dépendent les uns des autres pour démarrer React dans le navigateur.

Comme tous ces bundles sont nécessaires pour que l'application devienne interactive, il est important qu'ils soient aussi optimisés que possible. En pratique, cela signifie ne pas télécharger excessivement du code provenant d'autres parties de l'application.

Pour cette raison, Next.js utilisait un bundle commons qui contenait le JavaScript commun entre les pages. Le calcul de l'ancienne stratégie de découpage pour générer commons était une heuristique basée sur un ratio d'utilisation. Si un module était utilisé dans plus de 50% de toutes les pages, il était marqué comme module commun. Sinon, il était inclus dans le fichier JavaScript de la page.

Cependant, les applications peuvent être composées de nombreux types de pages différents. Par exemple, des pages marketing, un blog et un tableau de bord. S'il y avait un grand nombre de pages marketing comparé aux autres types de pages, le calcul des commons résultait en des optimisations fortement concentrées sur les pages marketing.

Notre objectif est d'optimiser pour tous les types de pages, dans une seule application.

Alex Castle a proposé une nouvelle méthode de chunking (création de fichiers JavaScript séparés) qui permet un chunking optimisé des commons avec plusieurs fichiers, y compris quand de nombreux types de pages sont impliqués.

Aujourd'hui, nous sommes heureux d'annoncer que ce nouveau comportement de chunking est activé par défaut dans Next.js 9.2. Nous tenons à exprimer notre profonde gratitude à l'équipe Google Chrome et à Alex Castle pour avoir contribué à ce changement. Ce changement reflète l'effort cumulé de semaines de recherche, tests en laboratoire, tests en conditions réelles et implémentation.

La nouvelle implémentation de chunking tire parti de HTTP/2 pour fournir un plus grand nombre de chunks de plus petite taille.

Sous la nouvelle heuristique, les chunks sont créés pour :

  • Un chunk minimal pour chaque page.
  • Un chunk framework contenant React, ReactDOM, le Scheduler de React, etc.
  • Des chunks library pour toute dépendance node_module supérieure à 160kb (avant minification/gzip)
  • Un chunk commons pour le code utilisé sur toutes les pages.
  • Autant de chunks partagés (utilisés par 2 pages ou plus) que possible, optimisant pour la taille globale de l'application et la vitesse de chargement initial.
  • Le runtime client-side de Next.js.
  • Le runtime Webpack.

Voyons ce que cela signifie dans une application réelle :

Un partenaire industriel early-adopter, Barnebys®, a vu une diminution de 23% de la taille globale de son application.

De plus, leur plus gros bundle JS a été réduit de 30% — de 605kB à 425kB — sans aucun changement de code requis.

Un autre partenaire industriel, SumUp®, a vu une diminution de 70% de leur plus gros bundle JS — de 395kB à 122kB — sans aucun changement de code requis.

Plus gros bundle JavaScript

AvantAprèsDelta
Barnebys605kB425kB30% plus petit
SumUp395kB122kB70% plus petit

Le nouveau comportement de chunking réduit non seulement la taille globale et de chargement initial, mais aussi les navigations client-side successives. Barnebys® a vu une réduction de 87% de la quantité de JavaScript chargée après six (6) navigations de page :

JavaScript chargé par plusieurs transitions client-side

AvantAprèsDelta
Barnebys136kB18kB87% plus petit

Ce nouveau comportement est entièrement rétrocompatible. Mettre à jour vers la dernière version de Next.js est tout ce que vous avez à faire pour bénéficier de cette amélioration de performance.

Routes dynamiques attrape-tout

Avec la sortie de Next.js 9, nous avions introduit les segments de route dynamiques avec pour objectif de simplifier les segments dynamiques dans Next.js sans avoir besoin d'un serveur custom. Cette fonctionnalité a été massivement adoptée par les utilisateurs de Next.js.

Il restait cependant certains cas que la fonctionnalité de segments de route dynamiques ne couvrait pas.

Un de ces cas était les routes attrape-tout. Par exemple, router un wildcard comme /post/** comme page. Ceci est particulièrement utile quand vous avez une structure imbriquée définie par une source de contenu comme un CMS.

Vous pouvez maintenant créer des routes dynamiques attrape-tout en utilisant la syntaxe [...name].

Par exemple, pages/post/[...slug].js correspondra à /post/a, /post/a/b, /post/a/b/c, etc.

slug sera fourni dans l'objet query du routeur comme un tableau de parties individuelles du chemin. Ainsi, pour le chemin /post/foo/bar, l'objet query sera { slug: ['foo', 'bar'] }.

Communauté

Nous sommes très enthousiastes de voir l'adoption de Next.js continuer à croître :

  • Nous avons eu plus de 880 contributeurs indépendants.
  • Sur GitHub, le projet a été star plus de 44 000 fois.
  • Le répertoire d'exemples contient plus de 220 exemples.

La communauté Next.js compte maintenant plus de 13 800 membres. Rejoignez-nous !

Nous sommes reconnaissants envers notre communauté et tous les retours et contributions externes qui ont aidé à façonner cette release.