BackRetour au blog

Next.js 5 : Webpack universel, imports CSS, plugins et zones

Next.js 5 se concentre sur une meilleure extensibilité, une meilleure composition pour les grandes applications et des performances accrues

Nous sommes très heureux de présenter Next.js 5.0 au monde. Il est disponible sur npm dès maintenant. Pour mettre à jour, exécutez :

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

En plus de mettre à jour Next.js, nous mettons à jour les dépendances peer react et react-dom

Next.js est une boîte à outils pour des applications React.js universelles, rendues côté serveur (ou pré-rendues statiquement). Commencer à développer une application de toute taille est aussi simple que d'exécuter next. (En savoir plus.)

Avec chaque nouvelle version, nous nous engageons à maintenir la compatibilité ascendante, à offrir des chemins de mise à jour simples et à ne modifier les API que lorsque cela est absolument nécessaire. Next.js 5.0 ne fait pas exception.

Sous le capot, cependant, Next.js a subi une transformation radicale pour permettre de nouveaux cas d'utilisation puissants et une meilleure extensibilité. Nous avons commencé par faire en sorte que Next.js partage un pipeline Webpack universel pour le code serveur et client.

Webpack universel et plugins Next

Next.js exploite des outils puissants existants comme Webpack, Babel et Uglify, présentés à l'utilisateur final sous une interface remarquablement simple : next (pour développer), next build (pour préparer la production) et next start (pour servir) ou next export pour pré-rendre en fichiers statiques.

L'une des premières décisions que nous avons prises a été de fournir des points d'extensibilité très puissants pour la configuration de ces outils. Nous ne voulions pas seulement de la simplicité d'utilisation, nous voulions permettre la flexibilité d'étendre la boîte à outils comme vous le souhaitez.

Par exemple, vous pouvez étendre la configuration webpack de Next.js en configurant une propriété webpack dans votre next.config.js.

Parce que webpack s'exécute différemment pour la production et le développement, nous avons décidé à l'époque d'en faire une fonction qui décore notre configuration webpack par défaut :

next.config.js
module.exports = {
  webpack(config, { dev }) {
    // modifiez-la !
    return config;
  },
};

Un exemple du fichier optionnel next.config.js

Cependant, Webpack ne s'exécuterait que sur les bundles client (navigateur), et vous manqueriez la possibilité d'utiliser cette excellente chaîne d'outils pour le rendu côté serveur.

Nous sommes heureux d'annoncer que nous avons largement refactorisé notre codebase pour faire fonctionner Webpack de manière universelle.

De votre point de vue, tout ce qui change est qu'une propriété supplémentaire isServer est passée à la fonction de décoration ci-dessus. Cependant, la nouvelle sémantique signifie que le vaste écosystème des loaders Webpack est maintenant disponible pour vous.

CSS, LESS, SASS, SCSS et modules CSS

L'une de nos fonctionnalités les plus demandées est la possibilité d'importer des fichiers CSS et de profiter des loaders Webpack :

import './index.css';
 
export default function Index() {
  return (
    <div>
      <p>J'adore le CSS !</p>
    </div>
  );
}

Une page exemple (pages/index.js) utilisant les imports CSS grâce à Webpack universel

Pour que cela fonctionne, vous pouvez ajouter les loaders dont vous avez besoin comme dépendances peer :

Terminal
npm i --save css-loader style-loader postcss-loader

Next.js vous donne la liberté de choisir les loaders dont vous avez besoin et de les mettre à jour vers différentes versions à volonté.

Et ensuite étendre la configuration pour configurer vos loaders. Dans next.config.js :

next.config.js
module.exports = {
  webpack(config, options) {
    const { dev, isServer } = options;
    const extractCSSPlugin = new ExtractTextPlugin({
      filename: 'static/style.css',
      disable: dev,
    });
    config.module.rules.push({
      test: /\\.css$/,
      use: cssLoaderConfig(extractCSSPlugin, {
        cssModules,
        dev,
        isServer,
      }),
    });
    return config;
  },
};

