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

2020年10月27日 火曜日

Next.js 10

投稿者

Next.js 10 をご紹介できることを大変嬉しく思います。主な機能は以下の通りです。

組み込みの画像コンポーネントと自動画像最適化

Next.js の目標は、開発者体験とユーザー体験の2つを改善することです。

今年は、開発者体験とすべての Next.js アプリケーションのパフォーマンス向上に多大な投資を行いました。私たちは、ブラウザが読み込む必要がある JavaScript の量を減らすことに注力しました。

パフォーマンスと開発者体験を向上させる 20以上の新機能 を導入しました。同時に、Next.js コアの JavaScript サイズは 16%削減 されました。

1月には、Google Chrome チームと共同で、クラス最高の新しい JavaScript コード分割戦略を導入しました。

例えば、Barnebys では アプリケーションサイズが23%減少 し、Sumup では 最大の Javascript バンドルサイズが70%減少 しました。これらの改善は、Next.js アプリケーションの コードを変更することなく 達成されました。

企業は Next.js を最新バージョンにアップグレードするだけで、この新しい戦略を自動的に採用しました。

ウェブ上の画像

ブラウザが読み込む JavaScript の量を減らすことに注力したことは報われましたが、ウェブは JavaScript だけでなく、マークアップや画像も含まれています。

ウェブページの総バイト数の50%は画像が占めています。

画像は、ページ読み込み時によく最大の可視要素となるため、Largest Contentful Paint に大きな影響を与えます。Largest Contentful Paint は、Google が検索ランキングに まもなく使用する Core Web Vital の1つです。

全画像の半分は1メガバイトを超えており、これはウェブ上で表示するために最適化されていないことを意味します。

今日、ユーザーは携帯電話、タブレット、ラップトップを使用してウェブを閲覧していますが、画像は依然として「ワンサイズフィットオール」です。例えば、サイトは2000 x 2000 ピクセルの画像を読み込みますが、携帯電話では100 x 100 ピクセルとしてしか表示されません。

さらに、ウェブページの画像の30%は初期ビューポートの外にあり、これはユーザーがページをさらに下にスクロールするまで見えない画像をブラウザが読み込んでいることを意味します。

画像にはしばしば width および height プロパティがないため、ページ読み込み時に画像が飛び跳ねて表示される原因となります。これは Cumulative Layout Shift Core Web Vital に悪影響を与えます。

ウェブサイトの画像の99.7%は、WebP のような最新の画像形式を使用していません。

ウェブページで画像をパフォーマンスよく使用するためには、サイズ、容量、遅延読み込み、最新の画像形式など、多くの側面を考慮する必要があります。

開発者は画像を最適化するために複雑なビルドツールを設定しなければなりませんが、それらのツールは通常、外部データソースから提供されるユーザー提出画像をカバーしないため、すべての画像を最適化することは不可能です。

この不可能な開発タスクは、必然的にユーザーに不満なエンドユーザー体験をもたらします。

Next.js 画像コンポーネント

ウェブ上での高性能画像のためのソリューションとして、Next.js 画像コンポーネントと自動画像最適化を発表できることを嬉しく思います。

最も基本的なこととして、Next.js 画像コンポーネントは、現代のウェブ向けに進化した HTML <img> 要素の単純な置き換えです。

<img
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>
import Image from 'next/image';
<Image
  src="/profile-picture.jpg"
  width="400"
  height="400"
  alt="Profile Picture"
/>;

Google Chrome チームは、ベストプラクティスをデフォルトにすることでページパフォーマンスを向上させるために、この React コンポーネントの作成を支援しました。

next/image コンポーネントを使用すると、画像は自動的に遅延読み込みされます。つまり、ユーザーが画像を見かける直前になって初めてレンダリングされます。これにより、初期ビューポート外の画像の30%を読み込むことを防ぎます。

画像の寸法が強制されるため、ブラウザは画像を読み込んだ際に飛び跳ねるのではなく、必要なスペースをすぐにレンダリングできるため、レイアウトシフトを防ぎます。

HTML <img> 要素の widthheight はレスポンシブレイアウトで問題を引き起こすことがありますが、next/image を使用する場合はそうではありませんnext/image を使用すると、提供された widthheight からのアスペクト比に基づいて画像が自動的にレスポンシブになります。

開発者は初期ビューポート内の画像をマークすることができ、Next.js がこれらの画像を自動的にプリロードできるようにします。初期ビューポート内の画像をプリロードすることで、Largest Contentful Paint が最大50%改善することが示されています。

自動画像最適化

