コンテンツへスキップ
ブログに戻る

2024年5月23日木曜日

Next.js 15 RC

投稿者

Next.js 15 Release Candidate (RC) が公開されました。この早期バージョンでは、次期安定版リリースに先立ち、最新の機能をテストできます。

  • React: React 19 RC、React Compiler (Experimental) のサポート、およびハイドレーションエラーの改善
  • キャッシュ: `fetch` リクエスト、`GET` ルートハンドラー、クライアントナビゲーションはデフォルトでキャッシュされなくなりました
  • Partial Prerendering (Experimental): 段階的な導入を可能にする新しいLayoutとPageの設定オプション
  • `next/after` (Experimental): レスポンスのストリーミングが完了した後にコードを実行するための新しいAPI
  • `create-next-app`: 更新されたデザインと、ローカル開発でTurbopackを有効にするための新しいフラグ
  • 外部パッケージのバンドル (Stable): App RouterとPages Routerの新しい設定オプション

今すぐNext.js 15 RCをお試しください

ターミナル
npm install next@rc react@rc react-dom@rc

React 19 RC

Next.js App Routerは、フレームワーク向けのReact canary channel上に構築されており、v19リリース前に開発者がこれらの新しいReact APIを使用し、フィードバックを提供できるようにしました。

Next.js 15 RCは、React 19 RCをサポートしました。これには、Actionsのようなクライアントとサーバー両方の新機能が含まれています。

詳細については、Next.js 15 アップグレードガイドReact 19 アップグレードガイド、およびReact Conf 基調講演をご覧ください。

注意: 一部のサードパーティライブラリは、まだReact 19と互換性がない場合があります。

React Compiler (Experimental)

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

Next.js 15では、React Compilerのサポートを追加しました。

`babel-plugin-react-compiler`をインストールする

ターミナル
npm install babel-plugin-react-compiler

次に、`next.config.js` に `experimental.reactCompiler` オプションを追加します

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: true,
  },
};
 
module.exports = nextConfig;

オプションで、コンパイラを「オプトイン」モードで実行するように設定できます

next.config.ts
const nextConfig = {
  experimental: {
    reactCompiler: {
      compilationMode: 'annotation',
    },
  },
};
 
module.exports = nextConfig;

注意: React Compilerは現在、Next.jsではBabelプラグインを通じてのみ使用可能であり、ビルド時間が遅くなる可能性があります。

React Compiler、および利用可能なNext.jsの設定オプションについて詳しくはこちら。

ハイドレーションエラーの改善

Next.js 14.1はエラーメッセージとハイドレーションエラーを改善しました。Next.js 15は、より改善されたハイドレーションエラー表示を追加することで、これらの改善を継続します。ハイドレーションエラーは、エラーのソースコードと、その問題に対処するための提案を表示するようになりました。

例えば、これはNext.js 14.1での以前のハイドレーションエラーメッセージです

Hydration error message in Next.js 14.1

Next.js 15 RCでは、これが次のように改善されました

Hydration error message improved in Next.js 15 RC

キャッシュの更新

Next.js App Routerは、独自のキャッシュデフォルト設定でリリースされました。これらは、必要に応じてオプトアウトする機能とともに、デフォルトで最もパフォーマンスの高いオプションを提供するために設計されました。

皆様からのフィードバックに基づき、私たちはキャッシュのヒューリスティックと、Partial Prerendering (PPR)のようなプロジェクトや`fetch`を使用するサードパーティライブラリとの連携について再評価しました。

Next.js 15では、`fetch` リクエスト、`GET` ルートハンドラー、およびクライアントルーターキャッシュのキャッシュデフォルトを、デフォルトでキャッシュする設定から、デフォルトでキャッシュしない設定に変更します。以前の動作を維持したい場合は、引き続きキャッシュをオプトインできます。

今後数ヶ月にわたりNext.jsのキャッシュを改善し続け、Next.js 15 GAの発表で詳細をお伝えします。

`fetch` リクエストはデフォルトでキャッシュされなくなりました

Next.jsは、サーバーサイドの`fetch`リクエストがフレームワークの永続的なHTTPキャッシュとどのように連携するかを設定するために、Web `fetch` API のキャッシュオプションを使用します

fetch('https://...', { cache: 'force-cache' | 'no-store' });
  • `no-store` - リモートサーバーから毎回リソースをフェッチし、キャッシュを更新しません
  • `force-cache` - キャッシュからリソースをフェッチするか(存在する場合)、リモートサーバーからフェッチしてキャッシュを更新します

Next.js 14では、動的関数または動的設定オプションが使用されない限り、`cache` オプションが提供されていない場合、`force-cache` がデフォルトで使用されていました。

Next.js 15では、`cache` オプションが提供されていない場合、`no-store` がデフォルトで使用されます。これは、fetchリクエストがデフォルトでキャッシュされなくなることを意味します。

`fetch` リクエストのキャッシュを有効にするには、以下の方法があります。

`GET` ルートハンドラーはデフォルトでキャッシュされなくなりました

