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

2024年10月15日 火曜日

Next.js 15 RC 2

投稿者

5月に最初のNext.js 15リリース候補が発表されて以来、皆様からのフィードバックに基づいて2番目のリリース候補を準備してきました。私たちが取り組んできた内容は以下の通りです。

Next.js 15 リリース候補 (RC2) を今すぐお試しください

# Use the new automated upgrade CLI
npx @next/codemod@canary upgrade rc
 
# ...or upgrade manually
npm install next@rc react@rc react-dom@rc

注意: このリリース候補には、以前のRCからのすべての変更が含まれています。

codemod CLIによるスムーズなアップグレード

Next.jsのメジャーリリースごとに、破壊的変更のアップグレードを自動化するためのcodemods(自動コード変換)が含まれています。

アップグレードをさらにスムーズにするために、強化されたcodemod CLIをリリースしました。

npx @next/codemod@canary upgrade rc

このツールは、コードベースを最新の安定版またはプレリリース版にアップグレードするのに役立ちます。CLIは依存関係を更新し、利用可能なcodemodsを表示し、それらを適用する手順を案内します。コマンドラインで指定されたdistタグ(@rc@canaryなど)によって、アップグレードするバージョンが決まります。

Next.js codemodsについて詳しく学ぶ。

開発用Turbopack

ローカル開発用のTurbopackは、Next.js 15の一般リリースで安定版となり、引き続きオプトインとなります。今すぐ実行して試すことができます。

next dev --turbo

Turbopackのベータ版およびリリース候補フェーズを通じて、テストに参加し、問題を報告し、修正を検証してくださった数千人の開発者の皆様のおかげで、最初のNext.js 15リリース候補以降、54件のGitHub issueを解決しました。このコミュニティの努力に加え、vercel.comv0.dev、およびnextjs.orgでの内部テストにより、多数の追加改善が特定されました。

過去3ヶ月間で、コールドコンパイルのパフォーマンス最適化に注力しました。前回のリリースと比較して、以下の改善が見られました。

  • メモリ使用量が25~35%削減
  • 数千のモジュールを含む大規模ページのコンパイルが30~50%高速化

今後のリリースでもこれらの領域の最適化を継続します。

今後、Turbopackチームは永続的なキャッシュ、メモリ使用量の削減、およびnext build用Turbopackの大きな進展を遂げており、96%のテストが合格しています。

注意: Turbopackのサポートされている機能とサポートされていない機能のすべてを参照してください。

非同期リクエストAPI (破壊的変更)

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

したがって、headerscookiesparamssearchParamsなど、リクエスト固有のデータに依存するAPIを非同期に移行しています。

import { cookies } from 'next/headers';
 
export async function AdminPanel() {
  const cookieStore = await cookies();
  const token = cookieStore.get('token');
 
  // ...
}

これは破壊的変更であり、以下のAPIに影響します。

  • cookies
  • headers
  • draftMode
  • layout.jspage.jsroute.jsdefault.jsgenerateMetadatagenerateViewportにおけるparams
  • page.jsにおけるsearchParams

移行を容易にするため、これらのAPIは一時的に同期的にアクセスできますが、次期メジャーバージョンまでは開発環境および本番環境で警告が表示されます。移行を自動化するためのcodemodが利用可能です。

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

codemodでコードを完全に移行できない場合は、アップグレードガイドをお読みください。また、Next.jsアプリケーションを新しいAPIに移行する方法のも提供しています。

サーバーアクションのセキュリティ強化

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

サーバーアクションやユーティリティ関数がコード内の他の場所でインポートされていなくても、それらは依然として公開されたHTTPエンドポイントです。この動作は技術的には正しいですが、意図しない関数の露出につながる可能性があります。

セキュリティを向上させるために、以下の強化を行いました。

  • デッドコード除去: 未使用のサーバーアクションは、そのIDがクライアントサイドのJavaScriptバンドルに公開されず、バンドルサイズの削減とパフォーマンスの向上が図られます。
  • 安全なアクションID: Next.jsは、クライアントがサーバーアクションを参照および呼び出すことを可能にするために、推測不可能な非決定的なIDを作成するようになりました。これらのIDは、セキュリティ強化のためにビルド間で定期的に再計算されます。
