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

2021年10月26日(火)

Next.js 12

投稿者

Next.js Confで発表したようにNext.js Conf、Next.js 12 はこれまでで最大のリリースの1つです。

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.
大規模なNext.jsコードベースで新しいRustコンパイラを使用した結果。
  • 大規模なコードベースに対するさらなる高速化: 世界最大級の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コンパイラをminifyに使用することもできます。これはTerserより7倍高速です。Minifyは、複数年のインフラストラクチャを置き換えるため、十分に検証されるまでオプトインです。

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

SWCの作成者であるDongYoon Kangと、Parcelの貢献者であるMaia Teegardenを採用したことに加えて、私たちは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レスポンス(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といった機能が追加されます。

私たちは、React 18が安定版リリースに向けて進む中で、Next.jsをReact 18に対応させるため、FacebookのReactチームと密接に連携して取り組んできました。これらの機能を試せるように、本日よりNext.js 12で実験的なフラグの下で利用可能にしました。

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

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

React 18 の Concurrent(並行)機能には、サーバーサイドの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 Component内にクライアントコンポーネントを直接インポートできます。これらのクライアントコンポーネントはハイドレーションされ、インタラクティブになるため、アップボートのような機能を追加できます。

現在、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インポートをサポートしています。

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

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

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

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

Framerのようなノーコードおよびデザインツールを含む、ESモジュールを提供する任意のCDNが機能します。

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

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

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

Next.js 12 では、ウェブクローラー(例:検索ボット) は、fallback: true を使用したISRページを自動的にサーバーレンダリングするようになります。一方、クローラーではないUser-Agentにはフォールバック状態の以前の挙動が提供されます。これにより、クローラーがローディング状態をインデックス化することを防ぎます。

より小さな画像を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をサポートしている場合は、それが提供されます。そうでない場合、ブラウザが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 フラグを使用した単一ファイルのLintをサポートするようになりました。
  • Next.js 12では、カスタムの tsconfig.json パスの設定をサポートするようになりました。
  • 構成をESモジュールとして記述するために、next.config.mjs がサポートされるようになりました。
  • 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, および @rgabs の貢献によって実現しました。