Next.js 15.1ではコアのアップグレード、新しいAPI、開発者体験の改善が行われました。主な更新点は以下の通りです:
- React 19(安定版): Pages RouterとApp Routerの両方でReact 19の公式サポートが利用可能になりました。
- エラーデバッグの改善: 開発者体験の向上とブラウザ・ターミナル向けのソースマップの改善。
after
(安定版): レスポンスのストリーミング完了後にコードを実行する新しいAPI。forbidden
/unauthorized
(実験的): より詳細な認証エラーハンドリングを可能にする新しいAPI。
今すぐアップグレードするか、以下のコマンドで新規プロジェクトを開始できます:
# 自動アップグレード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を使用する場合、開発環境間でエラー表示が一貫するようになり、シームレスなデバッグが可能になりました。以前はログに記録されたエラーにはメッセージのみが含まれ、スタックは含まれていませんでした。
改善前と改善後
ターミナル 改善前:
⨯ 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
ターミナル 改善後:
⨯ 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'
}
エラーオーバーレイ 改善前

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

これらの改善により、エラーがより明確で直感的になり、デバッグではなくアプリケーション構築に時間を集中できるようになります。
また、今後のリリースではエラーオーバーレイの再設計されたUIの導入を予定しています。
after
(安定版)
Next.js 15の最初のRCで導入されたafter()
APIが安定版になりました。
after()
を使用すると、ロギング、分析、その他のシステム同期などのタスクを、プライマリレスポンスをブロックすることなく、ユーザーへのレスポンスストリーミング完了後に実行できます。
主な変更点
導入以来、以下のフィードバックに対応してafter()
を安定化しました:
- セルフホスト型Next.jsサーバーのサポート改善。
after()
が他のNext.js機能と相互作用するシナリオのバグ修正。- 他のプラットフォームが独自の
waitUntil()
プリミティブを注入してafter()
を強化できる拡張性の向上。 - Server ActionsやRoute Handlersでの
cookies()
やheaders()
などのランタイムAPIのサポート。
import { after } from 'next/server';
import { log } from '@/app/utils';
export default function Layout({ children }) {
// セカンダリタスク
after(() => {
log();
});
// プライマリタスク
return <>{children}</>;
}
after
APIの詳細と活用方法についてはドキュメントを参照してください。
forbidden
とunauthorized
(実験的)
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
ファイルで有効にする必要があります:
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>;
}
カスタムエラーページの作成
エラーページをカスタマイズするには、以下のファイルを作成します:
import Link from 'next/link';
export default function Forbidden() {
return (
<div>
<h2>アクセス拒否</h2>
<p>このリソースにアクセスする権限がありません。</p>
<Link href="/">ホームに戻る</Link>
</div>
);
}
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にさらに機能と改善を追加する予定です。
unauthorized
とforbidden
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人以上の開発者の共同作業の成果です。このリリースは以下の方々によってもたらされました:
- Next.jsチーム: Andrew, Hendrik, Janka, Jiachi, Jimmy, Jiwon, JJ, Josh, Jude, Sam, Sebastian, Sebbie, Wyatt, Zack.
- Turbopackチーム: Alex, Benjamin, Donny, Maia, Niklas, Tim, Tobias, Will.
- Next.js Docsチーム: Delba, Rich, Ismael, Lee.
@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の皆さん、ご協力ありがとうございました!