// app/actions.js
'use server';
 
// This action **is** used in our application, so Next.js
// will create a secure ID to allow the client to reference
// and call the Server Action.
export async function updateUserAction(formData) {}
 
// This action **is not** used in our application, so Next.js
// will automatically remove this code during `next build`
// and will not create a public endpoint.
export async function deleteUserAction(formData) {}

サーバーアクションは引き続き公開HTTPエンドポイントとして扱う必要があります。サーバーアクションの保護について詳しく学ぶ。

静的ルートインジケーター

Next.jsは、開発中に静的ルートインジケーターを表示するようになり、どのルートが静的であるか動的であるかを簡単に識別できるようになりました。この視覚的な手がかりは、ページのレンダリング方法を理解することで、パフォーマンスを最適化するのに役立ちます。

next buildの出力を使用して、すべてのルートのレンダリング戦略を確認することもできます。

この更新は、Next.jsの可観測性を向上させ、開発者がアプリケーションを監視、デバッグ、最適化しやすくするための継続的な取り組みの一環です。また、専用の開発者ツールの開発も進めており、詳細については近日中に発表予定です。

無効にできる静的ルートインジケーターについて詳しく学ぶ。

<Form>コンポーネント

新しい<Form>コンポーネントは、HTMLの<form>要素をプリフェッチクライアントサイドナビゲーション、およびプログレッシブエンハンスメントで拡張します。

これは、検索フォームが結果ページに移動するなど、新しいページに移動するフォームに役立ちます。

import Form from 'next/form';
 
export default function Page() {
  return (
    <Form action="/search">
      <input name="query" />
      <button type="submit">Submit</button>
    </Form>
  );
}

<Form>コンポーネントには以下の機能があります。

  • プリフェッチ: フォームが表示されると、レイアウトロードUIがプリフェッチされ、高速なナビゲーションが可能になります。
  • クライアントサイドナビゲーション: 送信時に、共有レイアウトとクライアントサイドの状態が保持されます。
  • プログレッシブエンハンスメント: JavaScriptがまだロードされていない場合でも、フォームはフルページナビゲーション経由で機能します。

以前は、これらの機能を実現するには多くの手動での定型文が必要でした。例えば、

// Note: This is abbreviated for demonstration purposes.
// Not recommended for use in production code.
 
'use client'
 
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
 
export default function Form(props) {
  const action = props.action
  const router = useRouter()
 
  useEffect(() => {
    // if form target is a URL, prefetch it
    if (typeof action === 'string') {
      router.prefetch(action)
    }
  }, [action, router])
 
  function onSubmit(event) {
    event.preventDefault()
 
    // grab all of the form fields and trigger a `router.push` with the data URL encoded
    const formData = new FormData(event.currentTarget)
    const data = new URLSearchParams()
 
    for (const [name, value] of formData) {
      data.append(name, value as string)
    }
 
    router.push(`${action}?${data.toString()}`)
  }
 
  if (typeof action === 'string') {
    return <form onSubmit={onSubmit} {...props} />
  }
 
  return <form {...props} />
}

<Form>コンポーネントについて詳しく学ぶ。

next.config.tsのサポート

Next.jsはTypeScriptのnext.config.tsファイルタイプをサポートし、オートコンプリートと型安全なオプションのためのNextConfig型を提供します。

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

Next.jsのTypeScriptサポートについて詳しく学ぶ。

instrumentation.js (安定版)

register() APIを持つinstrumentationファイルは、ユーザーがNext.jsサーバーのライフサイクルにアクセスしてパフォーマンスを監視したり、エラーの原因を追跡したり、OpenTelemetryのような可観測性ライブラリと深く統合したりすることを可能にします。

この機能は安定版となり、experimental.instrumentationHook設定オプションは削除できます。

