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

2024年10月15日(火)

Next.js 15 RC 2

投稿者

5月に発表された最初のNext.js 15 Release Candidate以来、皆様からのフィードバックに基づき、2番目のRelease Candidateを準備してきました。今回取り組んできたことの概要は以下の通りです。

本日、Next.js 15 Release Candidate (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

注意: このRelease Candidateには、前回のRCのすべての変更が含まれています。

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

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

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

npx @next/codemod@canary upgrade rc

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

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

開発用Turbopack

ローカル開発用のTurbopackはNext.js 15の一般リリースで安定版になりますが、オプトインのままです。次のコマンドを実行して、本日試すことができます。

next dev --turbo

テストに参加し、問題を報告し、Turbopackのベータ版およびリリース候補段階での修正を確認してくれた何千人もの開発者に感謝します。最初のNext.js 15 Release Candidate以降、54件のGitHubイシューを解決しました。このコミュニティの努力に加えて、vercel.comv0.app、および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.jsgenerateMetadata、およびgenerateViewportparams
  • page.jssearchParams

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

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

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

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

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

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

セキュリティを強化するために、以下の改善を導入しました。

  • デッドコード削除: 未使用のサーバーアクションは、クライアントサイドJavaScriptバンドルにIDが公開されないため、バンドルサイズが削減され、パフォーマンスが向上します。
  • 安全なアクション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(安定版)

instrumentationファイルとregister() APIは、ユーザーが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レスポンスを再利用できるようにしました。

サーバーコンポーネントHMRキャッシュについてさらに詳しく学ぶ。

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ディレクティブをより詳細に制御する必要がある場合があります。

一般的なケースは、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.jsは、next startを使用する場合や、スタンドアロン出力モードで実行する場合にsharpを自動的に使用します。

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

ESLint 9サポート

Next.js 15では、ESLint 8の2024年10月5日の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/dynamicssr: falseオプションの使用を禁止します(PR)。
  • [改善] outputFileTracingRootoutputFileTracingIncludes、およびoutputFileTracingExcludesが実験的段階からアップグレードされ、安定版になりました(PR)。
  • [改善] グローバルCSSファイルとツリーの奥深くにあるCSSモジュールファイルのマージを回避します(PR)。
  • [改善] キャッシュハンドラーは、NEXT_CACHE_HANDLER_PATH環境変数で指定できます(PR)。
  • [改善] Pages Routerは、React 18とReact 19の両方をサポートします(PR)。
  • [改善] インスペクターが有効な場合、エラーオーバーレイにNode.jsインスペクターURLをコピーするボタンが表示されるようになります(PR)。
  • [改善] App Routerでのクライアントプリフェッチがpriority属性を使用するようになります(PR)。
  • [改善] Next.jsは、App RouterでNext.js内部エラーを再スローするためのunstable_rethrow関数を提供するようになりました(PR)。
  • [改善] unstable_afterは、静的ページでも使用できるようになりました(PR)。
  • [改善] SSR中にnext/dynamicコンポーネントが使用される場合、チャンクがプリフェッチされます(PR)。
  • [改善] App RouterでesmExternalsオプションがサポートされるようになりました(PR)。
  • [改善] experimental.allowDevelopmentBuildオプションを使用して、デバッグ目的でnext buildNODE_ENV=developmentを許可できます(PR)。
  • [改善] Server Actionの変換は、Pages Routerで無効になります(PR)。
  • [改善] ビルドワーカーは、終了時にビルドがハングするのを防ぐようになります(PR)。
  • [改善] Server Actionからのリダイレクト時、再検証が正しく適用されるようになります(PR)。
  • [改善] Edge Runtimeでの並列ルートの動的パラメータが正しく処理されるようになります(PR)。
  • [改善] 静的ページは、初期ロード後にstaleTimeを尊重するようになります(PR)。
  • [改善] vercel/ogのメモリリーク修正(PR)。
  • [改善] パッチタイミングが更新され、APIモックにmswのようなパッケージを使用できるようになりました(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 の皆様、ありがとうございました!