HTML <img> 要素と比較してこれらの改善があっても、まだ大きな問題があります。2000 x 2000 ピクセルの画像は、より小さな画像をレンダリングする携帯電話に送信されます。

Next.js 10 では、この問題も解決しています。next/image コンポーネントは、組み込みの画像最適化によって自動的に小さなサイズを生成します。

組み込みの画像最適化は、ブラウザがサポートしていれば、WebP のような最新の画像形式で画像を自動的に提供します。WebP は JPEG より約30%小さくなります。また、Next.js が 将来の 画像形式を自動的に採用し、それらの形式をサポートするブラウザに提供できるようにします。

画像最適化は、あらゆる画像ソースで機能します。CMS のような外部データソースから画像が供給される場合でも、最適化されます。

Next.js 10 は、ビルド時に画像を最適化するのではなく、ユーザーがリクエストしたときにオンデマンドで画像を最適化します。静的サイトジェネレーターや静的のみのソリューションとは異なり、10枚の画像でも1000万枚の画像でも、ビルド時間が増加することはありません。

結論

新しい next/image コンポーネントと自動画像最適化は、ユーザー体験を大幅に向上させる強力な新しいプリミティブです。

next/image コンポーネントは、自動遅延読み込み、重要な画像のプリロード、デバイス間での正しいサイズ調整、および最新形式の自動サポートを処理します。これらの機能は、あらゆるソースの画像で機能します。

これらの新しいプリミティブによって、ユーザー体験がどれだけ高速になるかを楽しみにしています。

詳細については、Next.js 画像コンポーネントと自動画像最適化のドキュメント を参照してください。

国際化ルーティング

今年、いくつかの企業やコミュニティメンバーが、国際化がいかに重要であるかを私たちのチームに理解させてくれました。

例えば、消費者の72%は翻訳されたサイトであれば滞在する可能性が高く、55%の消費者は母国語のEコマースサイトからしか購入しないと述べていることがわかりました。

異なる国で市場展開を計画している場合、プロジェクトの国際化は成功のために不可欠です。

プロジェクトを国際化するには、翻訳とルーティングの2つの主要な柱があります。

多くの React ライブラリはアプリケーションの翻訳を準備しますが、それらのほとんどはルーティングを手動で処理することを期待しており、一般的に単一のレンダリング戦略でのみ動作します。

そのため、Next.js 10 の一部として、国際化ルーティングと言語検出の組み込みサポートをリリースします。

この国際化ルーティングの組み込みサポートは、Next.js のハイブリッド戦略をサポートしており、ページごとに静的生成またはサーバーサイドレンダリングを選択できます。

Next.js 10 は、最も一般的な2つのルーティング戦略、サブパスルーティングとドメインルーティングをサポートしています。

どちらの戦略でも、Next.js の設定でロケールを構成することから始めます。

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    defaultLocale: 'en',
  },
};

ロケールは、ロケールを定義するための標準化された形式である UTS ロケール識別子 です。

一般的にロケール識別子は、言語、地域、スクリプトがハイフンで区切られて構成されます: language-region-script。地域とスクリプトはオプションです。例

  • en-US - 米国で話される英語
  • nl-NL - オランダで話されるオランダ語
  • nl - オランダ語、特定の地域なし

ロケールが設定されたら、サブパスルーティングまたはドメインルーティングを選択できます。

サブパスルーティング

サブパスルーティングは、ロケールを URL に含めます。これにより、すべての言語を単一のドメインで運用できます。

例えば、/nl-nl/blog/en/blog のようにロケールを URL に挿入できます。

ドメインルーティング

ドメインルーティングを使用すると、ロケールをトップレベルドメインにマッピングできます。例えば、example.nlnl ロケールに、example.comen ロケールにマッピングできます。

ドメインルーティングには、ドメインをルーティングする方法を知るための追加設定が必要です。

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'nl'],
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl',
      },
    ],
  },
};

言語検出

Next.js 10 には、/ ルートにおける組み込みの言語検出機能があり、すべてのモダンブラウザがサポートする Accept-Language ヘッダーに基づいています。設定されたロケールは Accept-Language ヘッダーと照合され、設定された戦略に従ってリダイレクトされます。

検索エンジン最適化

Next.js はユーザーが訪問したページの言語を認識しているため、自動的に <html> タグに lang 属性を追加します。

Next.js はページのバリエーションを認識しないため、next/head を使用して hreflang メタタグを追加するのはユーザーの責任です。hreflang の詳細については、Google Webmasters のドキュメントを参照してください。

