見出し画像

Next.js15へ上げてみよう

遂にNext.js15が来たのでアップグレードしていくついでにメモしておきます。


@next/codemod CLI: 最新の Next.js および React バージョンに簡単にアップグレードできます。

npx @next/codemod@canary upgrade

Codemodsは、コードベースを自動的に変換・修正するためのツールです。一般的に、ライブラリやフレームワークのバージョンアップに伴ってAPIが変更されたり、非推奨の機能が削除されたりする場合に、これらの変更をコード全体に適用するのは手間がかかります。Codemodsを使うことで、手動で行う修正作業を自動化できるため、作業効率が大幅に向上します。

Next.js 15では、Codemodsが提供され、バージョンアップに伴うコード変更を支援します。具体的には、非推奨のAPIを新しいAPIに置き換えたり、構文の変更に対応したりします。これにより、手動で大量のコードを修正する手間を省き、Next.js 15への移行を簡単に進めることができます。

Codemodsを使うと、コード全体を一度に変換できるため、ミスを減らしつつ、バージョンアップの作業を効率化できます。

Codemodの選択

◉   (v15.0.0-canary.179) app-dir-runtime-config-experimental-edge
◉   (v15.0.0-canary.171) next-async-request-api
◉   (v15.0.0-canary.153) next-request-geo-ip
◉   (v15.0.0-canary.44) next-dynamic-access-named-export


  • app-dir-runtime-config-experimental-edge
    Next.js 15では、appディレクトリを使用する新しいアプローチが進んでおり、これに加えてエッジランタイムを使用する構成がサポートされるようになっています。このCodemodは、エッジランタイムに関連する実験的なランタイム設定をアプリの構成に追加または修正します。エッジランタイムを使用すると、リクエストの処理がより高速に行われ、グローバルなCDNのエッジサーバーで実行されることで、パフォーマンスが向上します。

  • next-async-request-api
    このCodemodは、Next.jsのAPIルートで非同期リクエストハンドリングをサポートするようにするものです。Next.jsのAPIルートでは、リクエストのハンドリングを簡単に行えますが、このCodemodはAPIリクエストの非同期処理を最適化するために、コードを自動的に変換します。

  • next-request-geo-ip
    このCodemodは、Next.jsアプリケーションでリクエストの地理的IPデータを取得して活用するためのものです。これにより、訪問者の地域情報に基づいたパーソナライズされたコンテンツやサービスを提供することが可能になります。たとえば、国別のコンテンツ提供や、リージョンに応じたパフォーマンス最適化などのシナリオに役立ちます。

  • next-dynamic-access-named-export
    このCodemodは、Next.jsのnext/dynamicを使ってダイナミックインポートをする際に、名前付きエクスポートを正しく取り扱うためにコードを変換します。ダイナミックインポートは、アプリケーションのパフォーマンスを向上させるために使われる技術で、必要なコンポーネントだけをロードしてページの初期ロードを軽くします。この変換は、defaultエクスポートではなくnamedエクスポートを使用している場合に対応するものです。


Async Request APIs (Breaking): 簡素化されたレンダリングおよびキャッシュ モデルに向けた段階的なステップ

従来のサーバーサイド レンダリングでは、サーバーはコンテンツをレンダリングする前にリクエストを待機します。ただし、すべてのコンポーネントがリクエスト固有のデータに依存しているわけではないため、リクエストを待機してレンダリングする必要はありません。理想的には、サーバーはリクエストが到着する前に可能な限り準備します。これを可能にし、将来の最適化の準備を整えるには、リクエストをいつ待機するかを知る必要があります。


Caching Semantics (Breaking): フェッチ リクエスト、GET ルート ハンドラー、およびクライアント ナビゲーションは、デフォルトではキャッシュされなくなりました

Next.js 15では、キャッシュのデフォルト設定が変更され、GETリクエストやクライアントルーターでのキャッシュがデフォルトでは無効になりました。以前はデフォルトでキャッシュされていましたが、今後はキャッシュを利用する際には手動で設定が必要です。特定のファイル(例:sitemap.tsやopengraph-image.tsx)は静的にキャッシュされますが、dynamic設定を使用することで動的キャッシュを有効にできます。また、staleTimesフラグを使ってキャッシュのタイミングをカスタマイズ可能です。


React 19 Support: React 19、React コンパイラ (実験的)、およびハイドレーション エラーの改善をサポートします

Next.js 15は、React 19に対応し、App RouterでReact 19のRCを使用していますが、Pages RouterではReact 18との後方互換性もサポートしています。React 19は安定性が高く、プロジェクトの準備に適しています。

React Compiler (Experimental)
React コンパイラは、Meta の React チームによって作成された新しい実験的なコンパイラです。このコンパイラは、プレーンな JavaScript セマンティクスと React のルールを理解することでコードを深く理解し、コードに自動最適化を追加できます。このコンパイラは、useMemo や useCallback などの API を通じて開発者が手動でメモ化する必要のある量を減らし、コードをよりシンプルにし、保守しやすく、エラーが発生しにくくします。