Next 14では、`GET` HTTPメソッドを使用するルートハンドラーは、動的関数または動的設定オプションを使用しない限り、デフォルトでキャッシュされていました。Next.js 15では、`GET` 関数はデフォルトでキャッシュされません

`export dynamic = 'force-static'`のような静的ルート設定オプションを使用して、キャッシュをオプトインすることは引き続き可能です。

`sitemap.ts`と`opengraph-image.tsx``icon.tsx`、およびその他のメタデータファイルは、動的関数または動的設定オプションを使用しない限り、デフォルトで静的なままです。

クライアントルーターキャッシュはデフォルトでPageコンポーネントをキャッシュしなくなりました

Next.js 14.2.0では、Router Cacheのカスタム設定を可能にする実験的な`staleTimes`フラグを導入しました。

Next.js 15では、このフラグは引き続きアクセス可能ですが、デフォルトの動作をPageセグメントの`staleTime`を`0`にするように変更しています。これにより、アプリ内をナビゲートする際に、クライアントはナビゲーションの一部としてアクティブになるPageコンポーネントからの最新データを常に反映するようになります。ただし、変更されない重要な動作もいくつかあります。

  • 共有レイアウトデータは、部分的なレンダリングをサポートし続けるためにサーバーから再フェッチされません。
  • 戻る/進むナビゲーションは、ブラウザがスクロール位置を復元できるように、引き続きキャッシュから復元されます。
  • `Loading.js`は5分間(または`staleTimes.static`設定の値)キャッシュされたままになります。

以下の設定を行うことで、以前のクライアントルーターキャッシュの動作をオプトインできます。

next.config.ts
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
    },
  },
};
 
module.exports = nextConfig;

Partial Prerenderingの段階的な導入 (Experimental)

Next.js 14では、同じページで静的レンダリングと動的レンダリングを組み合わせる最適化であるPartial Prerendering (PPR)を導入しました。

Next.jsは現在、`cookies()`、`headers()`、およびキャッシュされていないデータリクエストなどの動的関数を使用しない限り、静的レンダリングをデフォルトとしています。これらのAPIは、ルート全体を動的レンダリングにオプトインさせます。PPRを使用すると、任意の動的UIをSuspense境界でラップできます。新しいリクエストが来ると、Next.jsはすぐに静的なHTMLシェルを提供し、同じHTTPリクエスト内で動的な部分をレンダリングしてストリーミングします。

段階的な導入を可能にするため、特定のLayoutsおよびPagesをPPRにオプトインするための`experimental_ppr` ルート設定オプションを追加しました。

app/page.jsx
import { Suspense } from "react"
import { StaticComponent, DynamicComponent } from "@/app/ui"
 
export const experimental_ppr = true
 
export default function Page() {
  return {
     <>
	     <StaticComponent />
	     <Suspense fallback={...}>
		     <DynamicComponent />
	     </Suspense>
     </>
  };
}

新しいオプションを使用するには、`next.config.js` ファイルの`experimental.ppr` 設定を`'incremental'` に設定する必要があります。

next.config.ts
const nextConfig = {
  experimental: {
    ppr: 'incremental',
  },
};
 
module.exports = nextConfig;

すべてのセグメントでPPRが有効になったら、`ppr` 値を `true` に設定して、アプリ全体および将来のすべてのルートでPPRを有効にすることが安全とみなされます。

PPRロードマップの詳細については、Next.js 15 GAのブログ記事で共有します。

詳細については、Partial Prerenderingをご覧ください。

`next/after`によるレスポンス後のコード実行 (Experimental)

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

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

`after()`は、レスポンスのストリーミングが完了した後に処理される作業をスケジュールできるようにすることで、この問題を解決する新しい実験的なAPIです。これにより、メインのレスポンスをブロックすることなくセカンダリタスクを実行できます。

これを使用するには、`next.config.js`に`experimental.after`を追加します

next.config.ts
const nextConfig = {
  experimental: {
    after: true,
  },
};
 
module.exports = nextConfig;

次に、Server Components、Server Actions、Route Handlers、またはMiddlewareで関数をインポートします。

import { unstable_after as after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Secondary task
  after(() => {
    log();
  });
 
  // Primary task
  return <>{children}</>;
}

詳細については、`next/after`をご覧ください。

`create-next-app`の更新

Next.js 15では、`create-next-app` を新しいデザインに更新しました。

New design for create-next-app in Next.js 15 RC

`create-next-app`を実行すると、ローカル開発でTurbopackを有効にするかどうかを尋ねる新しいプロンプトが表示されます(デフォルトは`No`です)。

ターミナル
 Would you like to use Turbopack for next dev?  No / Yes

`--turbo`フラグを使用してTurbopackを有効にできます。

ターミナル
npx create-next-app@rc --turbo

新しいプロジェクトをさらに簡単に開始できるように、新しい`--empty`フラグがCLIに追加されました。これにより、余分なファイルやスタイルが削除され、最小限の「Hello World」ページが作成されます。

ターミナル
npx create-next-app@rc --empty

外部パッケージのバンドル最適化 (Stable)

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

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

