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

2024年1月18日 木曜日

Next.js 14.1

投稿者

Next.js 14.1 には、開発者エクスペリエンスの改善が含まれています。具体的には以下の通りです。

今日アップグレードするか、以下から始めましょう。

ターミナル
npx create-next-app@latest

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

Node.js サーバー、Docker コンテナ、または静的エクスポートを使用して Next.js をセルフホストする方法についてのフィードバックを受け、明確化に努めてきました。セルフホスティングのドキュメントを全面的に見直しました。

Next.js 14.1 では、App Router 向けのインクリメンタル静的再生成 (ISR) およびより詳細なデータキャッシュのカスタムキャッシュハンドラーの提供を安定化しました。

next.config.js
module.exports = {
  cacheHandler: require.resolve('./cache-handler.js'),
  cacheMaxMemorySize: 0, // disable default in-memory caching
};

Kubernetes のようなコンテナオーケストレーションプラットフォームを使用する場合、各 Pod がキャッシュのコピーを持つため、セルフホスティング時にこの構成を使用することが重要です。カスタムキャッシュハンドラーを使用すると、Next.js アプリケーションをホストするすべての Pod 間で一貫性を確保できます。

例えば、キャッシュされた値を Redis や Memcached など、どこにでも保存できます。@neshcaRedis キャッシュハンドラーアダプター とその例に感謝します。

Turbopack の改善

ローカルでの Next.js 開発の信頼性とパフォーマンスに引き続き注力しています。

  • 信頼性: Turbopack が Next.js 開発テストスイート全体に合格し、Vercel のアプリケーションでも内部使用 (dogfooding) されています。
  • パフォーマンス: Turbopack の初回コンパイル時間と Fast Refresh の時間を改善
  • メモリ使用量: Turbopack のメモリ使用量を改善

next dev --turbo は、今後のリリースで安定化する予定ですが、引き続きオプトインとなります。

信頼性

Turbopack は、Next.js 開発テストスイート全体に合格しました (94%)。これは前回のアップデートから 600 件増加しています。進捗状況は areweturboyet.com で確認できます。

Vercel のすべての Next.js アプリケーション (vercel.comv0.app を含む) で next dev --turbo の内部使用 (dogfooding) を継続しています。これらのアプリケーションに取り組むすべてのエンジニアが毎日 Turbopack を使用しています。

Turbopack を使用する非常に大規模な Next.js アプリケーションで、いくつかの問題を発見し修正しました。これらの修正のため、既存の Next.js 開発テストスイートに新しいテストを追加しました。

パフォーマンス

vercel.com という大規模な Next.js アプリケーションで、以下の改善が見られました。

  • ローカルサーバー起動時間が最大 76.7% 高速化
  • Fast Refresh によるコード更新が最大 96.3% 高速化
  • 初回ルートコンパイル時間がキャッシュなしで最大 45.8% 高速化 (Turbopack はまだディスクキャッシュを備えていません)

v0.app では、React Client Component の検出とバンドリング方法を最適化できる機会を見つけました。これにより、初回コンパイル時間が最大 61.5% 短縮されました。このパフォーマンス向上は、vercel.com でも観測されました。

今後の改善

Turbopack は現在インメモリキャッシュを備えており、Fast Refresh のインクリメンタルコンパイル時間を改善します。

しかし、現在のところキャッシュは Next.js 開発サーバーを再起動しても保持されません。Turbopack のパフォーマンスにおける次の大きなステップはディスクキャッシュであり、これにより開発サーバーの再起動時にキャッシュを保持できるようになります。

開発者エクスペリエンスの改善

エラーメッセージの改善と Fast Refresh

ローカル開発エクスペリエンスにおいて、明確なエラーメッセージがいかに重要であるかは承知しています。next dev を実行した際に表示されるスタックトレースとエラーメッセージの質を向上させるため、数多くの修正を行いました。

  • 以前は webpack-internal のようなバンドラーエラーが表示されていたエラーでも、エラーのソースコードと影響を受けるファイルが正しく表示されるようになりました。
  • クライアントコンポーネントでエラーが発生した後、エディタでエラーを修正しても Fast Refresh でエラー画面がクリアされず、ハードリロードが必要でした。これらのインスタンスのいくつかを修正しました。例えば、クライアントコンポーネントから metadata をエクスポートしようとした場合などです。