Turbopack Dev (Stable): パフォーマンスと安定性の向上

next dev --turbo が安定し、開発エクスペリエンスをスピードアップできるようになりました。

turbo
turbo オプションを使用すると、Turbopack をカスタマイズしてさまざまなファイルを変換し、モジュールの解決方法を変更できます。

import type { NextConfig } from 'next'
 
const nextConfig: NextConfig = {
  turbo: {
    // ...
  },
}
 
export default nextConfig

Turbopack for Next.js では、組み込み機能のためにローダーやローダー構成は必要ありません。Turbopack には CSS のサポートと最新の JavaScript のコンパイルが組み込まれているため、@babel/preset-env を使用している場合は、css-loader、postcss-loader、または babel-loader は必要ありません。

Static Indicator: 新しい視覚的なインジケーターは開発中の静的ルートを表示します

Next.js では、開発中に静的ルート インジケーターが表示されるようになりました。これにより、どのルートが静的か動的かが識別しやすくなります。この視覚的なヒントにより、ページがどのようにレンダリングされるかを理解して、パフォーマンスを最適化しやすくなります。


unstable_after API (Experimental): レスポンスのストリーミングが終了した後にコードを実行する

ユーザーリクエストを処理する際、サーバーは通常、レスポンスの計算に直接関連するタスクを実行します。ただし、ログ記録、分析、その他の外部システム同期などのタスクを実行する必要がある場合もあります。

これらのタスクはレスポンスに直接関係しないため、ユーザーはそれらの完了を待つ必要はありません。ユーザーに応答した後に作業を延期することは、サーバーレス関数がレスポンスが閉じられた直後に計算を停止するため、課題となります。

after() は、応答のストリーミングが終了した後に処理される作業をスケジュールできるようにすることでこの問題を解決し、プライマリ応答をブロックせずにセカンダリタスクを実行できるようにする新しい実験的な API です。


instruments.js API (Stable): サーバーライフサイクルの監視のための新しい API

インストルメンテーション ファイルと register() API を使用すると、ユーザーは Next.js サーバーのライフサイクルを利用してパフォーマンスを監視し、エラーの原因を追跡し、OpenTelemetry などの観測ライブラリと深く統合することができます。

この機能は安定しており、experimental.instrumentationHook 設定オプションは削除できます。 さらに、Sentry と協力して、次の目的で使用できる新しい onRequestError フックを設計しました。

  • サーバーでスローされたすべてのエラーに関する重要なコンテキストをキャプチャします。これには以下が含まれます:

    • ルーター: Pages Router または App Router

    • サーバー コンテキスト: サーバー コンポーネント、サーバー アクション、ルート ハンドラー、またはミドルウェア

  • お気に入りの可観測性プロバイダーにエラーを報告します


Enhanced Forms (next/form): クライアント側ナビゲーションで HTML フォームを拡張します

新しい <Form> コンポーネントは、プリフェッチ、クライアント側ナビゲーション、プログレッシブエンハンスメントにより HTML <form> 要素を拡張します。
<Form> コンポーネントには以下が付属しています。

  • Prefetching: フォームが表示されているときに、レイアウトと読み込み UI がプリフェッチされ、ナビゲーションが高速化されます

  • Client-side Navigation: 送信時に、共有レイアウトとクライアント側の状態が保持されます

  • Progressive Enhancement: JavaScript がまだ読み込まれていない場合でも、フォームはフルページ ナビゲーションを介して機能します

next.config: next.config.ts の TypeScript サポート

Next.js は TypeScript next.config.ts ファイル タイプをサポートし、オートコンプリートとタイプセーフ オプション用の NextConfig タイプを提供するようになりました。

import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  /* config options here */
};
 
export default nextConfig;


Self-hosting Improvements: Cache-Control ヘッダーのより詳細な制御

アプリケーションをセルフホスティングする場合、Cache-Controlディレクティブをより細かく制御する必要があるかもしれません。

よくあるケースの 1 つは、ISR ページに送信される stale-while-revalidate 期間を制御することです。次の 2 つの改善を実装しました。

  1. next.config で expireTime 値を設定できるようになりました。これは以前は experimental.swrDelta オプションでした。

  2. デフォルト値を 1 年に更新し、ほとんどの CDN が意図したとおりに stale-while-revalidate セマンティクスを完全に適用できるようにしました。

また、カスタム Cache-Control 値をデフォルト値で上書きしなくなったため、完全な制御が可能になり、あらゆる CDN 設定との互換性が確保されます。

最後に、セルフホスティング時の画像最適化を改善しました。以前は、Next.js サーバー上の画像を最適化するために sharp をインストールすることを推奨していました。この推奨事項が無視されることもありました。Next.js 15 では、sharp を手動でインストールする必要がなくなりました。Next.js は、次回の起動時またはスタンドアロン出力モードで実行時に、sharp を自動的に使用します。

