Create React App からの移行
このガイドは、既存の Create React App サイトを Next.js に移行するのに役立ちます。
なぜ切り替えるのか?
Create React App から Next.js に切り替える理由はいくつかあります:
初期ページ読み込み時間が遅い
Create React App は純粋なクライアントサイド React を使用しています。クライアントサイドのみのアプリケーション(シングルページアプリケーション、SPA)は、初期ページ読み込み時間が遅くなりがちです。これは次の理由によるものです:
- ブラウザは React コードと全アプリケーションバンドルをダウンロードして実行するまで待つ必要があり、その後にデータを読み込むリクエストを送信できます。
- 新しい機能や依存関係を追加するたびに、アプリケーションコードが肥大化します。
自動コード分割がない
遅い読み込み時間の問題は、コード分割である程度管理できますが、手動でコード分割を行うと、パフォーマンスが悪化することがよくあります。手動でコード分割すると、ネットワークウォーターフォールを不注意に導入しやすくなります。Next.js はルーターに組み込まれた自動コード分割を提供しています。
ネットワークウォーターフォール
パフォーマンス低下の一般的な原因は、アプリケーションがデータ取得のためにシーケンシャルなクライアント-サーバーリクエストを行う場合です。SPA におけるデータ取得の一般的なパターンは、最初にプレースホルダーをレンダリングし、コンポーネントがマウントされた後にデータを取得することです。残念ながら、これは、データを取得する子コンポーネントが、親コンポーネントが独自のデータの読み込みを完了するまでデータ取得を開始できないことを意味します。
Next.js はクライアント上でのデータ取得をサポートしていますが、データ取得をサーバーに移すオプションも提供しており、クライアント-サーバーのウォーターフォールを排除できます。
高速で意図的な読み込み状態
React Suspense によるストリーミングの組み込みサポートにより、ネットワークウォーターフォールを導入せずに、UIのどの部分を最初にどの順序で読み込むかをより意図的に制御できます。
これにより、読み込みが高速なページを構築し、レイアウトシフトを排除できます。
データ取得戦略の選択
ニーズに応じて、Next.js では、ページとコンポーネントごとにデータ取得戦略を選択できます。ビルド時、サーバー上のリクエスト時、またはクライアント上のいずれかでデータを取得するかを決定できます。例えば、CMSからデータを取得してブログ投稿をビルド時にレンダリングし、CDNで効率的にキャッシュできます。
ミドルウェア
Next.js ミドルウェアを使用すると、リクエストが完了する前にサーバー上でコードを実行できます。これは、認証が必要なページにユーザーがアクセスした際に、ログインページにリダイレクトすることで、認証されていないコンテンツの一瞬のちらつきを避けるのに特に役立ちます。ミドルウェアは、実験や国際化にも役立ちます。
組み込みの最適化
画像、フォント、サードパーティスクリプトは、アプリケーションのパフォーマンスに大きな影響を与えることがよくあります。Next.js には、それらを自動的に最適化する組み込みコンポーネントが用意されています。
移行手順
この移行の目的は、できるだけ早く動作する Next.js アプリケーションを作成し、その後 Next.js の機能を段階的に採用することです。最初は、既存のルーターを移行せずに、純粋なクライアントサイドアプリケーション(SPA)として保持します。これにより、移行プロセス中の問題の可能性を最小限に抑え、マージコンフリクトを減らすことができます。
ステップ 1: Next.js 依存関係のインストール
最初に、next
を依存関係としてインストールする必要があります:
ステップ 2: Next.js 設定ファイルの作成
プロジェクトのルートに next.config.mjs
を作成します。このファイルには Next.js 設定オプションが保持されます。
ステップ 3: ルートレイアウトの作成
Next.js の App Router アプリケーションには、アプリケーション内のすべてのページをラップする ルートレイアウトファイルを含める必要があります。これは React サーバーコンポーネントです。
CRA アプリケーションで最も近いルートレイアウトファイルは、<html>
、<head>
、<body>
タグを含む index.html
ファイルです。
このステップでは、index.html
ファイルをルートレイアウトファイルに変換します:
src
ディレクトリに新しいapp
ディレクトリを作成します。- その
app
ディレクトリ内に新しいlayout.tsx
ファイルを作成します:
補足: レイアウトファイルには
.js
、.jsx
、または.tsx
拡張子を使用できます。
以前に作成した <RootLayout>
コンポーネントに index.html
ファイルの内容をコピーし、body.div#root
タグと body.noscript
タグを <div id="root">{children}</div>
に置き換えます:
補足: Next.js は CRA の
public/manifest.json
ファイル、追加のアイコン(favicon
、icon
、apple-icon
以外)、テスト設定を無視しますが、これらが必要な場合、Next.js もこれらのオプションをサポートしています。詳細は メタデータ API と テストのドキュメントを参照してください。
ステップ 4: メタデータ
Next.js にはデフォルトで meta charset と meta viewport タグが含まれているため、<head>
からそれらを安全に削除できます:
favicon.ico
、icon.png
、robots.txt
などのメタデータファイルは、app
ディレクトリの最上位に配置されていれば、自動的にアプリケーションの <head>
タグに追加されます。サポートされているすべてのファイルを app
ディレクトリに移動した後、それらの <link>
タグを安全に削除できます:
最後に、Next.jsはMetadata APIで最後の <head>
タグを管理できます。最終的なメタデータ情報をエクスポートされた metadata
オブジェクトに移動します:
上記の変更により、index.html
ですべてを宣言することから、Next.jsのフレームワークに組み込まれている規約ベースのアプローチ(Metadata API)に移行しました。このアプローチにより、SEOとWebページの共有性をより簡単に改善できます。
ステップ 5: スタイル
Create React Appと同様に、Next.jsはCSS Modulesを組み込みでサポートしています。
グローバルCSSファイルを使用している場合は、app/layout.tsx
ファイルにインポートします:
Tailwindを使用している場合、postcss
とautoprefixer
をインストールする必要があります:
次に、プロジェクトのルートに postcss.config.js
ファイルを作成します:
ステップ 6: エントリーポイントページの作成
Next.jsでは、page.tsx
ファイルを作成することでアプリケーションのエントリーポイントを宣言します。このファイルはCreate React Appの src/index.tsx
ファイルに最も近いものです。このステップでは、アプリケーションのエントリーポイントを設定します。
app
ディレクトリに [[...slug]]
ディレクトリを作成します。
このガイドではNext.jsをSPA(シングルページアプリケーション)として最初に設定することを目指すため、アプリケーションの可能なすべてのルートをキャッチするページエントリーポイントが必要です。そのため、app
ディレクトリに新しい [[...slug]]
ディレクトリを作成します。
このディレクトリはオプションのキャッチオールルートセグメントと呼ばれます。Next.jsはルートを定義するためにディレクトリを使用するファイルシステムベースのルーターを使用します。この特殊なディレクトリにより、アプリケーションのすべてのルートがその中の page.tsx
ファイルに転送されます。
app/[[...slug]]
ディレクトリ内に次の内容の新しい page.tsx
ファイルを作成します:
このファイルはサーバーコンポーネントです。next build
を実行すると、ファイルは静的アセットにプリレンダリングされます。動的コードは_不要_です。
このファイルはグローバルCSSをインポートし、generateStaticParams
に、インデックスルート /
のみを生成することを伝えます。
次に、クライアント専用で実行されるCreate React Appの残りの部分を移動します。
このファイルは、'use client'
ディレクティブで定義されたクライアントコンポーネントです。クライアントコンポーネントは、クライアントに送信される前に、サーバー上でHTMLにプリレンダリングされます。
クライアント専用のアプリケーションを開始するために、App
コンポーネントからプリレンダリングを無効にするようNext.jsを構成できます。
次に、エントリーポイントページを新しいコンポーネントを使用するように更新します:
ステップ 7: 静的画像インポートの更新
Next.jsは静的画像インポートをCreate React Appとは少し異なる方法で処理します。Create React Appでは、画像ファイルをインポートするとその公開URLを文字列として返します:
Next.jsでは、静的画像インポートはオブジェクトを返します。このオブジェクトは、Next.js <Image>
コンポーネントで直接使用するか、既存の <img>
タグでsrc
プロパティを使用できます。
<Image>
コンポーネントは、自動画像最適化の追加のメリットがあります。<Image>
コンポーネントは、画像の寸法に基づいて、結果の <img>
タグの width
および height
属性を自動的に設定します。これにより、画像の読み込み時にレイアウトのシフトを防ぐことができます。ただし、アプリケーションに、片方の寸法のみがスタイル設定され、もう片方が auto
にスタイル設定されていない画像が含まれている場合、問題が発生する可能性があります。auto
にスタイル設定されていない場合、寸法は <img>
タグの寸法属性の値にデフォルト設定され、画像が歪んで表示される可能性があります。
<img>
タグをそのまま使用することで、アプリケーションの変更量を減らし、上記の問題を防ぐことができます。その後、ローダーの設定によって画像を最適化したり、デフォルトで自動画像最適化を提供する Next.js サーバーに移行したりするために、オプションで後で <Image>
コンポーネントに移行できます。
/public
からインポートされる画像の絶対インポートパスを相対インポートに変換します:
<img>
タグに画像オブジェクト全体ではなく、画像 src
プロパティを渡します:
または、ファイル名に基づいて画像アセットのパブリック URL を参照することもできます。例えば、public/logo.png
は、アプリケーションで /logo.png
として画像を提供し、src
の値となります。
警告: TypeScript を使用している場合、
src
プロパティにアクセスする際に型エラーが発生する可能性があります。これを修正するには、tsconfig.json
ファイルのinclude
配列にnext-env.d.ts
を追加する必要があります。Next.js は、ステップ 9 でアプリケーションを実行すると、このファイルを自動的に生成します。
ステップ 8: 環境変数の移行
Next.js は、CRA と同様に .env
環境変数をサポートしています。
クライアント側で環境変数を公開するために使用される接頭辞が主な違いです。REACT_APP_
接頭辞のある環境変数をすべて NEXT_PUBLIC_
に変更してください。
ステップ 9: package.json
内のスクリプトを更新
Next.js への移行が成功したかをテストするために、アプリケーションを実行できるはずです。ただし、その前に、package.json
内の scripts
を Next.js 関連のコマンドで更新し、.next
と next-env.d.ts
を .gitignore
ファイルに追加する必要があります:
npm run dev
を実行し、http://localhost:3000
を開きます。Next.js でアプリケーションが実行されているはずです。
ステップ 10: クリーンアップ
Create React App 関連の成果物をコードベースからクリーンアップできます:
public/index.html
を削除src/index.tsx
を削除src/react-app-env.d.ts
を削除reportWebVitals
のセットアップを削除- CRA の依存関係(
react-scripts
)をアンインストール
バンドラーの互換性
Create React App と Next.js は、どちらもデフォルトで webpack を使用してバンドルします。
CRA アプリケーションを Next.js に移行する際、移行したいカスタム webpack 設定がある可能性があります。Next.js は、カスタム webpack 設定の提供をサポートしています。
さらに、Next.js は next dev --turbopack
を使用して、ローカル開発のパフォーマンスを向上させる Turbopack をサポートしています。Turbopack は、互換性と段階的な導入のために、いくつかの webpack ローダーもサポートしています。
次のステップ
すべてが計画通りに進めば、シングルページアプリケーションとして動作する Next.js アプリケーションが完成しています。ただし、まだ Next.js の利点のほとんどを活用できていませんが、現時点から段階的な変更を加えて、すべての利点を得ることができます。次に行うことは以下のようなものです:
- React Router から Next.js App Router に移行して、以下を取得:
- 自動コード分割
- ストリーミングサーバーレンダリング
- React サーバーコンポーネント
<Image>
コンポーネントで画像を最適化next/font
でフォントを最適化<Script>
コンポーネントでサードパーティスクリプトを最適化- Next.js ルールをサポートするように ESLint 設定を更新
補足: 静的エクスポートは、現在
useParams
フックの使用をサポートしていません。