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

2021年10月26日 火曜日

Next.js 12

投稿者

Next.js Confで発表した通り、Next.js 12はこれまでで最大のリリースです。

本日、npm i next@latestを実行してアップデートしてください。

Rustコンパイラによる高速なビルドとFast Refresh

すべてのNext.jsアプリケーションのプロダクションビルドを高速化し、ローカル開発で即座にフィードバックを得たいと考えています。Next.js 12には、ネイティブコンパイルを活用する全く新しいRustコンパイラが含まれています。

当社のRustコンパイラは、次世代の高速なツールプラットフォームであるSWC上に構築されています。ローカルでのリフレッシュは約3倍、プロダクション向けビルドは約5倍高速化されました。その他の改善点と機能には以下が含まれます。

Results from using the new Rust compiler with large Next.js codebases.
新しいRustコンパイラを大規模なNext.jsコードベースで使用した結果。
  • 大規模コードベース向けのさらなる高速化: 世界最大規模のNext.jsコードベースのいくつかとRustコンパイラを検証しました。
  • パフォーマンスの可観測性の向上: Next.jsは、クライアントとサーバーの両方のコンパイルについて、コンソールにFast Refreshのタイミングを出力するようになりました。これには、コンパイルされたモジュールとファイルの数が含まれます。
  • 基盤となるwebpackの改善: Fast Refreshの最適化やオンデマンドエントリの信頼性向上など、webpackに多数の改善を加えました。

Rustを使用したコンパイルはBabelより17倍高速で、Next.js 12ではデフォルトで有効になっており、JavaScriptおよびTypeScriptファイルの変換を置き換えます。これにより、Next.jsのBabel変換をRustに移植する必要があり、styled-jsx変換を実装するために使用されるRust製の全く新しいCSSパーサーも含まれます。

新しいRustコンパイラには下位互換性があります。既存のBabel設定がある場合は、自動的にオプトアウトされます。styled-componentsemotionrelayなどの人気ライブラリのパースは、まもなく移植する予定です。カスタムのBabelセットアップを使用している場合は、設定を共有してください

ミニファイのためにRustコンパイラを使用することもできます。これはTerserより7倍高速です。ミニファイは、長年のインフラを置き換えるため、十分に検証されるまではオプトインとなります。

next.config.js
module.exports = {
  swcMinify: true,
};

SWCの作成者であるDongYoon Kangと、Maia TeegardenParcelへのコントリビューター)を雇用することに加え、当社はRustエコシステムへの投資を継続しています。Rustでの開発経験をお持ちの方は、ぜひチームへの参加をご応募ください

詳細については、Next.js Confでのデモをご覧ください

Middlewareの導入

Middlewareを使用すると、設定ではなくコードで対応できるようになります。これにより、リクエストが完了する前にコードを実行できるため、Next.jsで完全な柔軟性が得られます。ユーザーからのリクエストに基づいて、書き換え、リダイレクト、ヘッダーの追加、さらにはHTMLのストリーミングによってレスポンスを変更できます。

Middleware gives you complete flexibility inside Next.js.
Middlewareは、Next.js内で完全な柔軟性をもたらします。

Middlewareは、一連のページでロジックを共有するあらゆる目的に使用できます。これには以下が含まれます。

Middlewareは、fetchなどの標準Web APIをサポートする厳格なランタイムを使用します。これはnext startを使用してすぐに機能し、Edge Middlewareを使用するVercelのようなEdgeプラットフォームでも機能します。

Next.jsでMiddlewareを使用するには、pages/_middleware.jsファイルを作成します。この例では、標準のWeb API Response(MDN)を使用します。

pages/_middleware.js
export function middleware(req, ev) {
  return new Response('Hello, world!');
}

詳細については、Next.js Confでのデモをご覧くださいと、ドキュメントをご確認ください

React 18への準備

React 18では、Suspense、自動更新バッチング、startTransitionのようなAPI、そしてReact.lazyをサポートするサーバーレンダリング用の新しいストリーミングAPIといった機能が追加されます。

FacebookのReactチームと密接に協力し、React 18の安定版リリースに向けてNext.jsの準備を進めてきました。Next.js 12では、これらの機能を実験的フラグの下で今すぐお試しいただけます。

ターミナル
npm install react@alpha react-dom@alpha

サーバーサイドストリーミング

React 18の並行機能には、サーバーサイドのSuspenseの組み込みサポートとSSRストリーミングサポートが含まれています。これにより、HTTPストリーミングを使用してページをサーバーレンダリングできます。これはNext.js 12の実験的な機能ですが、有効にするとSSRはMiddlewareと同じ厳格なランタイムを使用します。

有効にするには、実験的フラグconcurrentFeatures: trueを使用してください。

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
  },
};

React Server Components

