Next.js10から最新のNext.js11へのアップグレード方法を解説!Reactエンジニアがサンプルソースを交え解説!

Next.js10から最新のNext.js11へのアップグレード方法を解説!Reactエンジニアがサンプルソースを交え解説!

2021.08.10

こんにちは!

世界的にシェア数が多く開発が盛んな NextJS は、早いサイクルでメジャーバージョンがアップデートされます。最新バージョンでは常に従来の開発課題を解決するソリューションが提供されるので、ぜひ新しいバージョンでの開発に取り組みたいところです。

本記事では、Next.js10 から最新の Next .js11 へのアップグレード方法をReactJS エンジニアが紹介・解説いたします。

想定する読者

  • Next.js10 の開発プロジェクトに携わっているヒト
  • Web アプリケーションに対する基本的な知識を持っているヒト
  • React を使った開発経験があるヒト

はじめに

2021年6月16日に Next.js のバージョン11がリリースされました。

本記事では Next.js10 から最新の Next.js11 へのアップロード方法を詳しく解説していきたいと思います。

最新の Next.js のアップデート内容については、こちらの記事で詳しく解説しているので、ぜひ併せて参照してみてください。

Next.js をバージョン10からバージョン11へアップグレード

Next.js をバージョン10からバージョン11にアップグレードする具体的な方法を紹介していきます。

React と React DOM を最新バージョンにアップグレードする

ほとんどのアプリケーションでは最新バージョンの React を使用していて、 Next.js のバージョン11では React の最新バージョンである17.0.2に更新されています。

そのため、 Next.js をバージョン10からバージョン11にアップグレードする前に React を最新バージョンへとアップグレードする必要があります。

React を最新バージョンへアップグレードするには、下記のいずれかのコマンドを実行します。

npm を使用する場合

npm install react@latest react-dom@latest

yarn を使用する場合

yarn add react@latest react-dom@latest

プロジェクト内の package.json を確認して、 react と react-dom が最新バージョンに変更されていれば無事にアップグレードが完了しています。

{
  "react": "^17.0.2",
  "react-dom": "^17.0.2",
}

Next.js を最新バージョンにアップグレードする

React と React DOM を最新バージョンへアップグレード出来たら、いよいよ Next.js を最新バージョンへアップグレードしていきます。

とは言っても、 React と React DOM をアップグレードする際と、ほとんど同じで下記のいずれかのコマンドを実行します。

npm を使用している場合

npm install next@latest

yarn を使用している場合

yarn add next@latest

プロジェクト内の package.json を確認して、 next が最新バージョンに変更されていれば無事にアップグレードが完了しています。

{
  "next": "^11.0.0",
}

Webpack 5 について

Webpack についてはバージョン4からバージョン5が Next.js アプリケーションのデフォルトになりました。カスタム webpack 構成がない限り、アプリケーションは既にデフォルトの webpack 5 を使用しています。

アプリケーションで webpack 5 を使用すると、次のような多くのメリットがあります。

  • 改善されたディスクキャッシング: next build では後続のビルドで大幅に高速化
  • 高速リフレッシュの改善:高速リフレッシュ作業が優先される
  • アセットの長期キャッシュの改善:ビルド間での変更される可能性が低い決定論的コード出力
  • 改善されたツリーシェイク
  • new URL("file.png", import.meta.url) を使用したアセットのサポート
  • new Worker(new URL("worker.js", import.meta.url)) を使用する Web ワーカーのサポート
  • package.json フィールドでの exports/imports のサポート

カスタム webpack 構成を使用している場合は、アプリケーションが webpack 5 で動作することを確認するために下記のいくつかの手順を実行する必要があります。

  • next-transpile-modules を使用するときは、このパッチを含む最新バージョンを使用していることを確認する
  • @zeit/next-css , @zeit/next-sass を使用する場合、組み込みの CSS / Sass サポートを代わりに使用するようにする
  • @zeit/next-preact を使用する場合、代わりにこの例を使用する
  • @zeit/next-source-maps を使用する場合、組み込みの本番ソースマップサポートを使用する
  • webpack プラグインを使用するときは、最新バージョンにアップグレードされていることを確認する。ほとんどの場合、最新バージョンにはwebpack 5 のみサポートが含まれている。場合によっては、これらのアップグレードされた webpack プラグインは webpack5 のみをサポートしている。

Next.js バージョン11のアップグレード詳細内容

クリーニングの distDir がデフォルト設定に

キャッシュ .next を除いて、ビルド出力ディレクトリがデフォルトでクリアされるようになりました。

アプリケーションが以前のバージョンでこのキャッシュ動作に依存していた場合は、 next.config.js に cleanDistDir: false フラグを追加することで、新しいデフォルトの動作を無効にすることが出来ます。

cleanDistDir: false

next start / next dev で PORT がサポートされるように

Next.js11 では PORT アプリケーションを実行する必要のあるポートを設定するための環境変数をサポートしています。