Étendre la configuration webpack brute vous donne une grande flexibilité et un grand contrôle

Bien que notre recommandation générale soit d'utiliser des solutions de style locales aux composants, comme le plugin babel styled-jsx inclus, nous croyons que les loaders CSS ont de nombreux avantages importants, comme faciliter la réutilisation des bases de code CSS existantes et simplifier grandement la migration des anciennes bases de code vers Next.js.

Au lieu d'activer chaque fonctionnalité et loader concevable par défaut, nous introduisons les plugins Next.js, qui sont des fonctions simples qui décorent votre configuration. Au lieu d'étendre manuellement la configuration pour configurer les loaders comme nous l'avons fait ci-dessus, vous pouvez simplement faire :

const withCss = require('next-css');
module.exports = withCss({
  /* configuration optionnelle supplémentaire */
});

Tout ce qu'il faut pour activer l'import de fichiers .css est d'inclure next-css

En savoir plus sur l'utilisation des CSS Loaders avec Next.JS, ou référez-vous à certains des packages que nous avons déjà créés pour vous :

LoaderPackage
CSSnext-css
LESSnext-less
SASSnext-sass

Notre objectif est de permettre à la communauté de développer et de faire croître un écosystème d'extensions pratiques et simples. À cette fin, nous ouvrons le monorepo next-plugins pour que la communauté Next.js puisse le maintenir. Toutes les PR sont les bienvenues !

Support de TypeScript

L'une des technologies à la croissance la plus rapide dans l'écosystème JavaScript est TypeScript. À tel point qu'il est en train d'être officiellement supporté par Babel 7, ce qui signifie qu'il sera naturellement supporté par Next.js en personnalisant simplement votre .babelrc.

En attendant, grâce à notre nouveau support Webpack universel, vous pouvez déjà obtenir un support complet de TypeScript dès aujourd'hui !

Vous pouvez étendre votre configuration webpack comme ceci :

next.config.js
module.exports = {
  webpack(config, options) {
    const { dir, defaultLoaders } = options;
    config.resolve.extensions.push('.ts', '.tsx');
    config.module.rules.push({
      test: /\\.+(ts|tsx)$/,
      include: [dir],
      exclude: /node_modules/,
      use: [
        defaultLoaders.babel,
        { loader: 'ts-loader', options: { transpileOnly: true } },
      ],
    });
    return config;
  },
};

Tout ce que nous avons à faire est d'activer le ts-loader

Comme les loaders CSS et les pré-processeurs, TypeScript a été l'une des fonctionnalités les plus demandées. Pour faciliter son incorporation dans les projets comme n'importe quel autre loader, nous avons maintenant un plugin next-typescript que vous pouvez inclure dans votre fichier next.config.js :

next.config.js
const withTs = require('next-typescript');
module.exports = withTs({
  /* configuration supplémentaire */
});

Les plugins peuvent être trivialement composés : ce sont juste des fonctions

Meilleur support pour les alternatives à React et le surchargement de modules