React Server Componentsを使用すると、コンポーネント自体を含め、すべてをサーバー上でレンダリングできます。これは、サーバーでHTMLを事前に生成するサーバーサイドレンダリングとは根本的に異なります。Server Componentsでは、クライアントサイドのJavaScriptが一切不要で、ページのレンダリングが高速化されます。これにより、サーバーレンダリングの最高の部分とクライアントサイドのインタラクティブ性を組み合わせることで、アプリケーションのユーザーエクスペリエンスが向上します。

next.config.js
module.exports = {
  experimental: {
    concurrentFeatures: true,
    serverComponents: true,
  },
};

Next.jsでは、JSXとしてすべて表現された、コンポーネントレベルでのデータフェッチングが可能になりました。React Server Componentsを使用することで、物事を簡素化できます。getServerSidePropsgetStaticPropsのような特別な関数はもはや不要です。これは、データフェッチングをコンポーネントと併置するReact Hooksのモデルに沿っています。

任意のNext.jsページを.server.jsにリネームすることで、Server Componentを作成し、クライアントコンポーネントをServer Components内に直接インポートできます。これらのクライアントコンポーネントはハイドレートされ、インタラクティブになるため、高評価のような機能を追加できます。

現在、Next.jsでのサーバーサイドSuspense、選択的ハイドレーション、ストリーミングレンダリングに取り組んでおり、今後のブログ記事で進捗を共有します。

React 18およびServer Componentsに関するGoogle Auroraチームの共同作業者であるKara EricksonGerald Monacoに感謝します。

詳細については、Next.js Confでのデモをご覧くださいと、ドキュメントをご確認ください

ESモジュールサポートとURLインポート

ESモジュールは、JavaScriptに公式かつ標準化されたモジュールシステムをもたらします。これらは主要なすべてのブラウザとNode.jsでサポートされています。

この標準は、パッケージサイズとJavaScriptバンドルの小型化を可能にすることでWebエコシステムを前進させ、最終的に優れたユーザーエクスペリエンスにつながります。JavaScriptエコシステムがCommon JS(古い標準)からESモジュールに移行する中、私たちは不要な破壊的変更なしに、開発者がこれらの改善を段階的に採用できるよう支援することに尽力しています。

Next.js 11.1以降、CommonJSモジュールよりもESモジュールが優先される実験的サポートを追加しました。Next.js 12では、これがデフォルトになりました。CommonJSのみを提供するNPMモジュールのインポートは引き続きサポートされています。

URLインポート

Next.js 12には、URLを介してESモジュールをインポートする実験的サポートが含まれており、インストールや個別のビルドステップは不要です。

URLインポートを使用すると、どのパッケージでもURLを介して直接使用できます。これにより、Next.jsはリモートのHTTP(S)リソースをローカル依存関係とまったく同じように処理できます。

URLインポートが検出されると、Next.jsはリモートリソースを追跡するためにnext.lockファイルを生成します。URLインポートはローカルにキャッシュされるため、オフラインでも作業を続けることができます。Next.jsはクライアントとサーバーの両方のURLインポートをサポートしています。

オプトインするには、許可されたURLプレフィックスをnext.config.js内に追加します。

next.config.js
module.exports = {
  experimental: {
    urlImports: ['https://cdn.skypack.dev'],
  },
};

次に、URLから直接モジュールをインポートできます。

import confetti from 'https://cdn.skypack.dev/canvas-confetti';

ESモジュールを提供するすべてのCDNが動作します。これには、Framerのようなノーコードおよびデザインツールも含まれます。

詳細については、Next.js Confでのデモをご覧くださいと、ドキュメントをご確認ください

ボット対応ISRフォールバック

現在、fallback: trueを使用したIncremental Static Regenerationは、まだ生成されていないページへの最初のリクエストでページコンテンツをレンダリングする前に、フォールバック状態をレンダリングします。ページの読み込み(サーバーレンダリング)をブロックするには、fallback: 'blocking'を使用する必要があります。

Next.js 12では、ウェブクローラー(例:検索ボット)は、fallback: trueを使用してISRページを自動的にサーバーレンダリングしますが、クローラー以外のユーザーエージェントにはフォールバック状態の以前の動作を提供します。これにより、クローラーが読み込み状態をインデックスすることを防ぎます。

AVIFを使用したより小さい画像

組み込みの画像最適化APIがAVIF画像をサポートし、WebPと比較して画像を20%小さくできるようになりました。

AVIF画像はWebPと比較して最適化に時間がかかる場合があるため、この機能はnext.config.jsの新しいimages.formatsプロパティを使用してオプトインとしました。

next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
};

このフォーマットのリストは、リクエストのAcceptヘッダーを使用して、オンデマンドで最適化された画像フォーマットを決定するために使用されます。AVIFが最初にあるため、ブラウザがAVIFをサポートしている場合はAVIFが提供されます。サポートされていない場合は、ブラウザがWebPをサポートしていればWebPが提供されます。どちらのフォーマットもサポートされていない場合は、元の画像フォーマットが提供されます。

出力ファイルのトレース