さらに、Sentryと協力して、以下の目的で使用できる新しいonRequestErrorフックを設計しました。

  • サーバーでスローされたすべてのエラーに関する重要なコンテキストをキャプチャします(以下を含む)。
    • ルーター: Pages Router または App Router
    • サーバーコンテキスト: Server Component、Server Action、Route Handler、または Middleware
  • お気に入りの可観測性プロバイダにエラーを報告する。
export async function onRequestError(err, request, context) {
  await fetch('https://...', {
    method: 'POST',
    body: JSON.stringify({ message: err.message, request, context }),
    headers: { 'Content-Type': 'application/json' },
  });
}
 
export async function register() {
  // init your favorite observability provider SDK
}

onRequestError関数について詳しく学ぶ。

開発とビルドの改善

サーバーコンポーネントHMR

開発中、サーバーコンポーネントは保存時に再実行されます。これは、APIエンドポイントまたはサードパーティサービスへのfetchリクエストも呼び出されることを意味します。

ローカル開発のパフォーマンスを向上させ、請求されるAPI呼び出しの潜在的なコストを削減するため、Hot Module Replacement (HMR) が以前のレンダリングからのfetchレスポンスを再利用できるようにしました。

Server Components HMR Cacheについて詳しく学ぶ。

App Routerの静的生成の高速化

静的生成を最適化し、特にネットワークリクエストが遅いページのビルド時間を改善しました。

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

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

高度な静的生成制御 (実験的)

より詳細な制御が必要な高度なユースケースのために、静的生成プロセスをさらに制御できる実験的サポートを追加しました。

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

const nextConfig = {
  experimental: {
	  // how many times Next.js will retry failed page generation attempts
	  // before failing the build
    staticGenerationRetryCount: 1
    // how many pages will be processed per worker
    staticGenerationMaxConcurrency: 8
    // the minimum number of pages before spinning up a new export worker
    staticGenerationMinPagesPerWorker: 25
  },
}
 
export default nextConfig;

静的生成オプションについて詳しく学ぶ。

セルフホスティングの改善

アプリケーションをセルフホストする場合、Cache-Controlディレクティブをより詳細に制御する必要がある場合があります。

一般的なケースの1つは、ISRページに送信されるstale-while-revalidate期間の制御です。2つの改善を実装しました。

  1. next.configexpireTimeの値を設定できるようになりました。これは以前、experimental.swrDeltaオプションでした。
  2. デフォルト値を1年に更新し、ほとんどのCDNが意図したとおりにstale-while-revalidateセマンティクスを完全に適用できるようにしました。

また、カスタムのCache-Control値をデフォルト値で上書きすることもやめ、完全な制御とあらゆるCDN設定との互換性を確保しました。

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

詳細については、Next.jsのセルフホスティングに関する新しいデモとチュートリアルビデオをご覧ください。

ESLint 9のサポート

Next.js 15は、2024年10月5日にESLint 8がEOLを迎えることを受けて、ESLint 9のサポートも導入しています。

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

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

さらに、next lintの実行時に--ext--ignore-pathなどの非推奨オプションは削除されます。ESLint 10ではこれらの古い設定が最終的に許可されなくなるため、早めの移行を開始することを推奨します。

これらの変更の詳細については、移行ガイドを確認してください。

このアップデートの一環として、eslint-plugin-react-hooksv5.0.0にアップグレードしました。これにより、React Hooksの使用に関する新しいルールが導入されます。すべての変更はeslint-plugin-react-hooks@5.0.0の変更ログで確認できます。

