➡️

Next.js 15 RC2 和訳

2024/10/16に公開

https://nextjs.org/blog/next-15-rc2

雑に翻訳しました。
意訳がめちゃくちゃ含まれているので注意です。


5月に最初のNext.js 15 リリース候補版を発表した後、皆さまからのフィードバックをもとに、2回目のリリース候補版を準備してきました。 以下がその内容です。

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

# 新しい自動アップグレードCLIを使用する
npx @next/codemod@canary upgrade rc
 
# もしくは手動でアップグレードする
npm install next@rc react@rc react-dom@rc

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

Next.jsのメジャーリリースには必ずcodemod(自動化されたコード変換)が含まれており、変更点のアップグレードを自動化することができます。
アップグレードをさらにスムーズにするために、改良されたcodemod CLIをリリースしました。

npx @next/codemod@canary upgrade rc

このツールは、最新の安定版またはプレリリース版へのコードベースのアップグレードを手助けします。
CLIは依存関係を更新し、利用可能なcodemodを表示し、それらを適用する手順を案内します。
コマンドラインで指定されたディストリビューションタグ(@rc、@canaryなど)が、アップグレードするバージョンを決定します。

Next.jsのcodemodsについてはこちらをご覧ください。


開発時のTurbopack

ローカル開発のためのTurbopackは、Next.js 15の正式リリースで安定版となりますが、オプトインの状態のままです。以下のコマンドを実行することで、今日からお試しいただけます。

next dev --turbo

Turbopackのベータ版とリリース候補版の期間中、テストに参加して問題を報告し、修正を確認してくれた何千人もの開発者の皆さんのおかげで、最初のNext.js 15リリース候補以来、54のGitHubの問題が解決されました。
このコミュニティの取り組みと並行して、vercel.comv0.devnextjs.orgでの内部テストも、数多くの追加改善点を特定するのに役立ちました。

ここ3ヶ月間、私たちはコールドのコンパイル性能の最適化に注力してきました。前回のリリースと比べて、以下の改善が見られました。

  • メモリ使用量が25〜35%削減されました。
  • 数千のモジュールを持つ大規模なページのコンパイルが30〜50%速くなりました。

今後のリリースでも、この分野の最適化を続けていきます。
将来に向けて、Turbopackチームは永続的なキャッシング、メモリ使用量の削減、next buildに向けたTurbopackにおいて大きな進展を遂げており、テストの96%が合格しています。


Async Request APIs (破壊的変更)

従来のサーバーサイドレンダリングでは、サーバーはコンテンツをレンダリングする前にリクエストを待ちます。
しかし、すべてのコンポーネントがリクエスト固有のデータに依存しているわけではないため、それらをレンダリングするためにリクエストを待つ必要はありません。
理想的には、サーバーはリクエストが届く前にできるだけ多くの準備をしたいと考えています。
これを実現し、将来の最適化の下地を作るために、リクエストをいつ待つべきかを知る必要があります。

そのため、headercookieparamssearchParamsなどのリクエスト固有のデータに依存する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には一時的に同期的にアクセスできますが、次のメジャーバージョンまで開発環境と本番環境で警告が表示されます。移行を自動化するためのコードモッドが提供されています。

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

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


Server Actionsの強化されたセキュリティ

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

サーバーアクションやユーティリティ関数がコード内の他の場所でインポートされていない場合でも、一般にアクセス可能なHTTPエンドポイントであることに変わりはありません。この動作は技術的には正しいものの、意図せずそのような関数が公開されてしまう可能性があります。

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

  • デッドコードの排除: 使用されていないサーバーアクションのIDはクライアント側のJavaScriptバンドルに公開されなくなり、これによりバンドルサイズが小さくなり、パフォーマンスが向上します。
  • 安全なアクションID: Next.jsは、クライアントがサーバーアクションを参照および呼び出すことを可能にするために、推測不可能かつ非決定的なIDを作成します。これらのIDは、セキュリティを強化するためにビルド間で定期的に再計算されます。
// app/actions.js
'use server';