Next.js 8では、targetオプションを導入しました。これにより、ビルド時にwebpackを使用してすべての依存関係をバンドルし、Next.jsページをスタンドアロンのJavaScriptバンドルとして出力することが可能になりました。しかし、これが理想的ではないことにすぐに気づき、代わりに@vercel/nftを作成しました。@vercel/nftは、Vercelプラットフォーム上のすべてのデプロイで2年以上にわたり使用されています。

現在、これらの改善をデフォルトでNext.jsフレームワークに直接導入しており、すべてのデプロイプラットフォーム向けに、targetオプションよりも大幅に改善されたアプローチを提供します。

Next.js 12は、@vercel/nftを使用して各ページとAPIルートに必要なファイルを自動的にトレースし、これらのトレース結果をnext buildの出力の横に出力するため、インテグレーターはNext.jsが自動的に提供するトレースを活用できます。

これらの変更は、next startを介してDockerのようなツールを使用してデプロイするアプリケーションも最適化します。@vercel/nftを活用することで、将来的にはNext.jsの出力をスタンドアロンにすることができます。アプリケーションの実行に依存関係をインストールする必要がなくなり、Dockerイメージのサイズが大幅に削減されます。

@vercel/nftをNext.jsに導入することで、targetのアプローチが置き換えられ、Next.js 12ではtargetが非推奨となりました。詳細についてはドキュメントをご確認ください

その他の改善

  • アプリケーションにpages/_app.jsまたはpages/_document.jsを追加すると、Next.js CLIの再起動を必要とせずに、組み込みバージョンが自動的に置き換えられるようになりました。
  • ESLint統合は、next lint--fileフラグを使用して単一ファイルのリントをサポートするようになりました。
  • Next.js 12は、カスタムのtsconfig.jsonパスの設定をサポートするようになりました。
  • next.config.mjsは、設定をESモジュールとして記述するためにサポートされるようになりました。
  • getStaticPropsの進行中のリクエストが重複排除されるようになりました。
  • 静的ページのチェックは、共有ワーカープールを使用して実行されるようになりました。
  • Fast Refreshは、EventSource接続の代わりにWebSocket接続を使用するようになりました。

破壊的変更

  • Next.js 11でwebpack 5をデフォルトにした後、正式にwebpack 4を削除しました。webpack 5へのスムーズな移行を確実にするため、コミュニティと密接に協力してきました。
  • next.config.jstargetは不要になりました。
  • next/imageは、ラッピング要素としてdivの代わりにspanを使用するようになりました。
  • 最小Node.jsバージョンが12.0.0から12.22.0に引き上げられました。これは、ネイティブESモジュールをサポートする最初のNode.jsバージョンです。

詳細については、アップグレードガイドをご確認ください

コミュニティ

5年前、私たちはNext.jsを一般公開しました。その目的は、開発者エクスペリエンスを簡素化するゼロコンフィギュレーションのReactフレームワークを構築することでした。振り返ってみると、コミュニティがどれほど成長し、私たちが共に何を成し遂げることができたのかを見るのは信じられないほどです。これからも進み続けましょう。

Next.jsは、1,800人以上の個人開発者、GoogleやFacebookなどの業界パートナー、そして当社のコアチームの共同作業の成果です。

このリリースは、以下の貢献によって実現されました: @ka2n, @housseindjirdeh, @rojserbest, @lobsterkatie, @thibautsabot, @javivelasco, @sokra, @rishabhpoddar, @kdy1, @huozhi, @georgegach, @ionut-botizan, @paul-creates, @TimBarley, @kimizuy, @devknoll, @matamatanot, @christianvuerings, @pgrodrigues, @mohamedbhy, @AlfonzAlfonz, @kara, @molebox, @angelopoole, @oste, @genetschneider, @jantimon, @kyliau, @mxschmitt, @PhattOZ, @finn-orsini, @kriswuollett, @harryheman, @GustavoEdinger, @AryanBeezadhur, @Blevs, @colevscode, @atcastle, @ijjk, @velocity23, @jonowu, @timneutkens, @whitep4nth3r, @micro-chipset, @TyMick, @padmaia, @arthurdenner, @vitorbal, @zNeb, @jacksonhardaker, @shuding, @kylemh, @Bundy-Mundi, @ctjlewis, @thien-do, @leerob, @Dev-CasperTheGhost, @janicklas-ralph, @rezathematic, @KonstHardy, @fracture91, @lorensr, @Sheraff, @HaNdTriX, @emilio, @oluan, @ddzieduch, @colinclerk, @x4th, @volcareso, @oiva, @sinchang, @scottrepreneur, @smakosh, @catnose99, @adrienharnay, @donsn, @andersonleite, @msp5382, @tim-hanssen, @appsplash99, @alexvilchis, @RobEasthope, @royal, @Perry-Olsson, @well-balanced, @mrmckeb, @buraksakalli, @espipj, @prateekbh, @AleksaC, @eungyeole, and @rgabs