例えば、これは以前のエラーメッセージでした。

An example of an error from a fetch call in Next.js 14.
Next.js 14 でのフェッチ呼び出しのエラー例。

Next.js 14.1 では、これを以下のように改善しました。

Errors from fetch calls during rendering now display the source code of the error and the affected file.
レンダリング中のフェッチ呼び出しからのエラーが、エラーのソースコードと影響を受けるファイルを表示するようになりました。

window.history.pushState および window.history.replaceState

App Router で、ページをリロードせずにブラウザの履歴スタックを更新できるネイティブな pushState および replaceState メソッドが使用できるようになりました。

pushState および replaceState の呼び出しは Next.js App Router と統合され、usePathname および useSearchParams と同期させることができます。

これは、フィルター、ソート順、またはリロード間で保持したいその他の情報などの状態を保存する際に、URL を即座に更新する必要がある場合に役立ちます。

'use client';
 
import { useSearchParams } from 'next/navigation';
 
export default function SortProducts() {
  const searchParams = useSearchParams();
 
  function updateSorting(sortOrder: string) {
    const params = new URLSearchParams(searchParams.toString());
    params.set('sort', sortOrder);
    window.history.pushState(null, '', `?${params.toString()}`);
  }
 
  return (
    <>
      <button onClick={() => updateSorting('asc')}>Sort Ascending</button>
      <button onClick={() => updateSorting('desc')}>Sort Descending</button>
    </>
  );
}

Next.js でのネイティブ History API の使用方法については、こちらをご覧ください。

データキャッシュのロギング

next dev を実行した際の Next.js アプリケーションでのキャッシュデータの可観測性を向上させるため、logging 設定オプションに数多くの改善を加えました。

キャッシュの HIT または SKIP、およびリクエストされた完全な URL を表示できるようになりました。

ターミナル
GET / 200 in 48ms
  Compiled /fetch-cache in 117ms
 GET /fetch-cache 200 in 165ms
   GET https://api.vercel.app/products/1 200 in 14ms (cache: HIT)
  Compiled /fetch-no-store in 150ms
 GET /fetch-no-store 200 in 548ms
   GET https://api.vercel.app/products/1 200 in 345ms (cache: SKIP)
      Cache missed reason: (cache: no-store)

これは next.config.js 経由で有効にできます。

next.config.js
module.exports = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
};

next/image での <picture> およびアートディレクションのサポート

Next.js Image コンポーネントは、<Image> を直接使用する必要がない getImageProps() (安定版) を通じて、より高度なユースケースをサポートするようになりました。これには以下が含まれます。

  • background-image または image-set との連携
  • キャンバスの context.drawImage() または new Image() との連携
  • <picture> メディアクエリを使用して、アートディレクション またはライト/ダークモードの画像を実装
import { getImageProps } from 'next/image';
 
export default function Page() {
  const common = { alt: 'Hero', width: 800, height: 400 };
  const {
    props: { srcSet: dark },
  } = getImageProps({ ...common, src: '/dark.png' });
  const {
    props: { srcSet: light, ...rest },
  } = getImageProps({ ...common, src: '/light.png' });
 
  return (
    <picture>
      <source media="(prefers-color-scheme: dark)" srcSet={dark} />
      <source media="(prefers-color-scheme: light)" srcSet={light} />
      <img {...rest} />
    </picture>
  );
}

getImageProps() については こちらをご覧ください。

並列ルーティングとインターセプトルーティング

Next.js 14.1 では、並列ルーティングとインターセプトルーティングに20 件の改善を行いました。