// このアクションはアプリケーションで使用されていますので、
// Next.jsはクライアントがサーバーアクションを参照して呼び出せるように安全なIDを作成します。
export async function updateUserAction(formData) {}

// このアクションはアプリケーションで使用されていないため、
// Next.jsは`next build`時にこのコードを自動的に削除し、公開エンドポイントを作成しません。
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: これはデモンストレーションのため省略されている部分があります。
// 本番コードでの使用は推奨しません。

'use client'
 
import { useEffect } from 'react'
import { useRouter } from 'next/navigation'
 
export default function Form(props) {
  const action = props.action
  const router = useRouter()
 
  useEffect(() => {
    // フォームのターゲットがURLの場合、プリフェッチする
    if (typeof action === 'string') {
      router.prefetch(action)
    }
  }, [action, router])
 
  function onSubmit(event) {
    event.preventDefault()
 
    // すべてのフォームフィールドを取得し、データのURLをエンコードして `router.push` をトリガーする。
    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フックを設計しました。

  • サーバーで発生したすべてのエラーについて、以下のような重要なコンテキストを取得する。
    • Route: PageRouterまたはAppRouter
    • Server context: 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() {
  // お好きなオブザーバビリティプロバイダーのSDKをインストールしてください。
}

onRequestError関数の詳細については、こちらをご覧ください。


開発とビルドの改善

Server Components HMR

開発中には、保存時にサーバーコンポーネントが再実行されます。
これは、APIエンドポイントやサードパーティのサービスへのフェッチリクエストも呼び出されることを意味します。
ローカル開発のパフォーマンスを向上させ、課金されるAPIコールの潜在的なコストを削減するために、ホットモジュールリプレースメント(HMR)が以前のレンダーからのフェッチレスポンスを再利用できるようになりました。
サーバーコンポーネントのHMRキャッシュの詳細については、こちらをご覧ください。

AppRouterの静的生成の高速化

ビルド時間を改善するために静的生成を最適化しました。
特に、ネットワークのリクエストが遅いページにおいて効果的です。
以前は、静的最適化プロセスでページを2回レンダリングしていました。
1回目はクライアントサイドのナビゲーション用のデータを生成するためで、2回目は最初のページ訪問時のHTMLをレンダリングするためでした。今では、1回目のレンダリングを再利用することで2回目のプロセスを省略し、作業量とビルド時間を削減しています。

さらに、静的生成ワーカーは、今やページ間でフェッチキャッシュを共有しています。
フェッチコールでキャッシュをオプトアウトしない限り、その結果は同じワーカーが処理する他のページでも再利用されます。
これにより、同じデータに対するリクエストの数が削減されます。

静的生成の拡張(実験的)

より高度なユースケースのために、静的生成プロセスに対する制御を強化する実験的なサポートを追加しました。
これらのオプションはリソースの使用量の増加や、並行処理の増加によってメモリ不足のエラーが発生する可能性があるため、特定の要件がない限り現在のデフォルト設定を使用することをお勧めします。

const nextConfig = {
  experimental: {
	// ビルドに失敗したページ生成を何回リトライするか。
    staticGenerationRetryCount: 1
    // Worker1つあたり何ページ並列で処理するか
    staticGenerationMaxConcurrency: 8
    // 新しい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 startスタンドアロン出力モードで実行する際にNext.jsが自動的にsharpを使用します。

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


ESLint 9 サポート

Next.js 15では、2024年10月5日にESLint 8のサポートが終了するのに伴い、ESLint 9もサポートします。
スムーズな移行を保証するため、Next.jsはESLint 8と9の後方互換性を維持しています。

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

さらに、-ext-ignore-pathのような非推奨オプションはnext lint実行時に削除されます。
ESLintは最終的にESLint 10でこれらの古い設定を無効にすることに注意してください。

今回のアップデートの一環として、eslint-plugin-react-hooksv5.0.0にアップグレードし、React Hooksの使用に関する新しいルールを導入しました。 すべての変更点はeslint-plugin-react-hooks@5.0.0の変更履歴で確認できます。

PrAha

Discussion