-p / --port の使用は引き続き推奨されていますが、何らかの理由で使用が禁止されている場合には、 PORT を代わりに使用することが出来ます。

PORT=400 next start

next.config.js で画像をインポートするためのカスタマイズ

Next.js11 は、 next / image を使用した静的画像のインポートをサポートしています。

Next.js11 では、 next / image を使用することで2つの新機能を使用することが出来ます。

  • Automatic Size Detection (自動サイズ検出)
  • Image Placeholders (画像プレースホルダー)

この新機能は、画像のインポートを処理できることに依存しているため、 next / image 以前に next-images または next-optimized-images パッケージを追加した場合は、次の機能を使用して新しい組み込みサポートに移動するか、無効にすることが出来ます。

module.exports = {
  images: {
    disableStaticImages: true,
  },
}

pages / _app.js から super.componentDidCatch() を削除

Next.js9 以降、 next/app コンポーネントから componentDidCatch メソッドは廃止されて、不要になりました。 Next.js11 は削除されています。

pages / _app.js のコードの中にカスタマイズした componentDidCatch メソッドがある場合は、 super.componentDidCatch は不要なため削除できます。

pages / _app.js から Container を削除

Next.js9 以降、このエクスポートは不要になったため非推奨になり、開発中には警告が表示されて操作できなくなっていました。 Next.js11 では削除されています。

pages / _app.js の中で next / app から Container を使用している場合は、 Container を削除することができます。

import React from 'react'
import App, { Container } from 'next/app'

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props
    return (
      <Container>
        <Component {...pageProps} />
      </Container>
    )
  }
}

export default MyApp
import React from 'react'
import App from 'next/app'

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props
    return <Component {...pageProps} />
  }
}

export default MyApp

ページコンポーネントから props.url を削除

Next.js4 以降、 props.url プロパティは非推奨になり、開発中に警告が表示されていました。

getStaticProps / getServerSideProps の導入により、これらのメソッドは既に props.url の使用を許可していません。 Next.js11 では、 props.url は完全に削除されました。

next / image から unsized を削除

next / image の unsized プロパティは、 Next.js10.0.1 で非推奨になりました。

unsized プロパティの代わりに layout="fill" を使用することができます。

Next.js11 では unsized プロパティが削除されました。

next / dynamic から modules プロパティを削除

next / dynamic の modulesrender オプションは、 Next.js9.5 以降非推奨になり、非推奨になったことを示す警告が表示されます。

これは next / dynamic を API サーフェイスの React.lazy に近づけるために行われました。

このオプションは Next.js8 以降のドキュメントで記載されていないため、アプリケーションで使用されている可能性は低くなっています。

もしアプリケーションが modulesrender を使用している場合は、使用しないように移行することができます。

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

Head.rewind を削除

Head.rewind は Next.js9.5 以降動作しませんでしたが、 Next.js11 では削除されました。

Head.rewind の使用を安全に削除することができます。

Moment.js ロケールはデフォルトで削除

Moment.js には、デフォルトで多くのロケールの翻訳が含まれています。

Next.js は Moment.js を使用するアプリケーションのバンドルサイズを最適化するために、デフォルトでこれらのロケールを自動的に削除するようになりました。

特定のロケールをロードするには、次のような記述をします。

import moment from 'moment'
import 'moment/locale/ja'

moment.locale('ja')

この新しい動作を望まない場合には、 next.config.js に excludeDefaultMomentLocales: false を追加することでこの新しいデフォルトをオプトアウトすることができます。

Moment.js のサイズが大幅に減少するため、この新しい最適化を無効にしないことを強くお勧めしています。

router.events を更新

レンダリング中に router.events にアクセスしている場合、 Next.js11 では事前レンダリング中に router.events は提供されなくなりました。

useEffect の中で、 router.events にアクセスしていることを確認してください。

useEffect(() => {
  const handleRouteChange = (url, { shallow }) => {
    console.log(
      `App is changing to ${url} ${
        shallow ? 'with' : 'without'
      } shallow routing`
    )
  }

  router.events.on('routeChangeStart', handleRouteChange)

  // If the component is unmounted, unsubscribe
  // from the event with the `off` method:
  return () => {
    router.events.off('routeChangeStart', handleRouteChange)
  }
}, [router])

もしアプリケーションで公開されていない内部プロパティ router.router.events を使用する場合は、必ず router.events を使用してください。

まとめ

Next.js のバージョン10からバージョン11にアップグレードする方法を解説してきました。

このようにプロジェクトをアップグレードするには、数コマンド実行するだけで簡単にアップグレードすることができます。ただし削除されているものも多く、これらを既存のプロジェクトで使用していた場合には、移行作業などが発生する場合があります。そのため、ケースによっては改修作業に工数を要する場合もあるでしょう。

しかし、削除されたものについては基本的に元から非推奨のものが多いので、すんなりアップグレードを行えるのではないでしょうか。ぜひ、Next.js11 のアップグレードを検討してみてください。

Next.js、ReactJSの開発はお気軽にご相談ください。