App RouterとPages Router間の設定を統一するために、App Routerのデフォルトの自動バンドルに合わせる新しいオプション`bundlePagesRouterDependencies`を導入します。その後、必要に応じて`serverExternalPackages`を使用して特定のパッケージをオプトアウトできます。

next.config.ts
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'],
};
 
module.exports = nextConfig;

詳細については、外部パッケージの最適化をご覧ください。

その他の変更

  • [破壊的変更] 最小Reactバージョンが19 RCになりました
  • [破壊的変更] next/image: `squoosh`を削除し、`sharp`をオプションの依存関係として使用 (PR)
  • [破壊的変更] next/image: デフォルトの`Content-Disposition`を`attachment`に変更 (PR)
  • [破壊的変更] next/image: `src`に先頭または末尾のスペースがある場合にエラー (PR)
  • [破壊的変更] Middleware: 推奨されないReact APIのインポートを制限するために`react-server`条件を適用 (PR)
  • [破壊的変更] next/font: 外部`@next/font`パッケージのサポートを削除 (PR)
  • [破壊的変更] next/font: `font-family`ハッシュ化を削除 (PR)
  • [破壊的変更] キャッシュ: `force-dynamic`がfetchキャッシュに`no-store`のデフォルトを設定するようになりました (PR)
  • [破壊的変更] 設定: `swcMinify` (PR)、`missingSuspenseWithCSRBailout` (PR)、および`outputFileTracing` (PR) の動作をデフォルトで有効にし、非推奨のオプションを削除
  • [破壊的変更] Speed Insightsの自動計装を削除(現在は専用の@vercel/speed-insightsパッケージを使用する必要あり) (PR)
  • [破壊的変更] 動的サイトマップルートの`.xml`拡張子を削除し、開発環境と本番環境のサイトマップURLを整合させる (PR)
  • [改善] メタデータ: Vercelでホストされている場合の`metadataBase`の環境変数フォールバックを更新 (PR)
  • [改善] `optimizePackageImports`からの名前空間と名前付きインポートが混在する際のツリーシェイキングを修正 (PR)
  • [改善] 並列ルート: 不一致のキャッチオールルートにすべての既知のパラメーターを提供 (PR)
  • [改善] Config `bundlePagesExternals`が安定版となり、`bundlePagesRouterDependencies`に名称変更
  • [改善] Config `serverComponentsExternalPackages`が安定版となり、`serverExternalPackages`に名称変更
  • [改善] create-next-app: 新しいプロジェクトはデフォルトですべての`.env`ファイルを無視する (PR)
  • [ドキュメント] 認証ドキュメントを改善 (PR)
  • [ドキュメント] `@next/env` パッケージ (PR)

詳細については、アップグレードガイドをご覧ください。

貢献者

Next.jsは、3,000人を超える個人開発者、GoogleやMetaなどの業界パートナー、そしてVercelのコアチームの共同作業の成果です。このリリースは以下のチームによって提供されました。

ご協力いただいた@devjiwonchoi、@ijjk、@Ethan-Arrowood、@sokra、@kenji-webdev、@wbinnssmith、@huozhi、@domdomegg、@samcx、@Jaaneek、@evanwinter、@wyattjoh、@kdy1、@balazsorban44、@feedthejim、@ztanner、@ForsakenHarmony、@kwonoj、@delbaoliveira、@stipsan、@leerob、@shuding、@xiaohanyu、@timneutkens、@dvoytenko、@bobaaaaa、@bgw、@gaspar09、@souporserious、@unflxw、@kiner-tang、@Ehren12、@EffectDoplera、@IAmKushagraSharma、@Auxdible、@sean-rallycry、@Jeffrey-Zutt、@eps1lon、@jeanmax1me、@unstubbable、@NilsJacobsen、@PaulAsjes、@adiguno、@ryan-nauman、@zsh77、@KagamiChan、@steveluscher、@MehfoozurRehman、@vkryachko、@chentsulin、@samijaber、@begalinsaf、@FluxCapacitor2、@lukahartwig、@brianshano、@pavelglac、@styfle、@symant233、@HristovCodes、@karlhorky、@jonluca、@jonathan-ingram、@mknichel、@sopranopillow、@Gomah、@imddc、@notrab、@gabrielrolfsen、@remorses、@AbhiShake1、@agadzik、@ryota-murakami、@rishabhpoddar、@rezamauliadi、@IncognitoTGT、@webtinax、@BunsDev、@nisabmohd、@z0n、@bennettdams、@joeshub、@n1ckoates、@srkirkland、@RiskyMH、@coopbri、@okoyecharles、@diogocapela、@dnhn、@typeofweb、@davidsa03、@imranolas、@lubieowoce、@maxhaomh、@mirasayon、@blvdmitry、@hwangstar156、@lforst、@emmerich、@christian-bromann、@Lsnsh、@datner、@hiro0218、@flybayer、@ianmacartney、@ypessoa、@ryohidaka、@icyJoseph、@Arinji2、@lovell、@nsams、@Nayeem-XTREME、@JamBalaya56562、@Arindam200、@gaojude、@qqww08、@todor0v、@coltonehrman、および@wiessonに心から感謝いたします!