その他の変更点

  • 以前RC 1のブログ投稿で説明されたすべての変更点
  • [破壊的変更] App Routerでのexport const runtime = "experimental-edge"のエクスポートは非推奨になりました。ユーザーはexport const runtime = "edge"に切り替える必要があります。これを実行するためのcodemodが追加されました(PR
  • [破壊的変更] レンダリング中にrevalidateTagrevalidatePathを呼び出すとエラーが発生するようになりました(PR
  • [破壊的変更] instrumentation.jsおよびmiddleware.jsファイルは、ベンダー提供のReactパッケージを使用するようになりました(PR
  • [破壊的変更] 必要なNode.jsの最小バージョンが18.18.0に更新されました(PR
  • [破壊的変更] next/dynamic:非推奨のsuspenseプロップが削除され、コンポーネントがApp Routerで使用される場合、空のSuspense境界は挿入されなくなりました(PR
  • [破壊的変更] Edge Runtimeでモジュールを解決する際、workerモジュール条件は適用されなくなります(PR
  • [破壊的変更] Server Componentsでのnext/dynamicとのssr: falseオプションの使用が許可されなくなりました(PR
  • [改善] outputFileTracingRootoutputFileTracingIncludesoutputFileTracingExcludesが実験的から安定版にアップグレードされました(PR
  • [改善] グローバルCSSファイルとCSSモジュールファイルがツリーのより深いところでマージされるのを回避します(PR
  • [改善] キャッシュハンドラはNEXT_CACHE_HANDLER_PATH環境変数で指定できるようになりました(PR
  • [改善] Pages RouterはReact 18とReact 19の両方をサポートするようになりました(PR
  • [改善] エラーオーバーレイは、Node.js Inspectorが有効な場合、Inspector URLをコピーするためのボタンを表示するようになりました(PR
  • [改善] App Routerでのクライアントプリフェッチは、priority属性を使用するようになりました(PR
  • [改善] Next.jsは、App RouterでNext.js内部エラーを再スローするためのunstable_rethrow関数を提供するようになりました(PR
  • [改善] unstable_afterは静的ページで使用できるようになりました(PR
  • [改善] SSR中にnext/dynamicコンポーネントが使用される場合、チャンクはプリフェッチされます(PR
  • [改善] esmExternalsオプションがApp Routerでサポートされるようになりました(PR
  • [改善] experimental.allowDevelopmentBuildオプションは、デバッグ目的でnext buildとともにNODE_ENV=developmentを許可するために使用できます(PR
  • [改善] Pages Routerでサーバーアクションの変換が無効になりました(PR
  • [改善] ビルドワーカーは、終了時にビルドがハングアップするのを阻止するようになりました(PR
  • [改善] Server Actionからのリダイレクト時、再検証が正しく適用されるようになりました(PR
  • [改善] Edge Runtimeでの並列ルートにおける動的パラメータが正しく処理されるようになりました(PR
  • [改善] 静的ページは初回ロード後もstaleTimeを尊重するようになりました(PR
  • [改善] vercel/ogがメモリリーク修正で更新されました(PR
  • [改善] mswのようなAPIモックパッケージの使用を可能にするために、パッチのタイミングが更新されました(PR

貢献者

Next.jsは、3,000人以上の個々の開発者とVercelのコアチームの共同作業の成果です。今回のリリースは以下のチームによって提供されました。

@huozhi、@shuding、@wyattjoh、@PaulAsjes、@mcnaveen、@timneutkens、@stipsan、@aktoriukas、@sirTangale、@greatvivek11、@sokra、@anatoliik-lyft、@wbinnssmith、@coltonehrman、@hungdoansy、@kxlow、@ztanner、@manovotny、@leerob、@ryota-murakami、@ijjk、@pnutmath、@feugy、@Jeffrey-Zutt、@wiesson、@eps1lon、@devjiwonchoi、@Ethan-Arrowood、@kenji-webdev、@domdomegg、@samcx、@Jaaneek、@evanwinter、@kdy1、@balazsorban44、@feedthejim、@ForsakenHarmony、@kwonoj、@delbaoliveira、@xiaohanyu、@dvoytenko、@bobaaaaa、@bgw、@gaspar09、@souporserious、@unflxw、@kiner-tang、@Ehren12、@EffectDoplera、@IAmKushagraSharma、@Auxdible、@sean-rallycry、@jeanmax1me、@unstubbable、@NilsJacobsen、@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、@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、@tokkiyaa、@arlyon、@lorensr、@Juneezee、@Sayakie、@IGassmann、@bosconian-dynamics、@phryneas、@akazwz、@atik-persei、@shubh73、@alpedia0、@chogyejin、@notomo、@ArnoldVanN、@dhruv-kaushik、@kevva、@Kahitar、@anay-208、@boris-szl、@devnyxie、@LorisSigrist、@M-YasirGhaffar、@Lada496、@kippmr、@torresgol10、@pkiv、@Netail、@jontewks、@ArnaudFavier、@chrisjstott、@mratlamwala、@mayank1513、@karlkeefer、@kshehadeh、@Marukome0743、@a89529294、@anku255、@KeisukeNagakawa、@andrii-bodnar、@aldosch、@versecafe、@steadily-worked、@cfrank、@QiuranHu、@farsabbutt、@joostmeijles、@saltcod、@archanaagivale30、@crutchcorn、@crebelskydico、@Maaz-Ahmed007、@jophy-ye、@remcohaszing、@JoshuaKGoldberg、@creativoma、@GyoHeon、@SukkaW、@MaxLeiter、@neila-a、@stylessh、@Teddir、@ManuLpz4、@Julian-Louis、@syi0808、@mert-duzgun、@amannn、@MonstraG、@hamirmahal、@tariknh、@Kikobeats、@LichuAcu、@Kuboczoch、@himself65、@Sam-Phillemon9493、@Shruthireddy04、@Hemanshu-Upadhyay、@timfuhrmann、@controversial、@pathliving、@mischnic、@mauroaccornero、@NavidNourani、@allanchau、@ekremkenter、@yurivangeffen、@gnoff、@darthmaim、@gdborton、@Willem-Jaap、@KentoMoriwaki、@TrevorSayre、@marlier、@Luluno01、@xixixao、@domin-mnd、@niketchandivade、@N2D4、@kjugi、@luciancah、@mud-ali、@codeSTACKr、@luojiyin1987、@mehmetozguldev、@ronanru、@tknickman、@joelhooks、@khawajaJunaid、@rubyisrust、@abdull-haseeb、@bewinsnw、@housseindjirdeh、@li-jia-nan、@aralroca、@s-ekai、@ah100101、@jantimon、@jordienr、@iscekic、@Strift、@slimbde、@nauvalazhar、@HughHzyb、@guisehn、@wesbos、@OlyaPolya、@paarthmadan、@AhmedBaset、@dineshh-m、@avdeev、@Bhavya031、@MildTomato、@Bjornnyborg、@amikofalvy、@yosefbeder、@kjac、@woutvanderploeg、@Ocheretovich、@ProchaLu、@luismiramirez、@omahs、@theoludwig、@abhi12299、@sommeeeer、@lumirlumir、@royalfig、@iampoul、@molebox、@txxxxc、@zce、@mamuso、@kahlstrm、@vercel-release-bot、@zhawtof、@PapatMayuri、@PlagueFPS、@IDNK2203、@jericopulvera、@liby、@CannonLock、@timfish、@whatisagi、@none23、@haouvw、@Pyr33x、@SouthLink、@frydj、@CrutchTheClutch、@sleevezip、@r34son、@yunsii、@md-rejoyan-islam、@kartheesan05、@nattui、@KonkenBonken、@weicheng95、@brekk、@Francoscopic、@B33fb0n3、@ImDR、@nurullah、@hdodov、@ebCrypto、@soedirgo、@floriangosse、@Tim-Zj、@raeyoung-kim、@erwannbst、@DerTimonius、@hirotomoyamada、@Develliot、@chandanpasunoori、@vicb、@ankur-dwivedi、@kidonng、@baeharam、@AnaTofuZ、@coderfin、@xugetsu、@alessiomaffeis、@kutsan、@jordyfontoura、@sebmarkbage、@tranvanhieu01012002、@jlbovenzo、@Luk-z、@jaredhan418、@bangseongbeom、@penicillin0、@neoFinch、@DeepakBalaraman、@Manoj-M-S、@Unsleeping、@lonr、@Aerilym、@ytori、@acdlite、@actopas、@n-ii-ma、@adcichowski、@mobeigi、@JohnGemstone、および@jjm2317に多大なる感謝を申し上げます!