Actualización 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

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

Despliegue en producción en Vercel

Si anteriormente configuraste routes en tu archivo vercel.json para rutas dinámicas, estas reglas pueden eliminarse al aprovechar la nueva función de Enrutamiento Dinámico de Next.js 9.

Las rutas dinámicas de Next.js 9 se configuran automáticamente en Vercel y no requieren ninguna personalización en vercel.json.

Puedes leer más sobre Enrutamiento Dinámico aquí.

Revisa 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 funciones de Next.js!

El siguiente getInitialProps no hace nada y puede eliminarse:

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 está presente).

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

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

Los siguientes tipos son diferentes:

Esta lista fue creada por la comunidad para ayudarte a actualizar. Si encuentras otras diferencias, envía un pull-request a esta lista para 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 la configuración de Next.js a nivel de página, como AMP opcional y funciones de 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 migrarse 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 lo que 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/ se trata de manera diferente

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

Funciones obsoletas

next/dynamic ha marcado como obsoleta 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 alineado con 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