Next.jsアプリケーションを本番環境向けに最適化する方法
Next.jsアプリケーションを本番環境に移行する前に、最適なユーザーエクスペリエンス、パフォーマンス、セキュリティを実現するために実装を検討すべき最適化とパターンがあります。
このページでは、アプリケーションの構築中や本番環境に移行する前に参考にできるベストプラクティスと、認識しておくべきNext.jsの自動最適化について説明します。
自動最適化
これらのNext.jsの最適化はデフォルトで有効になっており、設定は必要ありません:
- サーバーコンポーネント: Next.jsはデフォルトでサーバーコンポーネントを使用します。サーバーコンポーネントはサーバー上で実行され、クライアント側でのレンダリングにJavaScriptを必要としません。そのため、クライアント側のJavaScriptバンドルのサイズに影響を与えません。インタラクティブ性が必要な場合は、必要に応じてクライアントコンポーネントを使用できます。
- コード分割: サーバーコンポーネントによりルートセグメントごとの自動コード分割が可能になります。必要に応じて遅延ロードを使用してクライアントコンポーネントやサードパーティライブラリを読み込むことも検討できます。
- プリフェッチ: 新しいルートへのリンクがユーザーのビューポートに入ると、Next.jsはバックグラウンドでそのルートをプリフェッチします。これにより新しいルートへの遷移がほぼ瞬時に行われます。必要に応じてプリフェッチを無効にすることもできます。
- 静的レンダリング: Next.jsはビルド時にサーバーとクライアントのコンポーネントを静的にレンダリングし、レンダリング結果をキャッシュしてアプリケーションのパフォーマンスを向上させます。必要に応じて特定のルートに対して動的レンダリングを選択できます。
- キャッシング: Next.jsはデータリクエスト、サーバーおよびクライアントコンポーネントのレンダリング結果、静的アセットなどをキャッシュして、サーバー、データベース、バックエンドサービスへのネットワークリクエスト数を削減します。必要に応じてキャッシングを無効にすることもできます。
これらのデフォルト設定は、アプリケーションのパフォーマンスを向上させ、各ネットワークリクエストで転送されるデータ量とコストを削減することを目的としています。
開発中
アプリケーションの構築中は、最適なパフォーマンスとユーザーエクスペリエンスを確保するために、以下の機能の使用をお勧めします:
ルーティングとレンダリング
- レイアウト: レイアウトを使用してページ間でUIを共有し、遷移時に部分レンダリングを有効にします。
<Link>
コンポーネント:<Link>
コンポーネントを使用してクライアントサイドナビゲーションとプリフェッチを行います。- エラーハンドリング: カスタムエラーページを作成して、本番環境でのキャッチオールエラーや404エラーを適切に処理します。
- 構成パターン: サーバーとクライアントコンポーネントの推奨される構成パターンに従い、クライアント側のJavaScriptバンドルが不必要に増大しないよう
"use client"
境界の配置を確認してください。 - 動的API:
cookies
やsearchParams
プロップなどの動的APIを使用すると、ルート全体が動的レンダリング(またはルートレイアウトで使用される場合はアプリケーション全体)に切り替わることに注意してください。動的APIの使用が意図的であることを確認し、必要に応じて<Suspense>
境界でラップしてください。
補足: 部分的プリレンダリング (実験的)を使用すると、ルート全体を動的レンダリングに切り替えることなく、ルートの一部を動的にすることができます。
データ取得とキャッシング
- サーバーコンポーネント: サーバーコンポーネントを使用して、サーバー上でのデータ取得のメリットを活用します。
- ルートハンドラー: クライアントコンポーネントからバックエンドリソースにアクセスするためにルートハンドラーを使用します。ただし、追加のサーバーリクエストを避けるため、サーバーコンポーネントからルートハンドラーを呼び出さないでください。
- ストリーミング: ローディングUIとReact Suspenseを使用して、UIをサーバーからクライアントに段階的に送信し、データ取得中にルート全体がブロックされるのを防ぎます。
- 並列データ取得: 必要に応じて並列でデータを取得してネットワークウォーターフォールを削減します。また、必要に応じてデータのプリロードも検討してください。
- データキャッシング: データリクエストがキャッシュされているかどうかを確認し、必要に応じてキャッシングを有効にします。
fetch
を使用しないリクエストがキャッシュされていることを確認してください。 - 静的画像:
public
ディレクトリを使用して、画像などのアプリケーションの静的アセットを自動的にキャッシュします。
UIとアクセシビリティ
- フォームとバリデーション: サーバーアクションを使用してフォーム送信、サーバーサイドバリデーション、エラー処理を行います。
- フォントモジュール: フォントモジュールを使用してフォントを最適化します。これにより、フォントファイルが他の静的アセットと共に自動的にホストされ、外部ネットワークリクエストが削減され、レイアウトシフトが軽減されます。
<Image>
コンポーネント: Imageコンポーネントを使用して画像を最適化します。これにより、画像が自動的に最適化され、レイアウトシフトが防止され、WebPなどの最新フォーマットで提供されます。<Script>
コンポーネント: Scriptコンポーネントを使用してサードパーティスクリプトを最適化します。これにより、スクリプトが自動的に遅延され、メインスレッドをブロックすることを防ぎます。- ESLint: 組み込みの
eslint-plugin-jsx-a11y
プラグインを使用して、アクセシビリティの問題を早期に発見します。
セキュリティ
- 汚染(Tainting): データオブジェクトや特定の値を汚染(taint)することで、機密データがクライアントに露出するのを防ぎます。
- サーバーアクション: ユーザーがサーバーアクションを呼び出す権限を持っていることを確認します。推奨されるセキュリティプラクティスを確認してください。
- 環境変数:
.env.*
ファイルが.gitignore
に追加され、公開変数のみがNEXT_PUBLIC_
プレフィックスを付けていることを確認してください。 - コンテンツセキュリティポリシー: クロスサイトスクリプティング、クリックジャッキング、その他のコード注入攻撃などのさまざまなセキュリティ脅威からアプリケーションを守るために、コンテンツセキュリティポリシーの追加を検討してください。
メタデータとSEO
- メタデータAPI: メタデータAPIを使用して、ページタイトル、説明などを追加することでアプリケーションの検索エンジン最適化(SEO)を向上させます。
- Open Graph(OG)画像: OG画像を作成して、アプリケーションをソーシャルシェアに備えます。
- サイトマップとロボット: サイトマップとロボットファイルを生成して、検索エンジンがページをクロールしインデックスするのを支援します。
型安全性
- TypeScriptとTSプラグイン: TypeScriptとTypeScriptプラグインを使用して、より優れた型安全性を確保し、エラーを早期に発見できるようにします。
本番環境に移行する前に
本番環境に移行する前に、next build
を実行してアプリケーションをローカルでビルドし、ビルドエラーを確認してから、next start
を実行して本番環境に近い環境でアプリケーションのパフォーマンスを測定できます。
Core Web Vitals
- Lighthouse: シークレットモードでLighthouseを実行し、ユーザーがサイトをどのように体験するかをよく理解し、改善すべき領域を特定します。これはシミュレーションテストであり、実際のデータ(Core Web Vitalsなど)と併せて確認する必要があります。
useReportWebVitals
フック: このフックを使用してCore Web Vitalsデータを分析ツールに送信します。
バンドルの分析
@next/bundle-analyzer
プラグインを使用して、JavaScriptバンドルのサイズを分析し、アプリケーションのパフォーマンスに影響を与える可能性のある大きなモジュールや依存関係を特定します。
さらに、以下のツールは、アプリケーションに新しい依存関係を追加した場合の影響を理解するのに役立ちます: