🗾

Next.js 12について本気出して和訳してみた

2021/10/27に公開

Next.js 12について本気出して和訳してみた

Next.js 12がリリースされました!!!🎉
公式ページは英語となっておりますので、Next.js 12の内容を和訳していきます。

公式ページは以下となっております。
https://nextjs.org/blog/next-12

英語が苦手な方はこの記事を参考にしてください!!!
※本記事で使用している画像は公式ページのものです。


Next.js 12

2021年10月27日(水)

Next.js Confで発表したように、Next.js 12は過去最大のリリースとなります。

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

Rustコンパイラーによるビルドの高速化とリロードの高速化

Next.jsでは、すべてのアプリケーションが本番環境でより速くビルドされ、ローカル開発では即座にフィードバックが得られるようにしたいと考えています。Next.js 12には、ネイティブ・コンパイルの利点を活かした全く新しいRustコンパイラが搭載されています。

Rustコンパイラーは、次世代の高速ツールのためのオープンプラットフォームであるSWC上に構築されています。バンドルとコンパイルが最適化され、ローカルでは約3倍のFast Refresh、プロダクションでは約5倍ビルドの高速化がとなっています。その他の改善点や特徴は以下のとおりです。


大規模なNext.jsのコードベースで新しいRustコンパイラーを使用した結果

  • 大規模なコードベースでのさらなる高速化: 世界最大級のNext.jsのコードベースでRustコンパイラーの検証をしました。
  • パフォーマンスにおける観測性の向上: Next.jsでは、クライアントとサーバーの両方のコンパイル時に、Fast Refreshのタイミングをコンソールに出力するようになり、コンパイルされたモジュールやファイルの数も表示されます。
  • 根底となるwebpackの改善: Fast Refreshの最適化や、オンデマンドエントリーの信頼性向上など、webpackには数多くの改良が加えられています。

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

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

縮小化のためのRustコンパイラーを使ったオプトインもできます。これはTerserよりも7倍速いです。縮小化は数年がかりのインフラを置き換えるものなので、徹底的に検証されるまではオプトインとなります。

// next.config.js

module.exports = {
  swcMinify: true
}

SWCの生みの親であるDongYoon Kangや、Parcelの貢献者であるMaia Teegardenを採用した上で、Rustのエコシステムへの投資を続けています。もしあなたがRustを使った経験があるなら、ぜひ私たちのチームにこちらから応募してください。

詳しくは、Next.js Confにてデモをご覧ください。

ミドルウェアの紹介

ミドルウェアを使うと、設定よりもコードを使うことができます。Next.jsでは、リクエストが完了する前にコードを実行することができるため、柔軟性に富んでいます。ユーザーが入力したリクエストに基づいて、レスポンスを書き換えたり、リダイレクトしたり、ヘッダーを追加したり、さらにはHTMLをストリーミングしたりして、レスポンスを修正することができます。


ミドルウェアはNext.jsの内部で完全な柔軟性を発揮します

ミドルウェアは、一連のページのロジックを共有するあらゆるものに使用できます。

ミドルウェアは、fetchなどの標準的なWeb APIをサポートする厳格な実行を行います。これは、next startを使用してすぐに動作します。また、Edge Functionsを使用するVercelなどのEdgeプラットフォームでも動作します。

Next.jsでミドルウェアを使用するには、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では、サスペンスのような機能、アップデートの自動バッチ処理、startTransitionのようなAPI、React.lazyをサポートしたサーバーレンダリング用の新しいストリーミングAPIなどが追加されます。

FacebookのReactチームと緊密に連携し、安定版リリースに向けてNext.jsをReact 18に対応させてきました。Next.js 12では、これらの機能を実験的なフラグで試すことができます。

npm install react@alpha react-dom@alpha

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

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

有効にするには、実験的なフラグconcurrentFeatures: trueとします。

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

Reactサーバーコンポーネント

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

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

Next.jsでは、データの取得をコンポーネントレベルで行うことができるようになり、すべてJSXで表現されます。React Serverコンポーネントを使うことで、シンプルにすることができます。getServerSidePropsgetStaticPropsのような特別な関数はもう必要ありません。これは、データの取得をコンポーネントにコロケーションするというReact Hooksのモデルと一致します。

Next.jsのページを.server.jsにリネームしてサーバーコンポーネントを作成し、クライアントコンポーネントをサーバーコンポーネントの中に直接インポートすることができます。これらのクライアントコンポーネントはハイドレイトしてインタラクティブになるので、アップブートのような機能を追加することができます。

Next.jsでは現在、サーバーサイドのサスペンス、選択的なハイドレーション、ストリーミングレンダリングに取り組んでおり、その進捗状況は今後のブログ記事で紹介する予定です。

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

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

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

この標準規格は、パッケージサイズやJavaScriptのバンドルを小さくすることでウェブのエコシステムを前進させ、最終的にはより良いユーザーエクスペリエンスをもたらします。JavaScriptのエコシステムがCommon JS(旧規格)からESモジュールに移行する中で、私たちは開発者が不必要な変更をすることなく、これらの改善点を段階的に採用できるように支援することを約束します。

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

URLインポート

Next.js 12では、ESモジュールをURL経由でインポートする機能が実験的にサポートされていますが、インストールや別のビルドステップは必要ありません。

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

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

next.config.jsの中に、許可されるURLプレフィックスを追加することでオプトインできます。

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

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

AVIFによる画像の小型化

内蔵の画像最適化APIがAVIF画像をサポートするようになり、WebPに比べて20%小さい画像を作成できるようになりました。

AVIF 画像は WebP に比べて最適化に時間がかかるため、next.config.jsの新しいimages.phatsプロパティを使用して、この機能を選択できるようにしています。

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

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

出力ファイルのトレース

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

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

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

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

Next.jsに@vercel/nftを導入することで、targetのアプローチに取って代わることができ、Next.js 12ではtargetは非推奨となりました。詳しくはドキュメントをご覧ください。

その他の改善点

  • アプリケーションにpages/_app.jspages/document.jsを追加すると、Next.jsのCLIを再起動することなく、自動的に組み込みバージョンが置き換えられるようになりました。
  • ESLintの統合で、next lint--fileフラグによるsingle-file lintingがサポートされました。
  • Next.js 12では、カスタムのtsconfig.jsonのパスを設定できるようになりました。
  • next.config.mjsがESモジュールとして設定を書くことに対応しました。
  • getStaticPropsに関して、In-flight???のリクエストが重複排除されるようになりました。
  • 静的ページのチェックに、共有ワーカープールを使用するようになりました。
  • 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モジュールをサポートする最初のバージョンとなりました。

詳しくは、アップグレードガイドをご覧ください。

コミュニティ

今から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

Discussion