Cómo actualizar a la versión 9

Para actualizar a la versión 9, ejecuta el siguiente comando:

Terminal
npm i next@9
Terminal
yarn add next@9
Terminal
pnpm up next@9
Terminal
bun add next@9

Nota importante: Si estás usando TypeScript, asegúrate de actualizar también @types/react y @types/react-dom a sus versiones correspondientes.

Verifica tu archivo de App personalizada (pages/_app.js)

Si anteriormente copiaste el ejemplo de App personalizada (<App>), es posible que puedas eliminar tu getInitialProps.

¡Eliminar getInitialProps de pages/_app.js (cuando sea posible) es importante para aprovechar las nuevas características de Next.js!

El siguiente getInitialProps no hace nada y puede ser eliminado:

class MyApp extends App {
  // ¡Elimíname, no hago nada!
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

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

    return { pageProps }
  }

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

Cambios importantes

@zeit/next-typescript ya no es necesario

Next.js ahora ignorará el uso de @zeit/next-typescript y te advertirá que lo elimines. Por favor, elimina este plugin de tu next.config.js.

Elimina las referencias a @zeit/next-typescript/babel de tu .babelrc personalizado (si existe).

El uso de fork-ts-checker-webpack-plugin también debe ser eliminado de tu next.config.js.

Las definiciones de TypeScript ahora se publican con el paquete next, por lo que debes desinstalar @types/next ya que podrían causar conflictos.

Los siguientes tipos han cambiado:

Esta lista fue creada por la comunidad para ayudarte en la actualización. Si encuentras otras diferencias, por favor envía un pull-request para actualizar esta lista y ayudar a otros usuarios.

De:

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

a:

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

La clave config ahora es una exportación en una página

Ya no puedes exportar una variable personalizada llamada config desde una página (ej. export { config } / export const config ...). Esta variable exportada ahora se usa para especificar configuraciones de nivel de página en Next.js como características de AMP opcional y Rutas API.

Debes renombrar cualquier exportación config que no sea para propósitos de Next.js.

next/dynamic ya no renderiza "loading..." por defecto durante la carga

Los componentes dinámicos no renderizarán nada por defecto mientras se cargan. Aún puedes personalizar este comportamiento estableciendo la propiedad loading:

import dynamic from 'next/dynamic'

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

withAmp ha sido eliminado en favor de un objeto de configuración exportado

Next.js ahora tiene el concepto de configuración a nivel de página, por lo que el componente de orden superior withAmp ha sido eliminado para mantener la consistencia.

Este cambio puede ser migrado automáticamente ejecutando los siguientes comandos en la raíz de tu proyecto 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

Para realizar esta migración manualmente, o ver qué producirá el codemod, consulta a continuación:

Antes

import { withAmp } from 'next/amp'

function Home() {
  return <h1>Mi página AMP</h1>
}

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

Después

export default function Home() {
  return <h1>Mi página AMP</h1>
}

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

next export ya no exporta páginas como index.html

Anteriormente, exportar pages/about.js resultaría en out/about/index.html. Este comportamiento ha cambiado para resultar en out/about.html.

Puedes revertir al comportamiento anterior creando un next.config.js con el siguiente contenido:

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

pages/api/ es tratado de manera diferente

Las páginas en pages/api/ ahora son consideradas Rutas API. Las páginas en este directorio ya no contendrán un bundle del lado del cliente.

Características obsoletas

next/dynamic ha marcado como obsoleto la carga de múltiples módulos a la vez

La capacidad de cargar múltiples módulos a la vez ha sido marcada como obsoleta en next/dynamic para estar más cerca de la implementación de React (React.lazy y Suspense).

¡Actualizar el código que depende de este comportamiento es relativamente sencillo! Hemos proporcionado un ejemplo de antes/después para ayudarte a migrar tu aplicación:

Antes

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

Despué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