Mise à niveau vers la version 9

Pour effectuer la mise à niveau vers la version 9, exécutez la commande suivante :

Terminal
npm install next@9

yarn add next@9

Déploiement en production sur Vercel

Si vous aviez configuré des routes dans votre fichier vercel.json pour des routes dynamiques, ces règles peuvent être supprimées en profitant de la nouvelle fonctionnalité de routage dynamique de Next.js 9.

Les routes dynamiques de Next.js 9 sont configurées automatiquement sur Vercel et ne nécessitent aucune personnalisation dans vercel.json.

Vous pouvez en apprendre plus sur le routage dynamique ici.

Vérifiez votre fichier d'application personnalisée (pages/_app.js)

Si vous aviez précédemment copié l'exemple de l'application personnalisée <App>, vous pourrez peut-être supprimer votre getInitialProps.

Supprimer getInitialProps de pages/_app.js (quand c'est possible) est important pour profiter des nouvelles fonctionnalités de Next.js !

Le getInitialProps suivant ne fait rien et peut être supprimé :

class MyApp extends App {
  // Supprimez-moi, je ne sers à rien !
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx)
    }

    return { pageProps }
  }

  render() {
    // ... etc
  }
}

Changements cassants

@zeit/next-typescript n'est plus nécessaire

Next.js ignorera désormais l'utilisation de @zeit/next-typescript et vous avertira de le supprimer. Veuillez retirer ce plugin de votre next.config.js.

Supprimez les références à @zeit/next-typescript/babel de votre .babelrc personnalisé (si présent).

L'utilisation de fork-ts-checker-webpack-plugin doit également être supprimée de votre next.config.js.

Les définitions TypeScript sont maintenant publiées avec le package next, donc vous devez désinstaller @types/next car ils entreraient en conflit.

Les types suivants ont changé :

Cette liste a été créée par la communauté pour vous aider à effectuer la mise à niveau. Si vous trouvez d'autres différences, merci d'envoyer une pull-request pour aider les autres utilisateurs.

De :

import { NextContext } from 'next'
import { NextAppContext, DefaultAppIProps } from 'next/app'
import { NextDocumentContext, DefaultDocumentIProps } from 'next/document'

Vers :

import { NextPageContext } from 'next'
import { AppContext, AppInitialProps } from 'next/app'
import { DocumentContext, DocumentInitialProps } from 'next/document'

La clé config est maintenant une exportation au niveau de la page

Vous ne pouvez plus exporter une variable personnalisée nommée config depuis une page (c'est-à-dire export { config } / export const config ...). Cette variable exportée est maintenant utilisée pour spécifier la configuration Next.js au niveau de la page, comme les fonctionnalités AMP opt-in et les routes API.

Vous devez renommer toute exportation config qui n'est pas destinée à Next.js.

next/dynamic n'affiche plus "loading..." par défaut pendant le chargement

Les composants dynamiques n'afficheront plus rien par défaut pendant le chargement. Vous pouvez toujours personnaliser ce comportement en définissant la propriété loading :

import dynamic from 'next/dynamic'

const DynamicComponentWithCustomLoading = dynamic(
  () => import('../components/hello2'),
  {
    loading: () => <p>Chargement</p>,
  }
)

withAmp a été supprimé au profit d'un objet de configuration exporté

Next.js a maintenant le concept de configuration au niveau de la page, donc le composant d'ordre supérieur withAmp a été supprimé pour plus de cohérence.

Cette modification peut être automatiquement migrée en exécutant les commandes suivantes à la racine de votre projet Next.js :

Terminal
curl -L https://github.com/vercel/next-codemod/archive/master.tar.gz | tar -xz --strip=2 next-codemod-master/transforms/withamp-to-config.js npx jscodeshift -t ./withamp-to-config.js pages/**/*.js

Pour effectuer cette migration manuellement, ou voir ce que le codemod produira, consultez ci-dessous :

Avant

import { withAmp } from 'next/amp'

function Home() {
  return <h1>Ma page AMP</h1>
}

export default withAmp(Home)
// ou
export default withAmp(Home, { hybrid: true })

Après

export default function Home() {
  return <h1>Ma page AMP</h1>
}

export const config = {
  amp: true,
  // ou
  amp: 'hybrid',
}

next export n'exporte plus les pages sous forme de index.html

Auparavant, l'exportation de pages/about.js produisait out/about/index.html. Ce comportement a été modifié pour produire out/about.html.

Vous pouvez revenir au comportement précédent en créant un next.config.js avec le contenu suivant :

next.config.js
module.exports = {
  trailingSlash: true,
}

pages/api/ est traité différemment

Les pages dans pages/api/ sont maintenant considérées comme des routes API. Les pages dans ce répertoire ne contiendront plus de bundle côté client.

Fonctionnalités dépréciées

next/dynamic a déprécié le chargement de plusieurs modules à la fois

La possibilité de charger plusieurs modules à la fois a été dépréciée dans next/dynamic pour se rapprocher de l'implémentation de React (React.lazy et Suspense).

Mettre à jour le code qui repose sur ce comportement est relativement simple ! Nous avons fourni un exemple avant/après pour vous aider à migrer votre application :

Avant

import dynamic from 'next/dynamic'

const HelloBundle = dynamic({
  modules: () => {
    const components = {
      Hello1: () => import('../components/hello1').then((m) => m.default),
      Hello2: () => import('../components/hello2').then((m) => m.default),
    }

    return components
  },
  render: (props, { Hello1, Hello2 }) => (
    <div>
      <h1>{props.title}</h1>
      <Hello1 />
      <Hello2 />
    </div>
  ),
})

function DynamicBundle() {
  return <HelloBundle title="Dynamic Bundle" />
}

export default DynamicBundle

Après

import dynamic from 'next/dynamic'

const Hello1 = dynamic(() => import('../components/hello1'))
const Hello2 = dynamic(() => import('../components/hello2'))

function HelloBundle({ title }) {
  return (
    <div>
      <h1>{title}</h1>
      <Hello1 />
      <Hello2 />
    </div>
  )
}

function DynamicBundle() {
  return <HelloBundle title="Dynamic Bundle" />
}

export default DynamicBundle