De nombreuses implémentations de remplacement de React ont émergé au fil du temps. Parmi elles, certaines notables sont [preact](https://preactjs.com/), nervjs et inferno.

D'autres bibliothèques se concentrent sur le remplacement du moteur de rendu DOM, comme react-dom-lite, qui vise à créer une version plus légère de React en introduisant quelques compromis mineurs dans la compatibilité des navigateurs.

Le support Webpack universel rend le processus d'incorporation de ces bibliothèques comme remplacements encore plus facile. Dans la même veine que les autres plugins, voici tout ce que vous avez à faire pour utiliser Next.js avec preact :

Terminal
npm i @zeit/next-preact preact preact-compat

Nous installons le plugin preact et les dépendances peer nécessaires

const withPreact = require('@zeit/next-preact');
module.exports = withPreact();

Notre nouveau next.config.js prêt pour preact

Découvrez le module très simple @zeit/next-preact ou créez le vôtre !

Cartes sources externes optionnelles en production

Maintenant que Next.js utilise webpack à la fois pour le code client et serveur, activer les cartes sources (source maps) dans les builds de production ne nécessite qu'un petit ajustement de configuration.

En développement, les cartes sources sont automatiquement activées, donc nous les configurons différemment pour la production :

next.config.js
module.exports = {
  webpack(config, { dev }) {
    if (!dev) {
      config.devtool = 'source-map';
    }
    return config;
  },
};

Nous configurons simplement l'option devtool différemment lorsqu'on n'est pas en développement

Zones

L'un des objectifs déclarés de Next.js depuis le début était de ramener et préserver la simplicité du Web.

Le rendu côté serveur (SSR), une approche simple et agnostique pour la récupération de données et les pages déclaratives basées sur la structure du système de fichiers sont quelques-unes des fonctionnalités que nous avons introduites dans cette optique.

Un aspect souvent négligé des services web et des sites web est à quel point ils sont naturellement composables et évolutifs.

Par exemple, mondomaine.com/paramètres et mondomaine.com/ pourraient être deux applications entièrement différentes, déployées indépendamment, évoluant indépendamment, voire exécutant différentes versions du même logiciel.

Tout ce qu'il faut pour les "coller ensemble" en une expérience uniforme pour l'utilisateur final est une simple configuration de la couche de routage backend ou des répartiteurs de charge qui les exposent au monde. Nous sommes très heureux de proposer désormais la capacité de composer plusieurs applications construites avec Next.js, connectées ensemble en utilisant les composants <Link> normaux. Nous appelons cette fonctionnalité Zones.

À titre d'exemple, considérez ces deux applications Next.js indépendantes déployées sur Vercel :

Nos deux pages offrent une expérience transparente, mais elles appartiennent à des applications distinctes

Nos deux pages offrent une expérience transparente, mais elles appartiennent à des applications distinctes

Lorsque nous avons refondu notre documentation, nous voulions rendre l'acceptation des contributions communautaires aussi simple que possible.

Nous avons décidé de séparer le "mini-site" de documentation dans son propre dépôt. De plus, chaque fois qu'une pull-request est soumise et qu'un changement est proposé, nous le déployons automatiquement, isolément :

Chaque fois qu'un changement survient dans une PR, notre bot le déploie automatiquement

Chaque fois qu'un changement survient dans une PR, notre bot le déploie automatiquement

Ce que nous avons obtenu ce sont deux zones, rassemblées sous le domaine parent https://vercel.com en utilisant notre fonctionnalité d'alias de chemin. Cela ressemble à ceci :

{
  "rules": [
    { "pathname": "/docs", "dest": "our-docs.vercel.app" },
    { "pathname": "/api", "dest": "our-docs.vercel.app" },
    { "dest": "my-main-website.vercel.app" }
  ]
}

Ces règles simples vous permettent de composer des microservices et des zones ensemble

Il ne reste plus qu'à invoquer une commande now alias :

Terminal
now alias -r rules.json mon-domaine.com

Notre mission est de rendre le déploiement aussi universel et ouvert que possible. Pour faciliter le développement local, nous avons récemment open sourcé micro-proxy, un outil qui fonctionne avec le même format de configuration vu ci-dessus.

Vous pouvez également assembler des zones avec d'autres solutions comme Nginx, HAProxy ou API Gateway.

Temps de build de production plus rapides

Nous pensons que l'expérience développeur et l'expérience utilisateur vont de pair. Plus les changements peuvent être écrits, testés et déployés efficacement, plus rapidement les nouvelles fonctionnalités sont ajoutées, les bugs corrigés et l'expérience utilisateur globale s'améliore.

Par conséquent, nous restons concentrés sur l'itération continue des performances des briques de base du système.

Avec Next.js 5.0, nous avons eu l'opportunité de reconsidérer next build, la commande que vous exécutez avant de déployer en production ou d'exporter votre application Next.js comme site statique.

Nous sommes heureux d'annoncer que pour vercel.com, une application React composée de milliers de composants, nous avons constaté des améliorations significatives avec Next.js 5.0, avec 23,6 % de temps de build de production en moins :

La build de production de notre application principale prend désormais 38 secondes de moins

La build de production de notre application principale prend désormais 38 secondes de moins

Amélioration du cache pour les imports dynamiques

Chaque fois que vous utilisez un import() dynamique, cela indique à WebPack qu'un nouveau point d'entrée de découpage de code (code-splitting) existe.

Au moment du build, cela signifie générer un bundle spécifique pour le sous-arbre de modules correspondant.

Avant Next.js 5.0, les bundles dynamiques recevaient une URL ressemblant à ceci :

/_next/1517592683901/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6.js

Désormais, nous avons transformé les imports dynamiques en hachages adressables par contenu (content-addressable) du sous-arbre :

/_next/webpack/chunks/components_hello1_1345d10fc951cd6717c5676c467579a6-b7874680a9e21fb6eb89.js

Cela signifie qu'entre les déploiements, vos utilisateurs et clients n'auront pas à retélécharger inutilement le code qu'ils ont déjà utilisé.

Fragments

Next.js construit un composant <Document> de haut niveau qui est rendu côté serveur avec chaque page. Surcharger ce composant vous donne un contrôle total sur votre balisage, permettant de nombreux cas d'usage avancés.

Une partie de ce balisage initial est la liste des scripts que Next.js doit évaluer côté client. Un _document personnalisé ressemble à ceci :

pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document';
export default class extends Document {
  render() {
    return (
      <html>
        <Head />
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Document vous permet de personnaliser l'intégralité du rendu serveur d'une page

Jusqu'à récemment, nous étions obligés d'encapsuler nos scripts dans une <div>.

Avec Next.js 5.0, nous tirons désormais parti du nouveau support des Fragment, ce qui se traduit par des pages plus légères et un contrôle total sur le style de la page, sans balisage superflu.

Erreurs plus précises

Node.js ne supporte pas les cartes sources (source maps), les erreurs qui surviennent côté serveur sont accompagnées d'une trace de pile pointant vers le code compilé.

Avec Next 5, nous avons amélioré le support des cartes sources côté serveur. Les erreurs survenant lors du rendu serveur pointent désormais vers la bonne fonction et le bon numéro de ligne.

Les erreurs affichent désormais la bonne ligne, le bon fichier et le nom de la fonction

Les erreurs affichent désormais la bonne ligne, le bon fichier et le nom de la fonction

Conclusion

Universal Webpack consolide les fondations de Next.js et le rend encore plus pérenne. Globalement, il n'y a plus de séparation artificielle entre les plugins ou loaders applicables à Next.js et ceux qui ne le sont pas.

Dans l'esprit de la configuration zéro, nous sommes ravis de présenter Next Plugins, le dépôt communautaire pour les recettes qui étendent automatiquement les fonctionnalités de Next.js, sans avoir à ajuster des paramètres spécifiques.

Avec cela, nous supportons désormais tout le spectre des solutions CSS, des langages compilés en JS comme TypeScript et des alternatives à React comme Nerve, simplement en ajoutant un module supplémentaire et en étant explicite sur son inclusion dans next.config.js. Simplicité sans obscurité.

Les Zones permettent d'interconnecter des applications Next.js qui ne sont pas ancrées dans le même dépôt ou même sur les mêmes serveurs. Nous considérons cela comme une étape très importante dans la catégorie des améliorations de "scalabilité d'équipe".

Next.js devient ainsi un excellent candidat pour les grandes applications maintenues par plusieurs équipes. Elles peuvent désormais déployer des améliorations simultanément, réduire les surfaces d'erreur, augmenter la vitesse d'itération et même essayer différentes technologies en plus de notre cœur, comme les nombreuses approches de gestion d'état ou de récupération de données.

Nous voulons saisir cette occasion pour remercier Deep Varma et l'équipe d'ingénierie de Trulia pour leurs contributions clés en termes d'idées, de code et de tests qui ont mené à la conception de cette fonctionnalité.

Comme toujours, cette version n'aurait pas été possible sans les nombreux contributeurs open source et notre merveilleuse communauté.