Next.js における国際化の未来

国際化ルーティングは、プロジェクトの国際化とローカライズを容易にする一連の機能の最初のものです。国際化ルーティングにより、大部分の React 国際化ライブラリとの統合が可能になります。

国際化ルーティングの詳細については、国際化ルーティングのドキュメント を参照してください。

Next.js Speed Insights

Vercel では、測定できないものは修正できないと認識しています。

訪問者はサイトのパフォーマンスにますます敏感になっています。サイトの読み込みに 3秒以上かかる場合、50%以上がサイトを離脱します。eコマースの場合、読み込み時間を10分の1秒改善するだけで コンバージョンが1%増加した例が多数あります。

パフォーマンスが成功にとってどれほど重要であるかという理由から、Next.js Speed Insights をリリースできることを誇りに思います。これは、実世界でのパフォーマンスメトリクスを追跡し、その洞察を開発ワークフローにフィードバックするためのソリューションです。

Next.js Speed Insights を使用すると、

一度測定するのではなく、継続的に測定できるようになります。

開発デバイスで測定するのではなく、測定値は実際の訪問者が使用しているデバイスから得られます。

Next.js Speed Insights は、全体像に焦点を当て、ユーザー層を深く理解し、アプリケーションがユーザーのためにどのように機能するかを把握することに重点を置いています。

実データ収集にこだわるのは、パフォーマンス低下の原因が必ずしも最も明白ではないためです。パフォーマンスの回帰は、サードパーティのスクリプトやスタイルシート、またはサイズが大きすぎたり速度が遅いファーストパーティのフォント、画像、ビデオなど、さまざまな場所から発生する可能性があります。

Core Web Vitals

Google は、Web Performance Working Groupと協力して、ユーザーがウェブサイトのパフォーマンスをどのように体験しているかを正確に測定するための一連の指標を確立しました。これらは適切に Web Vitals と名付けられています。Web Vitals は、ウェブサイトの知覚される読み込み速度、応答性、視覚的な安定性を追跡する指標であり、これら3つはウェブサイトの全体的な健全性にとって不可欠です!

知覚される読み込み速度は、Largest Contentful Paint、つまりページのすべてのコンテンツが表示されるまでの時間で測定できます。例えば、スニーカーを購入するためのリンクを開いたときに、スニーカー、その価格、カートに追加ボタンが表示されるまでの時間が LCP です。

ページの応答性は、First Input Delay で測定できます。これは、ユーザーがページとの最初のインタラクションの反応を見るまでに待たなければならない時間です。例えば、私が「カートに追加」をクリックしてから、カート内のアイテム数がインクリメントされるまでの時間が FID です。

最後に、視覚的な安定性は Cumulative Layout Shift で測定できます。これは、要素がユーザーに表示された後にどれだけ移動するかを示します。例えば、画像が遅れて読み込まれたために移動したボタンをタップしようとしてイライラした経験は誰にでもあるでしょう。それがレイアウトシフトです。

実際のユーザーに対するこれらの Web Vitals の継続的な測定と適合性は非常に重要です。それが、サイトがユーザーにとってどのように機能しているかを真に知る唯一の方法です。サイトのパフォーマンスは、ユーザーのデバイスやネットワーク状況、またはページとのインタラクション方法によって劇的に異なる場合があります。パーソナライズされたコンテンツや広告を読み込むサイトも、ユーザーごとに大きく異なるパフォーマンスを経験する可能性があります。

エミュレートされたテストでは、これらの重要なシグナルを捕捉できません。

Next.js Speed Insights を使用すると、合成ベンチマークではなく、現実世界での洞察を収集できます。これにより、時折のテストに依存するのではなく、継続的な測定ストリームが可能になり、開発者のワークフローの一部として確実に組み込まれます。

Next.js Speed Insights を使用すると、合成ベンチマークではなく、現実世界での洞察を収集できます。これにより、時折のテストに依存するのではなく、継続的な測定ストリームが可能になり、開発者のワークフローの一部として確実に組み込まれます

今すぐアプリケーションで有効にする方法については、nextjs.org/analyticsにアクセスしてください。

Next.js Commerce

Eコマースはウェブの最も重要な用途の1つです。Next.js 10 の新機能は、eコマースのための強力な新しいツールです。

そのため、本日、BigCommerce と共同で、eコマースサイト向けのオールインワン React スターターキットである Next.js Commerce をリリースしました。数クリックで、Next.js 開発者はそれをクローン、デプロイ、完全にカスタマイズできます。今すぐ nextjs.org/commerce で始めてください。

