【Next.js和訳】Upgrade Guide
この記事について
この記事は、Upgrade Guideの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
Upgrade Guide
バージョン 10 から 11 へのアップグレード
React のバージョンを最新にアップグレード
ほとんどのアプリケーションは、すでに最新の React を使用しています。Next.js 11 では、最小の React バージョンが 17.0.2 に更新されています。
アップグレードするには、以下のコマンドを実行します。
npm install react@latest react-dom@latest
yarn
を使う場合は、以下のコマンドを実行してください。
yarn add react@latest react-dom@latest
Next.js を最新のバージョンにアップグレードする
アップグレードするには、ターミナルで以下のコマンドを実行します。
npm install next@latest
または
yarn add next@latest
Webpack 5
Webpack 5 は、すべての Next.js アプリケーションのデフォルトとなっています。カスタムの webpack 設定を行っていない場合、アプリケーションはすでに webpack 5 を使用しています。カスタムの webpack を設定している場合は、Next.js の webpack 5 のドキュメントを参照してアップグレードすることができます。
distDir
のクリーニングがデフォルトに
Next.js のキャッシュを除き、ビルドの出力ディレクトリ(デフォルトでは.next
)がデフォルトでクリアされるようになりました。詳細については、cleaning distDir
RFCを参照してください。
アプリケーションがこの動作に依存していた場合は、next.config.js
にcleanDistDir: false
フラグを追加することで、新しいデフォルトの動作を無効にすることができます。
PORT
がnext dev
とnext start
でサポート
Next.js 11 では、アプリケーションを実行するためのポートを設定する環境変数PORT
がサポートされています。これまで通り-p
/--port
の使用が推奨されますが、-p
の使用が禁止されていた場合は、代替手段としてPORT
を使用することができます。
例
PORT=4000 next start
next.config.js
をカスタマイズして画像を取り込む
Next.js 11 では、next/image
による静的な画像のインポートをサポートしています。この新機能は、画像のインポートを処理できるかどうかにかかっています。以前にnext-images
またはnext-optimized-images
パッケージを追加していた場合は、next/image
を使った新しい組み込みサポートに移行するか、この機能を無効にすることができます。
module.exports = {
images: {
disableStaticImages: true,
},
}
pages/_app.js
からsuper.componentDidCatch()
を削除
next/app
コンポーネントのcomponentDidCatch
は、Next.js 9 以降、不要になったため非推奨となり、Next.js 11 では削除されました。
pages/_app.js
にカスタムのcomponentDidCatch
メソッドがある場合、super.componentDidCatch
は不要になったので削除できます。
pages/_app.js
からContainer
を削除
このエクスポートは、Next.js 9 以降、不要になったため非推奨となっており、それ以降は開発中に警告が出てダメになっていました。Next.js 11 では削除されています。
pages/_app.js
がnext/app
からContainer
をインポートしている場合は、Container
が削除されているので削除できます。詳しくはドキュメントをご覧ください。
props.url
の使用を削除する
ページコンポーネントからこのプロパティは Next.js 4 から非推奨となり、開発中に警告が表示されるようになりました。getStaticProps
/ getServerSideProps
の導入により、これらのメソッドはprops.url
の使用を禁止しました。Next.js 11 では、このプロパティは完全に削除されました。
詳しくはドキュメントをご覧ください。
next/image
のunsized
プロパティの削除
next/image
のunsized
プロパティは、Next.js 10.0.1 で非推奨となりました。代わりにlayout="fill"
を使用することができます。Next.js 11 ではunsized
が削除されました。
next/dynamic
のmodules
プロパティの削除
next/dynamic
のmodules
とrender
オプションは、Next.js 9.5 から非推奨となり、非推奨であることを示す警告が表示されるようになりました。これは、next/dynamic
の API サーフェスをReact.lazy
に近づけるために行われたものです。Next.js 11 では、modules
とrender
オプションが削除されました。
このオプションは Next.js 8 以降のドキュメントでは言及されていないので、アプリケーションがこのオプションを使用している可能性は低いでしょう。
modules
やrender
を使用するアプリケーションの場合は、ドキュメントを参照してください。
Head.rewind
の削除
Head.rewind
は Next.js 9.5 から廃止されていましたが、Next.js 11 で削除されました。Next.js 11 で削除されました。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
を追加することで無効にすることができます。
router.events
の使用方法の更新
レンダリング時にrouter.events
にアクセスしている場合、Next.js 11 ではプリレンダリング時に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)
// コンポーネントがアンマウントされた場合は、`off`メソッドでイベントの配信を停止します。
return () => {
router.events.off("routeChangeStart", handleRouteChange)
}
}, [router])
公開されていない内部プロパティであるrouter.router.events
を使用している場合は、必ずrouter.events
も使用してください。
React 16 から 17 へ
React 17 では、新しいJSX Transformが導入され、長い間使われてきた Next.js の機能が広く React のエコシステムに導入されました。JSX を使用する際にimport React from 'react'
を書く必要はありません。React 17 を使用する際、Next.js は自動的にこの新しいトランスフォームを使用します。このトランスフォームはReact
の変数をグローバルにしません。これは以前の Next.js の実装では意図しない副作用でした。誤ってReact
をインポートせずに使用してしまったケースを自動的に修正するcodemod が用意されています。
バージョン 9 から 10 へのアップグレード
バージョン 9 から 10 への変更点はありません。
アップグレードするには、以下のコマンドを実行してください。
npm install next@10
yarn
を使う場合は、以下のコマンドを実行してください。
yarn add next@10
バージョン 8 から 9 へのアップグレード
プリアンブル
Vercel でのプロダクション・デプロイメント
以前、vercel.json
ファイルにダイナミックルート用のroutes
を設定していた場合、Next.js 9 の新機能であるダイナミックルートを活用する際に、これらのルールを削除することができます。
Next.js 9 のダイナミックルートはVercel上で自動的に設定され、vercel.json のカスタマイズは必要ありません。
Dynamic Routing についてはこちらをご覧ください。
pages/_app.js
)
カスタムのチェック(Custom <App>
の例をコピーした場合は、getInitialProps
を削除できるかもしれません。
Next.js の新機能を活用するには、可能な限りpages/_app.js
からgetInitialProps
を削除することが重要です。
次の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
から削除してください。
カスタム.babelrc
(もしあれば)から@zeit/next-typescript/babel
への参照を削除してください。
fork-ts-checker-webpack-plugin
の使用もあなたのnext.config.js
から削除してください。
TypeScript Definitions はnext
パッケージで公開されているので、衝突するため@types/next
をアンインストールする必要があります。
以下のタイプが異なります。
以下から
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 ...
など)。このエクスポートされた変数は、Optin AMP や API Route の機能など、ページレベルの Next.js の設定を指定するために使われるようになりました。
Next.js を使用しないconfig
のエクスポートは、別の名前に変更する必要があります。
next/dynamic
は、ロード中にデフォルトで"loading..."を表示しなくなりました
ダイナミックコンポーネントは、デフォルトではロード中に何も表示しません。loading
プロパティを設定することで、この動作をカスタマイズすることができます。
import dynamic from "next/dynamic"
const DynamicComponentWithCustomLoading = dynamic(() => import("../components/hello2"), {
loading: () => <p>Loading</p>,
})
withAmp
が削除され、エクスポートされる設定オブジェクトが採用されました
Next.js にはページレベルの設定という概念があるため、一貫性を保つために高次コンポーネントである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 が生成するものを確認するには、以下を参照してください。
Before
import { withAmp } from 'next/amp'
function Home() {
return <h1>My AMP Page</h1>
}
export default withAmp(Home)
// または
export default withAmp(Home, { hybrid: true })
After
export default function Home() {
return <h1>My AMP Page</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
を作成します。
module.exports = {
trailingSlash: true,
}
./pages/api/
の扱いの変更
./pages/api/
のページはAPI ルートとみなされます。このディレクトリのページには、クライアント側のバンドルは含まれなくなります。
非推奨の機能
next/dynamic
では、複数のモジュールを一度に読み込む機能が非推奨となりました。
next/dynamic
では、React の実装(React.lazy
とSuspense
)に近づけるために、複数のモジュールを一度にロードする機能が非推奨となりました。
この動作に依存しているコードを更新することは、比較的簡単です アプリケーションを移行する際の参考として、before/after の例を用意しました。
Before
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
After
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
Discussion