Server Actions Security:推測不可能なエンドポイントと未使用のアクションの削除

サーバー アクションは、クライアントから呼び出すことができるサーバー側の関数です。ファイルの先頭に 'use server' ディレクティブを追加し、非同期関数をエクスポートすることで定義されます。


サーバーアクションまたはユーティリティ関数がコードの他の場所にインポートされていない場合でも、それはパブリックにアクセス可能なHTTPエンドポイントです。この動作は技術的には正しいですが、そのような関数が意図せず公開される可能性があります。

セキュリティを強化するために、次の機能強化を導入しました。

  • デッドコードの排除: 使用されていないサーバーアクションの ID はクライアント側の JavaScript バンドルに公開されないため、バンドルのサイズが削減され、パフォーマンスが向上します

  • Secure action IDs: Next.jsは、推測不可能で非決定的なIDを作成し、クライアントがサーバーアクションを参照して呼び出すことができるようになりました。これらのIDは、セキュリティ強化のため、ビルド間で定期的に再計算されます

Bundling External Packages (Stable):アプリおよびページ ルーターの新しい構成オプション

外部パッケージをバンドルすると、アプリケーションのコールド スタート パフォーマンスが向上します。App Router では、外部パッケージはデフォルトでバンドルされており、新しい serverExternalPackages 構成オプションを使用して特定のパッケージをオプトアウトできます。

外部パッケージがデフォルトでバンドルされることで、初回のロード時に必要な依存関係がすでに含まれているため、アプリケーションの起動が速くなります。これにより、ユーザーが初めてアプリを使用する際や、サーバーが再起動される時などの待ち時間が短縮されます。また、serverExternalPackagesオプションは、特定のパッケージをバンドルしない選択も可能にし、パフォーマンス調整を柔軟に行えます。

Pages Router では、外部パッケージはデフォルトではバンドルされませんが、既存の transpilePackages オプションを使用してバンドルするパッケージのリストを指定できます。この構成オプションでは、各パッケージを指定する必要があります。

アプリとページ ルーター間の構成を統一するために、アプリ ルーターのデフォルトの自動バンドルに一致する新しいオプション、bundlePagesRouterDependencies を導入します。必要に応じて、serverExternalPackages を使用して特定のパッケージをオプトアウトできます。

const nextConfig = {
  // Automatically bundle external packages in the Pages Router:
  bundlePagesRouterDependencies: true,
  // Opt specific packages out of bundling for both App and Pages Router:
  serverExternalPackages: ['package-name'],
};
 
export default nextConfig;


ESLint 9 Support: ESLint 9 のサポートが追加


Next.js 15 では、2024 年 10 月 5 日に ESLint 8 のサポートが終了するのに伴い、ESLint 9 のサポートも導入されています。

スムーズな移行を確実にするために、Next.js は下位互換性を維持しており、ESLint 8 または 9 のいずれかを引き続き使用できます。

ESLint 9 にアップグレードし、新しい設定形式をまだ採用していないことが検出された場合、Next.js は移行を容易にするために ESLINT_USE_FLAT_CONFIG=false エスケープ ハッチを自動的に適用します。

Development and Build Performance: ビルド時間の改善と高速リフレッシュの高速化

Server Components HMR
開発中、サーバーコンポーネントは保存時に再実行されます。つまり、APIエンドポイントやサードパーティのサービスへのフェッチリクエストも呼び出されます

ローカル開発のパフォーマンスを向上させ、課金対象の API 呼び出しの潜在的なコストを削減するために、ホット モジュール置換 (HMR) が以前のレンダリングからのフェッチ応答を再利用できるようにしました

Faster Static Generation for the App Router
特にネットワーク リクエストが遅いページでは、静的生成を最適化してビルド時間を短縮しました。

以前は、静的最適化プロセスでページを 2 回レンダリングしていました。1 回目はクライアント側ナビゲーション用のデータを生成するため、2 回目は最初のページ訪問用の HTML をレンダリングするためです。現在は、最初のレンダリングを再利用して 2 回目のパスを省略し、作業負荷とビルド時間を削減しています。

さらに、静的生成ワーカーはページ間でフェッチキャッシュを共有するようになりました。フェッチ呼び出しがキャッシュをオプトアウトしない場合、その結果は同じワーカーによって処理される他のページで再利用されます。これにより、同じデータに対するリクエストの数が減ります。

Advanced Static Generation Control (Experimental)
より高度な制御によってメリットが得られる高度なユースケースのために、静的生成プロセスをより細かく制御するための実験的なサポートを追加しました。

これらのオプションにより、同時実行性の向上によりリソース使用量が増加し、メモリ不足エラーが発生する可能性があるため、特別な要件がない限り、現在のデフォルトを維持することをお勧めします。



いいなと思ったら応援しよう!