過去 2 回のリリースでは、Next.js のパフォーマンスと信頼性の向上に注力してきました。現在、並列ルーティング および インターセプトルーティング に多くの改善を加えました。特に、キャッチオールルートと Server Actions のサポートを追加しました。

  • 並列ルーティングを使用すると、同じレイアウト内で 1 つ以上のページを同時にまたは条件付きでレンダリングできます。ダッシュボードやソーシャルサイトのフィードなど、アプリの高度に動的なセクションでは、複雑なルーティングパターンを実装するために並列ルーティングを使用できます。
  • インターセプトルーティングを使用すると、現在のレイアウト内でアプリケーションの別の部分からルートを読み込むことができます。例えば、フィード内の写真をクリックすると、フィードをオーバーレイしてモーダルで写真を表示できます。この場合、Next.js は /photo/123 ルートをインターセプトし、URL をマスクして /feed の上にオーバーレイします。

並列ルーティングとインターセプトルーティングについては こちらまたは例をこちらでご覧いただけます (例を表示)。

その他の改善点

14.0 以降、コミュニティから多くのアップボートがあったバグをいくつか修正しました。

最近、キャッシュ に関する動画や、App Router に関するよくある間違い についての動画も公開しました。これらが参考になるかもしれません。

  • [ドキュメント] リダイレクト に関する新しいドキュメント
  • [ドキュメント] テスト に関する新しいドキュメント
  • [ドキュメント] 本番環境チェックリスト に関する新しいドキュメント
  • [機能] next/third-parties<GoogleAnalytics /> コンポーネントを追加 (ドキュメント)
  • [改善] create-next-app がより小さく、インストールが高速になりました (PR)
  • [改善] ネストされたルートでエラーが発生しても、global-error でキャッチできます (PR)
  • [改善] サーバーアクションで使用される redirect は、basePath を尊重するようになりました (PR)
  • [改善] App Router での next/script および beforeInteractive の使用を修正 (PR)
  • [改善] @aws-sdk および lodash を自動的にトランスパイルして、ルート起動を高速化 (PR)
  • [改善] next dev および next/font でのスタイル未適応コンテンツのフラッシュを修正 (PR)
  • [改善] セグメントのエラー境界を越えて notFound エラーを伝播 (PR)
  • [改善] Pages Router i18n でロケールドメインからの公開ファイルの提供を修正 (PR)
  • [改善] 無効な revalidate 値が渡された場合にエラーを表示 (PR)
  • [改善] Windows で作成されたビルドが Linux マシンでパスの問題を起こすのを修正 (PR)
  • [改善] basePath を使用するマルチゾーンアプリでの Fast Refresh / HMR を修正 (PR)
  • [改善] 終了シグナルからの正常なシャットダウンを改善 (PR)
  • [改善] 異なるルートからインターセプトする際に、モーダルルートが競合する問題を修正 (PR)
  • [改善] basePath 設定で使用する際のインターセプトルートを修正 (PR)
  • [改善] 並列スロットが見つからない場合に 404 が発生する際の警告を表示 (PR)
  • [改善] キャッチオールルートと併用する際のインターセプトルートを改善 (PR)
  • [改善] revalidatePath と併用する際のインターセプトルートを改善 (PR)
  • [改善] 並列ルートでの @children スロットの使用を修正 (PR)
  • [改善] 並列ルートでの params 使用時の TypeError を修正 (PR)
  • [改善] デフォルトの並列ルートでのキャッチオールルート正規化を修正 (PR)
  • [改善] next build サマリーでの並列ルート表示を修正 (PR)
  • [改善] インターセプトルートとルートパラメータ使用時の問題を修正 (PR)
  • [改善] 深くネストされた並列/インターセプトルートを改善 (PR)
  • [改善] ルートグループとペアになったインターセプトルートでの 404 エラーを修正 (PR)
  • [改善] サーバーアクション / ルーターキャッシュの再検証との並列ルートでの使用を修正 (PR)
  • [改善] インターセプトルートと rewrites を使用した場合の修正 (PR)
  • [改善] サーバーアクションがサードパーティライブラリから動作するようになりました (PR)
  • [改善] Next.js が ESM パッケージ内で使用できるようになりました (PR)
  • [改善] Material UI などのライブラリのバレルファイル最適化 (PR)
  • [改善] Suspense なしで useSearchParams を誤って使用した場合、ビルド時にエラーが表示されるようになります (PR)