React 17 のサポート

React 17 は Next.js に対して破壊的な変更はありませんでしたが、例えばピア依存関係の更新など、いくつかのメンテナンス上の変更が必要でした。新しい JSX トランスフォームは React 17 を使用すると自動的に有効になり、設定変更は不要です。

React 17 の使用を開始するには、Next.js と React をアップグレードするだけです。

ターミナル
npm install next@latest react@latest react-dom@latest

getStaticProps / getServerSideProps 高速リフレッシュ

getStaticProps および getServerSideProps 関数を編集すると、Next.js は自動的に関数を再実行し、新しいデータを適用するようになりました。これにより、ページを更新することなく、より迅速に反復処理を行うことができます。

getStaticPropsgetServerSideProps の詳細については、データフェッチのドキュメント を参照してください。

MDX の高速リフレッシュ

@next/mdx を介して Next.js で MDX を使用する場合、MDX コンテンツの変更は Fast Refresh を活用するようになり、編集時にブラウザがページを再読み込みする必要がなくなります。

@next/mdx のドキュメントでは、Next.js で MDX をセットアップする方法が説明されています。

サードパーティの React コンポーネントからの CSS インポート

サードパーティの CSS を React コンポーネント内にインポートできるようになりました。これにより、単一のコンポーネント専用の CSS をコード分割できます。例えば、react-datepicker ライブラリを使用する際に、_app.js で CSS をインポートする必要がなくなりました。

components/MyComponent.js
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
 
function MyComponent() {}

Next.js が CSS インポートをどのように処理するかについては、組み込みの CSS サポートドキュメント を参照してください。

href の自動解決

以前に動的ルーティングを使用したことがある場合、next/linkhrefas の両方のプロパティを提供しなければならなかったケースに遭遇したことがあるかもしれません。それは次のようなものでした。

<Link href="/categories/[slug]" as="/categories/books" />

これにより、Next.js は動的パラメータの href を補間できましたが、開発者が as を追加するのを忘れたり、hrefas を追加してページ遷移がクライアントサイドルーティングを使用しなかったりすることで、摩擦が生じていました。

私たちは数ヶ月前、開発者体験とエンドユーザー体験の向上を主目標として、この摩擦を解決することに着手しました。私たちは href が自動的に解決されるソリューションに向けて段階的に取り組みました。

Next.js 10 の一部として、ほとんどのユースケースで as プロパティを使用する必要がなくなったことをお知らせいたします。これにより、開発者の摩擦が解消され、エンドユーザー体験が向上します。

この変更は完全に下位互換性があり、現在 hrefas の両方を使用している場合、既存の動作は維持されます。

href の自動解決を採用するには、next/link の使用を、以前 as プロパティにあった値を保持する href のみを使用するように変更するだけです。

<Link href="/categories/books" />

next/link とクライアントサイドルーティングの詳細については、next/link のドキュメント を参照してください。

@next/codemod CLI

私たちは、広範な下位互換性を通じて、Next.js のアップグレードが可能な限りスムーズに行われるよう尽力しています。このコミットメントは、新しくより良いソリューションを導入しつつ、機能を控えめに非推奨にすることから始まります。このコミットメントに加え、すべての Next.js 機能について、ローカル開発を再現するテストを含む広範な統合テストを行っています。

Next.js の機能が非推奨になり、大規模なコードベースの変更が必要な場合、私たちのチームはそれに対応するコードモッドを作成します。コードモッドとは、プロジェクト全体で実行してソースコードを更新できる自動化されたコード変換のことです。

例えば、アロー関数と匿名関数を名前付き関数に更新するコードモッドをリリースしました。この変換 は、そうしないと React Fast Refresh が関数を有効な React コンポーネントとして検出しないため必要です。同様に、React hooks の eslint ルールもその関数を React コンポーネントとして認識しません。

Next.js 10 では、アプリケーションを更新するために単一のコマンド npx @next/codemod <transform> <path> を実行できる新しい Next.js codemods CLI ツールをリリースします。

コードモッドの詳細については、Next.js Codemods のドキュメント を参照してください。

getStaticPaths のブロッキングフォールバック

Next.js 9.3 では、getStaticPropsgetStaticPaths を導入し、getStaticPathsfallback プロパティを返す機能を追加しました。fallback プロパティは、完全な再ビルドを必要とせずに、追加の静的ページを生成することを可能にし、最初に静的 HTML ファイルを提供し、その後のリクエストで完全にレンダリングされたコンテンツに置き換えられます。過去数ヶ月間、私たちは企業から、似ているが少し異なる動作を求める多くのフィードバックを受け取りました。それは、ユーザーが初めてページをリクエストしたときにブロッキングプリレンダリングを行い、その最初のレンダリングの後、そのページを後続のリクエストで再利用するというものです。

