Обновление до версии 9

Для обновления до версии 9 выполните следующую команду:

Терминал
npm install next@9

yarn add next@9

Продуктовое развертывание на Vercel

Если вы ранее настраивали routes в файле vercel.json для динамических маршрутов, эти правила можно удалить, используя новую функцию Динамической маршрутизации (Dynamic Routing) в Next.js 9.

Динамические маршруты Next.js 9 автоматически настраиваются на Vercel и не требуют никакой кастомизации в vercel.json.

Подробнее о Динамической маршрутизации можно прочитать здесь.

Проверьте ваш кастомный файл приложения (pages/_app.js)

Если вы ранее копировали пример Кастомного <App>, вы можете удалить ваш getInitialProps.

Удаление getInitialProps из pages/_app.js (где это возможно) важно для использования новых функций Next.js!

Следующий getInitialProps ничего не делает и может быть удален:

class MyApp extends App {
  // Удалите меня, я ничего не делаю!
  static async getInitialProps({ Component, ctx }) {
    let pageProps = {}

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

    return { pageProps }
  }

  render() {
    // ... и т.д.
  }
}

Критические изменения

@zeit/next-typescript больше не нужен

Next.js теперь игнорирует использование @zeit/next-typescript и предупредит вас о необходимости удалить его. Пожалуйста, удалите этот плагин из вашего next.config.js.

Удалите ссылки на @zeit/next-typescript/babel из вашего кастомного .babelrc (если есть).

Использование fork-ts-checker-webpack-plugin также должно быть удалено из вашего next.config.js.

Определения TypeScript теперь поставляются с пакетом next, поэтому вам нужно удалить @types/next, так как они могут конфликтовать.

Типы изменились следующим образом:

Этот список был создан сообществом, чтобы помочь вам обновиться. Если вы найдете другие различия, пожалуйста, отправьте pull-request в этот список, чтобы помочь другим пользователям.

Было:

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

Стало:

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

Ключ config теперь экспортируется на уровне страницы

Теперь вы не можете экспортировать кастомную переменную с именем config со страницы (например, export { config } / export const config ...). Эта экспортируемая переменная теперь используется для указания конфигурации Next.js на уровне страницы, такой как Opt-in AMP и функции API Routes.

Вы должны переименовать экспорт config, не предназначенный для Next.js, во что-то другое.

next/dynamic больше не рендерит "loading..." по умолчанию во время загрузки

Динамические компоненты по умолчанию не будут рендерить ничего во время загрузки. Вы все еще можете настроить это поведение, установив свойство loading:

import dynamic from 'next/dynamic'

const DynamicComponentWithCustomLoading = dynamic(
  () => import('../components/hello2'),
  {
    loading: () => <p>Загрузка</p>,
  }
)

withAmp удален в пользу экспортируемого объекта конфигурации

Next.js теперь имеет концепцию конфигурации на уровне страницы, поэтому higher-order компонент withAmp был удален для согласованности.

Это изменение может быть автоматически применено путем выполнения следующих команд в корне вашего проекта Next.js:

Терминал
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

Чтобы выполнить это миграцию вручную или посмотреть, что произведет codemod, см. ниже:

До

import { withAmp } from 'next/amp'

function Home() {
  return <h1>Моя AMP страница</h1>
}

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

После

export default function Home() {
  return <h1>Моя AMP страница</h1>
}

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

next export больше не экспортирует страницы как index.html

Ранее экспорт pages/about.js приводил к созданию out/about/index.html. Теперь это поведение изменено на создание out/about.html.

Вы можете вернуть предыдущее поведение, создав next.config.js со следующим содержимым:

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

pages/api/ обрабатывается иначе

Страницы в pages/api/ теперь считаются API Routes. Страницы в этой директории больше не будут содержать клиентский бандл.

Устаревшие функции

next/dynamic устарел для загрузки нескольких модулей одновременно

Возможность загружать несколько модулей одновременно в next/dynamic устарела, чтобы быть ближе к реализации React (React.lazy и Suspense).

Обновление кода, который полагается на это поведение, относительно просто! Мы предоставили пример до/после, чтобы помочь вам мигрировать ваше приложение:

До

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

После

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