コントリビューター

Next.js は、3,000 人以上の個々の開発者、Google や Meta といった業界パートナー、そして Vercel のコアチームの共同作業の成果です。コミュニティにご参加ください。 GitHub DiscussionsReddit、そして Discord で。

このリリースは、以下の方々によってもたらされました。

そして、@OlehDutchenko, @eps1lon, @ebidel, @janicklas-ralph, @JohnPhamous, @chentsulin, @akawalsky, @BlankParticle, @dvoytenko, @smaeda-ks, @kenji-webdev, @rv-david, @icyJoseph, @dijonmusters, @A7med3bdulBaset, @jenewland1999, @mknichel, @kdy1, @housseindjirdeh, @max-programming, @redbmk, @SSakibHossain10, @jamesmillerburgess, @minaelee, @officialrajdeepsingh, @LorisSigrist, @yesl-kim, @StevenKamwaza, @manovotny, @mcexit, @remcohaszing, @ryo-manba, @TranquilMarmot, @vinaykulk621, @haritssr, @divquan, @IgorVaryvoda, @LukeSchlangen, @RiskyMH, @ash2048, @ManuWeb3, @msgadi, @dhayab, @ShahriarKh, @jvandenaardweg, @DestroyerXyz, @SwitchBladeAK, @ianmacartney, @justinh00k, @tiborsaas, @ArianHamdi, @li-jia-nan, @aramikuto, @jquinc30, @samcx, @Haosik, @AkifumiSato, @arnabsen, @nfroidure, @clbn, @siddtheone, @zbauman3, @anthonyshew, @alexfradiani, @CalebBarnes, @adk96r, @pacexy, @hichemfantar, @michaldudak, @redonkulus, @k-taro56, @mhughdo, @tknickman, @shumakmanohar, @vordgi, @hamirmahal, @gaspar09, @JCharante, @sjoerdvanBommel, @mass2527, @N-Ziermann, @tordans, @davidthorand, @rmathew8-gh, @chriskrogh, @shogunsea, @auipga, @SukkaW, @agustints, @OXXD, @clarencepenz, @better-salmon, @808vita, @coltonehrman, @tksst, @hugo-syn, @JakobJingleheimer, @Willem-Jaap, @brandonnorsworthy, @jaehunn, @jridgewell, @gtjamesa, @mugi-uno, @kentobento, @vivianyentran, @empflow, @samennis1, @mkcy3, @suhaotian, @imevanc, @d3lm, @amannn, @hallatore, @Dylan700, @mpsq, @mdio, @christianvuerings, @karlhorky, @simonhaenisch, @olci34, @zce, @LavaToaster, @rishabhpoddar, @jirihofman, @codercor, @devjiwonchoi, @JackieLi565, @thoushif, @pkellner, @jpfifer, @quisido, @tomfa, @raphaelbadia, @j9141997, @hongaar, @MadCcc, @luismulinari, @dumb-programmer, @nonoakij, @franky47, @robbertstevens, @bryndyment, @marcosmartini, @functino, @Anisi, @AdonisAgelis, @seangray-dev, @prkagrawal, @heloineto, @kn327, @ihommani, @MrNiceRicee, @falsepopsky, @thomasballinger, @tmilewski, @Vadman97, @dnhn, @RodrigoTomeES, @sadikkuzu, @gffuma, @Schniz, @joulev, @Athrun-Judah, @rasvanjaya21, @rashidul0405, @nguyenbry, @Mwimwii, @molebox, @mrr11k, @philwolstenholme, @IgorKowalczyk, @Zoe-Bot, @HanCiHu, @JackHowa, @goncy, @hirotomoyamada, @pveyes, @yeskunall, @ChendayUP, @hmaesta, @ajz003, @its-kunal, @joelhooks, @blurrah, @tariknh, @Vinlock, @Nayeem-XTREME, @aziyatali, @aspehler, and @moka-ayumu の貢献。