📈

Next 15の変更点

2024/10/28に公開

https://github.com/vercel/next.js/releases/tag/v15.0.0

@next/codemod CLIを使ったアップグレード

Next.js 15バージョンでは、@next/codemod CLIを使用してコードベースを自動で変更できるようになりました。

npx @next/codemod@canary upgrade latest

このコマンドを使用すると、現在のプロジェクトのNext.jsを最新バージョン(またはプレリリース版)にアップグレードし、必要なコード変更が自動で反映されます。

複雑な手作業を行わずに最新のNext.jsへ更新し、コード互換性も自動で保証することができます。

非同期リクエストAPI (重大な変更)

従来のSSR(サーバーサイドレンダリング)方式では、サーバーがクライアントにコンテンツを提供する前にすべてのリクエストが完了するまで待機していました。しかし、Next.js 15では効率を高めるため、必要なデータのみを非同期でリクエストし、それだけを待機する方式に変更されました。

そのため、特定のリクエストに依存するデータ(headers、cookies、params、searchParams)は、非同期APIに変換する必要があります。

@next/codemod CLIを使用すれば、コードベースを簡単にマイグレーションできます。

npx @next/codemod@canary next-async-request-api .

このCLIを通じてコード変更を進めると、以下のように変更されます。
変更前

export async function generateMetadata({
  params,
}: {
  params: { slug: string };
}): Promise<Metadata | undefined> {
  // paramsがすぐに使用可能なデータとして提供される
  const post = getAllPosts().find((post) => post.slug === params.slug);
  return { title: post.title };
}

ここでは、paramsは { slug: string }の形で即時使用できるオブジェクトとして提供されており、awaitなしでparams.slugをそのまま使用できました。
変更後

export async function generateMetadata(props: {
  params: Promise<{ slug: string }>;
}): Promise<Metadata | undefined> {
  // 今やparamsはPromiseオブジェクトのため、awaitで値を待つ
  const { slug } = await props.params;
  const post = getAllPosts().find((post) => post.slug === slug);
  return { title: post.title };
}

ここでは、paramsがPromiseオブジェクトとして提供されているため、awaitキーワードを使ってprops.paramsが返す { slug: string } データを待機してから使用する必要があります。

従来の方式ではすべてのリクエストデータが準備できるまで無条件で待機してからページをレンダリングしていたため、特定のデータが不要な場合でも待機時間が発生していました。
変更後は必要なデータだけをawaitで待機するので、不要な待機時間を減らすことができます。
これにより、必要なデータを非同期で待っている間に他のレンダリング作業を開始でき、効率が高まります。

Next.js 15の非同期処理方式は、サーバーがデータをリクエストし待機する方式を最適化し、サーバーの全体的な性能とページの読み込み速度を改善します。
サーバーはリクエストデータが準備できるまで待たずに可能な作業を先に準備することで、より早くページを応答できるようになります。

キャッシュセマンティクス

キャッシング戦略がより柔軟で詳細に調整できるように変更されました。
Next.js 14では、データがサーバーにある場合、いつでもキャッシュを利用してデータを即座に取得する方式が基本設定でした。つまり、ページやAPIデータが常にキャッシュされるため、最新のデータが即座に反映されないことがありました。

Next.js 15では、キャッシュを使用するかどうかをより詳細に設定できるようになり、基本的にキャッシュはオフの状態で、最新データを表示する方式に変わりました。これにより、以下のように状況に応じてキャッシュを調整することが可能です。

GETルートハンドラーのキャッシュ

変更前 (Next.js 14): GETリクエストを使用するAPIは基本的にキャッシュが適用され、同じデータを複数回リクエストしても迅速に取得できました。
変更後 (Next.js 15): GETリクエストのAPIはデフォルトでキャッシュを使用しないように変更され、最新データが毎回リクエストされます。
キャッシュが必要な場合: export const dynamic = "force-static"設定を追加することでキャッシュを有効化できます。たとえば、頻繁に更新されないsitemap.tsなどのファイルにはキャッシュを設定しておくと、より迅速に取得できます。

クライアントルータのキャッシュ

変更前 (Next.js 14.2): Next.jsはクライアントがページを移動する際、前のページをキャッシュして、より早くページ間を移動できるようにしていました。
変更後 (Next.js 15): ページ移動時に常に最新データが取得され、各ページで最新の情報が反映されるようになりました。

しかし、いくつかのキャッシュ動作は維持されています:

  • レイアウトデータは再リクエストされず、素早く再利用されます。
  • 前後のページ移動時、ブラウザがスクロール位置を記憶し、スクロールがそのまま維持されます。
  • loading.jsは最大5分間キャッシュされ、ローディング画面が迅速に表示されます。

next.config.tsでキャッシュ時間の設定も可能

const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30, // クライアントルータで30秒間キャッシュを維持
    },
  },
};

export default nextConfig;

ポイント

常に最新データを表示: ページ移動時は常に最新データが表示されます。
必要な場合のみキャッシュ使用: 特定のAPIやデータにキャッシュ設定を追加することで、パフォーマンスを向上できます。

React 19

React 19はまだRC(リリース候補)状態ですが、NextチームはReactチームと緊密に連携し、React 19の安定性についてReactチームから確信を得たため、Next.js 15バージョンでReact 19を適用してリリースすることになりました。

npm install babel-plugin-react-compiler
next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
export default nextConfig;

Turbopack Dev

next dev --turboは、安定して高速な開発環境を提供できるようになりました。

スタティックルートインジケーター

開発環境で、Next.js 15はスタティックルートインジケーターを提供します。このインジケーターにより、各ルートがスタティックルートかダイナミックルートかを確認できます。

サーバーアクション(関数)のセキュリティ向上

サーバーアクショuse serverは、クライアントからサーバーの特定の関数を直接呼び出せる機能ですが、クライアントに露出する可能性があるため、セキュリティ面での注意が必要です。今回の改善により、サーバーアクションがより安全に保護され、パフォーマンスも向上しました。

静的生成制御機能(Experimental)

ビルド速度を向上させるため、静的ページ生成方法を詳細に調整できる実験的オプションが追加されました。
staticGenerationRetryCount: 静的ページ生成が失敗した場合に再試行する回数を設定します。デフォルトは1で、必要な場合のみ変更することを推奨します。
staticGenerationMaxConcurrency: 各ワーカーが同時に処理できるページ数で、ビルド速度に影響を与えます。
staticGenerationMinPagesPerWorker: 新しいワーカーが開始される前に処理する最低ページ数を指定して、ワーカーリソースを最適化します。

next.config.ts
const nextConfig = {
  experimental: {
    staticGenerationRetryCount: 1,         // ビルド失敗時に1回再試行
    staticGenerationMaxConcurrency: 8,     // 各ワーカーが処理する最大ページ数
    staticGenerationMinPagesPerWorker: 25, // ワーカー開始前に処理する最低ページ数
  },
};

export default nextConfig;

その他の追加の変更点については、公式ブログのリリースノートで確認できます。
https://nextjs.org/blog/next-15

Discussion