Backブログに戻る

Next.js 15.1

Next.js 15.1ではReact 19の安定版サポート、エラーデバッグの改善、新しい実験的な認証APIなどが導入されました。

Next.js 15.1ではコアのアップグレード、新しいAPI、開発者体験の改善が行われました。主な更新点は以下の通りです:

今すぐアップグレードするか、以下のコマンドで新規プロジェクトを開始できます:

Terminal
# 自動アップグレードCLIを使用
npx @next/codemod@canary upgrade latest
 
# ...または手動でアップグレード
npm install next@latest react@latest react-dom@latest
 
# ...または新規プロジェクトを開始
npx create-next-app@latest

React 19(安定版)

Next.js 15.1ではReact 19を完全にサポート:

  • Pages Routerの場合: React 19安定版をRelease CandidateやCanaryリリースなしで使用可能(React 18のサポートも継続)。
  • App Routerの場合: React Canaryリリースを引き続き組み込みで提供。これにはReact 19の安定版変更に加え、新しいリリース前にフレームワークで検証中の新機能も含まれます。

Next.js 15リリース以降、React 19には「sibling pre-warming」が追加されました。

React 19の更新内容の詳細については、公式React 19ブログ記事を参照してください。

エラーデバッグの改善

Next.jsのエラーデバッグを改善し、ターミナル、ブラウザ、または接続されたデバッガーで問題の発生源を迅速に特定できるようになりました。これらの改善はWebpackとTurbopack(Next.js 15で安定版化)の両方に適用されます。

ソースマップの強化

ソースマップの改善により、エラーの発生源をより簡単に追跡できるようになりました。ignoreListプロパティを実装し、外部依存関係のスタックフレームを非表示にすることで、アプリケーションコードに焦点を当てやすくしました。

メソッド名のソースマッピングをより正確に行うには、Turbopack(現在安定版)の採用をお勧めします。TurbopackはWebpackよりもソースマップの処理と検出が改善されています。

ライブラリ作者向け: 特に外部設定されている場合(例: serverExternalPackages設定)、ライブラリを公開する際にソースマップのignoreListプロパティを設定することを推奨します。

折りたたみスタックフレーム

スタックフレームの折りたたみロジックを改善し、コードの最も関連性の高い部分を強調表示するようにしました。

  • ブラウザとエラーオーバーレイ: サードパーティ依存関係のスタックフレームはデフォルトで非表示になり、アプリケーションコードに集中できます。非表示のフレームはデベロッパーツールまたはオーバーレイで「無視されたフレームを表示」をクリックすると表示されます。
  • ターミナル: サードパーティ依存関係のフレームもデフォルトで折りたたまれ、エラーフォーマットがブラウザ出力と一致するようになりました。開発中に重要なスタックトレースを見逃さないよう、エラーはブラウザでも再生されます。

プロファイリングの強化

無視されたスタックフレームは組み込みのブラウザプロファイラでも認識されます。これにより、外部ライブラリのノイズなしにアプリケーションコードの遅い関数を特定しやすくなります。

Edge Runtimeの改善

Edge Runtimeを使用する場合、開発環境間でエラー表示が一貫するようになり、シームレスなデバッグが可能になりました。以前はログに記録されたエラーにはメッセージのみが含まれ、スタックは含まれていませんでした。

改善前と改善後

ターミナル 改善前:

Terminal
 app/page.tsx (6:11) @ eval
 Error: boom
    at eval (./app/page.tsx:12:15)
    at Page (./app/page.tsx:11:74)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at stringify (<anonymous>)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at AsyncResource.runInAsyncScope (node:async_hooks:206:9)
