Backブログに戻る

Next.js 10

Next.js 10では、組み込みの画像最適化、国際化ルーティング、Next.js Analytics、React 17サポートなどが導入されました!

Next.js 10のリリースを発表します。主な新機能は以下の通りです:

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

Next.jsの目標は、開発者体験(Developer Experience)とユーザー体験(User Experience)の向上です。

今年はすでに開発者体験と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メガバイト以上で、ウェブ表示用に最適化されていません。

現在、ユーザーはスマートフォン、タブレット、ノートPCでウェブを閲覧していますが、画像は依然として「one size fits all(一つのサイズですべてに対応)」のままです。例えば、2000×2000ピクセルの画像を読み込んでも、スマートフォンでは100×100ピクセルでしか表示されません。

さらに、ウェブページ上の画像の30%は初期ビューポートの外側にあり、ユーザーがページをスクロールするまで表示されない画像をブラウザが読み込んでいます。

画像にはwidthheightプロパティが設定されていないことが多く、ページ読み込み時に画像がジャンプする原因となります。これはCore Web VitalのCumulative Layout Shift(累積レイアウトシフト)を悪化させます。

ウェブサイト上の画像の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×2000ピクセルの画像が、より小さな画像を表示するスマートフォンに送信されます。

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

組み込み画像最適化は、ブラウザがサポートしていれば、WebPのような最新画像フォーマット(JPEGより約30%小さい)で画像を自動的に提供します。また、Next.jsが将来の画像フォーマットを自動的に採用し、それらをサポートするブラウザに提供することも可能にします。

画像最適化はあらゆる画像ソースで動作します。CMSのような外部データソースからの画像であっても最適化されます。

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

まとめ

新しいnext/imageコンポーネントと自動画像最適化は、ユーザー体験を大幅に改善する強力な新機能です。

next/imageコンポーネントは、自動遅延読み込み、重要な画像のプリロード、デバイス間での適切なサイズ設定、最新フォーマットの自動サポートを処理します。これらの機能はあらゆるソースからの画像で動作します。

これらの新機能でユーザー体験がどれだけ速くなるか楽しみです。

詳細はNext.js画像コンポーネントと自動画像最適化のドキュメントをご覧ください。

国際化ルーティング

今年、多くの企業やコミュニティメンバーの協力により、国際化がいかに重要かを理解しました。

例えば、72%の消費者はサイトが翻訳されていると滞在する可能性が高く、55%の消費者は母国語のeコマースサイトからのみ購入すると回答しています。

異なる国で市場に参入する場合、プロジェクトの国際化は成功に不可欠です。

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

多くのReactライブラリはアプリケーションを翻訳可能に準備しますが、ほとんどの場合ルーティングは手動で処理する必要があり、一般的に1つのレンダリング戦略でのみ動作します。

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

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

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にロケールを配置します。これによりすべての言語を単一ドメインで運用できます。

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

ドメインルーティング

ドメインルーティングでは、ロケールをトップレベルドメインにマッピングできます。例えば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ウェブマスター向けドキュメントをご覧ください。

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

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

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

Next.js Speed Insights

Vercelでは、測定できないものは改善できないことを知っています。

訪問者はサイトのパフォーマンスにますます敏感になっています。50%以上の訪問者は、読み込みに3秒以上かかるとサイトを離れます。eコマースの場合、読み込み時間を0.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)またはページのすべてのコンテンツが表示された時点で測定できます。例えば、スニーカーを購入するためのリンクを開いたとき、スニーカーとその価格、カート追加ボタンが表示されるまでの時間がLCPです。

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

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

実際のユーザーに対するこれらの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をアップグレードするだけです:

Terminal
npm install next@latest react@latest react-dom@latest

getStaticProps / getServerSideProps のFast Refresh

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

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

MDXのFast Refresh

@next/mdxを通じてNext.jsでMDXを使用する場合、MDXコンテンツを変更するとFast Refreshが利用され、編集時にブラウザがページをリロードする必要がなくなります。

@next/mdxドキュメントでは、Next.jsでMDXを設定する方法を案内しています。

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

Reactコンポーネント内でサードパーティのCSSをインポートできるようになりました。これにより、単一のコンポーネント専用の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フックのeslintルールも関数をReactコンポーネントとして認識しません。

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

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

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

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

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

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

pages/posts/[id].js
export function getStaticPaths() {
  return {
    // フォールバック動作のためにブロッキングモードを有効にする
    fallback: 'blocking',
  };
}

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

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

getStaticPropsgetServerSidePropsの導入以来、ユーザーがリダイレクトと404応答を返す必要があるケースに気づきました。これらのケースを合理化するために、getStaticPropsgetServerSidePropsから2つの新しいフィールドnotFoundredirectを返すことができるようになりました。

notFoundサポート

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

pages/posts/[id].js
export function getStaticProps() {
  return {
    // 404ステータスコードでデフォルトの404ページを返す
    notFound: true,
  };
}

redirectサポート

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

pages/posts/[id].js
export function getStaticProps() {
  return {
    // 内部ページ`/another-page`へのリダイレクトを返す
    redirect: {
      destination: '/another-page',
      permanent: false,
    },
  };
}
pages/posts/[id].js
export function getServerSideProps() {
  return {
    // 外部ドメイン`example.com`へのリダイレクトを返す
    redirect: {
      destination: 'https://example.com',
      permanent: false,
    },
  };
}

結論

Next.jsの採用が継続的に成長していることを嬉しく思います:

  • 1,300人以上の独立した貢献者がおり、9.5リリース以降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、そして@futantan!