Next.js 10 では、このケースを解決します。

getStaticPaths の新しい fallback: 'blocking' モードを発表できることを嬉しく思います。これにより、静的フォールバックがブラウザに送信されず、最初のリクエストがプリレンダリングを待つブロッキング動作が可能になります。

pages/posts/[id].js
export function getStaticPaths() {
  return {
    // enables blocking mode for the fallback behavior
    fallback: 'blocking',
  };
}

追加の静的ページを増分的に生成するための fallback の動作の詳細については、fallback ドキュメントを参照してください。

getStaticProps / getServerSideProps のリダイレクトと notFound サポート

getStaticProps および getServerSideProps の導入以来、ユーザーがリダイレクトと 404 レスポンスを返す必要があるケースを認識しました。これらのケースを効率化するために、getStaticPropsgetServerSideProps から notFoundredirect という2つの新しいフィールドを返せるようになりました。

notFound のサポート

notFound フィールドを true で返すと、デフォルトの 404 ページがステータスコード 404 とともに返されます。これにより、SSG で追加のページを生成したり、404 ページの手動レンダリングを処理したりする必要がなくなります。

pages/posts/[id].js
export function getStaticProps() {
  return {
    // returns the default 404 page with a status code of 404
    notFound: true,
  };
}

redirect のサポート

リダイレクトを返すことができるようになりました。これには destination と、リダイレクトが永続的であるかどうか (例: permanent: true) が含まれます。デフォルトのステータスコードではなく特定のステータスコードを使用する必要がある場合は、オプションで statusCode を返すこともできます。

pages/posts/[id].js
export function getStaticProps() {
  return {
    // returns a redirect to an internal page `/another-page`
    redirect: {
      destination: '/another-page',
      permanent: false,
    },
  };
}
pages/posts/[id].js
export function getServerSideProps() {
  return {
    // returns a redirect to an external domain `example.com`
    redirect: {
      destination: 'https://example.com',
      permanent: false,
    },
  };
}

結論

Next.js の採用が継続的に拡大していることを嬉しく思います。

  • 9.5 のリリース以降、1,300人を超える独立した貢献者がおり、120人以上の新しい貢献者が加わりました。
  • GitHub では、プロジェクトに 54,800回以上のスターが付けられています。

GitHub Discussionsで Next.js コミュニティに参加してください。Discussions は、他の Next.js ユーザーとつながり、自由に質問したり、自分の作品を共有したりできるコミュニティスペースです。

クレジット

このリリースを形作るのに貢献してくださった、外部からのフィードバックや貢献を含むすべてのコミュニティに感謝いたします。

このリリースは、以下の貢献によってもたらされました: @ijjk, @adebiyial, @elliottsj, @saintmalik, @HaNdTriX, @prateekbh, @amirsaeed671, @paambaati, @imagentleman, @gregrickaby, @Janpot, @atcastle, @Kirkhammetz, @remorses, @davidsonsns, @kmkzt, @slawekkolodziej, @Timer, @styfle, @timneutkens, @ykzts, @ashconnell, @orYoffe, @lfades, @justinwhall, @fbaiodias, @ludofischer, @felipeguilhermefs, @gr-qft, @TasukuUno, @YichiZ, @weichienhung, @seosmmbusiness, @HsuTing, @gsimone, @peduarte, @ztanner, @neighborhood999, @chibicode, @merceyz, @opudalo, @lunchboxav, @mohsen1, @akd-io, @justman00, @helloworld, @devknoll, @borekb, @ArthurMaverick, @sakito21, @TrySound, @omBratteng, @svenheden, @hallaji, @kettanaito, @vvo, @m-lautenbach, @jensmeindertsma, @Zeko369, @longlho, @stefanprobst, @laugharn, @sdornan, @daneroo, @mohd-akram, @austingmhuang, @sphilee, @devinekadeni, @Bacher, @nghiepit, @tomasdisk, @leader22, @paulogdm, @284km, @belgattitude, @geritol, @stigkj, @sampoder, @samrobbins85, @Pitasi, @digitalPlayer1125, @timfee, @plug-n-play, @philihp, @leerob, @dylanjha, @Kerumen, @rdimaio, @jorisw, @zerbinidamata, @jamesgeorge007, @Jashnm, and @futantan!