digest: "380744807"
  4 | export default function Page() {
  5 |   const throwError = myCallback(() => {
> 6 |     throw new Error('boom')
    |           ^
  7 |   }, [])
  8 |
  9 |   throwError()
 GET / 500 in 2354ms

ターミナル 改善後:

Terminal
 Error: boom
    at eval (app/page.tsx:6:10)
    at Page (app/page.tsx:5:32)
  4 | export default function Page() {
  5 |   const throwError = myCallback(() => {
> 6 |     throw new Error('boom')
    |          ^
  7 |   }, [])
  8 |
  9 |   throwError() {
  digest: '225828171'
}

エラーオーバーレイ 改善前

Next.js 15.1バージョン以前のエラーオーバーレイの例

エラーオーバーレイ 改善後

Next.js 15.1バージョン以降のエラーオーバーレイの例

これらの改善により、エラーがより明確で直感的になり、デバッグではなくアプリケーション構築に時間を集中できるようになります。

また、今後のリリースではエラーオーバーレイの再設計されたUIの導入を予定しています。

after(安定版)

Next.js 15の最初のRCで導入されたafter() APIが安定版になりました。

after()を使用すると、ロギング、分析、その他のシステム同期などのタスクを、プライマリレスポンスをブロックすることなく、ユーザーへのレスポンスストリーミング完了後に実行できます。

主な変更点

導入以来、以下のフィードバックに対応してafter()を安定化しました:

  • セルフホスト型Next.jsサーバーのサポート改善。
  • after()が他のNext.js機能と相互作用するシナリオのバグ修正
  • 他のプラットフォームが独自のwaitUntil()プリミティブを注入してafter()を強化できる拡張性の向上
  • Server ActionsやRoute Handlersでのcookies()headers()などのランタイムAPIのサポート
app/layout.js
import { after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // セカンダリタスク
  after(() => {
    log();
  });
 
  // プライマリタスク
  return <>{children}</>;
}

after APIの詳細と活用方法についてはドキュメントを参照してください。

forbiddenunauthorized(実験的)

Next.js 15.1には、コミュニティのフィードバックに基づいた2つの実験的APIforbidden()unauthorized()が含まれています。

フィードバックをお待ちしています — 開発環境で試して、ディスカッションスレッドでご意見をお聞かせください。

概要

App Routerに慣れている方は、カスタマイズ可能なnot-found.tsxファイルとともに404動作をトリガーするnotFound()を使用したことがあるでしょう。バージョン15.1では、このアプローチを認証エラーに拡張します:

forbidden()403エラーをトリガーし、forbidden.tsxでUIをカスタマイズ可能。

unauthorized()401エラーをトリガーし、unauthorized.tsxでUIをカスタマイズ可能。

知っておくと良いこと: notFound()エラーと同様に、初期レスポンスヘッダーが送信された後にエラーがトリガーされた場合、ステータスコードは200になります。詳細

機能の有効化

この機能はまだ実験的であるため、next.config.tsファイルで有効にする必要があります:

next.config.ts
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  experimental: {
    authInterrupts: true,
  },
};
 
export default nextConfig;

注: next.config.tsのサポートはNext.js 15で導入されました。詳細

forbidden()unauthorized()の使用

forbidden()unauthorized()はServer Actions、Server Components、Client Components、またはRoute Handlersで使用できます。以下は例です:

import { verifySession } from '@/app/lib/dal';
import { forbidden } from 'next/navigation';
 
export default async function AdminPage() {
  const session = await verifySession();
 
  // ユーザーが'admin'ロールを持っているか確認
  if (session.role !== 'admin') {
    forbidden();
  }
 
  // 認可されたユーザー向けに管理ページをレンダリング
  return <h1>Admin Page</h1>;
}

カスタムエラーページの作成

エラーページをカスタマイズするには、以下のファイルを作成します:

app/forbidden.tsx
import Link from 'next/link';
 
export default function Forbidden() {
  return (
    <div>
      <h2>アクセス拒否</h2>
      <p>このリソースにアクセスする権限がありません。</p>
      <Link href="/">ホームに戻る</Link>
    </div>
  );
}
app/unauthorized.tsx
import Link from 'next/link';
 
export default function Unauthorized() {
  return (
    <div>
      <h2>未認証</h2>
      <p>このページにアクセスするにはログインしてください。</p>
      <Link href="/login">ログインページへ</Link>
    </div>
  );
}

この機能をPRで提案し、APIのプロトタイピングを支援してくれたClerkに感謝します。15.2でこの機能を安定化する前に、より広範なユースケースをサポートするため、APIにさらに機能と改善を追加する予定です。

unauthorizedforbidden APIの詳細についてはドキュメントを参照してください。

その他の変更

  • [機能] create-next-appでESLint 9を使用(PR
  • [機能] キャッシュタグの最大数を128に増加(PR
  • [機能] 実験的CssChunkingPluginを無効化するオプション追加(PR
  • [機能] 実験的CSSインライン化サポート追加(PR
  • [改善] Sassのlegacy-js-api警告を抑制(PR
  • [改善] リライト使用時の未処理拒否を修正(PR
  • [改善] webpackワーカーが失敗した場合に親プロセスが確実に終了するように(PR
  • [改善] catch-allルートでのルートインターセプトを修正(PR
  • [改善] リクエスト重複排除でのレスポンスクローン問題を修正(PR
  • [改善] 複数ルートレイアウト間のServer Actionリダイレクトをサポート(PR
  • [改善] Turbopack互換性のためにMDXプラグインを文字列として提供可能に(PR

コントリビューター

Next.jsは3,000人以上の開発者の共同作業の成果です。このリリースは以下の方々によってもたらされました:

@sokra, @molebox, @delbaoliveira, @eps1lon, @wbinnssmith, @JamBalaya56562, @hyungjikim, @adrian-faustino, @mottox2, @lubieowoce, @bgw, @mknichel, @wyattjoh, @huozhi, @kdy1, @mischnic, @ijjk, @icyJoseph, @acdlite, @unstubbable, @gaojude, @devjiwonchoi, @cena-ko, @lforst, @devpla, @samcx, @styfle, @ztanner, @Marukome0743, @timneutkens, @JeremieDoctrine, @ductnn, @karlhorky, @reynaldichernando, @chogyejin, @y-yagi, @philparzer, @alfawal, @Rhynden, @arlyon, @MJez29, @Goodosky, @themattmayfield, @tobySolutions, @kevinmitch14, @leerob, @emmanuelgautier, @mrhrifat, @lid0a, @boar-is, @nisabmohd, @PapatMayuri, @ovogmap, @Reflex2468, @LioRael, @betterthanhajin, @HerringtonDarkholme, @bpb54321, @ahmoin, @Kikobeats, @abdelrahmanAbouelkheir, @lumirlumir, @yeeed711, @petter, @suu3の皆さん、ご協力ありがとうございました!