Next.js でのルートのプリフェッチ

Next.js がルートのプリフェッチによってナビゲーションを高速化する仕組みと、そのカスタマイズ方法について説明します。

学習内容

この投稿では、Next.js のルーティングの仕組み、ルーティングを最適化する方法、ニーズに合わせてカスタマイズする方法について説明します。

Next.js では、ルーティングを手動で設定する必要はありません。Next.js ではファイル システムベースのルーティングが使用されるため、./pages/ ディレクトリ内にファイルとフォルダを作成するだけです。

index.js、margherita.js、pineapple- APIs.js の 3 つのファイルを含むページ ディレクトリのスクリーンショット。

別のページにリンクするには、従来の <a> 要素と同じように <Link> コンポーネントを使用します。

<Link href="/margherita">
  <a>Margherita</a>
</Link>

ナビゲーションに <Link> コンポーネントを使用する場合、Next.js はもう少し細かい処理を行います。通常、リンクをたどるとページがダウンロードされますが、Next.js はページのレンダリングに必要な JavaScript を自動的にプリフェッチします。

いくつかのリンクを含むページを読み込んだ場合、リンクをたどる時点で、その背後にあるコンポーネントがすでに取得されている可能性が高くなります。これにより、新しいページにすばやく移動できるようになり、アプリケーションの応答性が向上します。

以下のサンプルアプリでは、index.js ページは <Link>margherita.js にリンクしています。

Chrome DevTools を使用して、margherita.js がプリフェッチされていることを確認します。 1. サイトをプレビューするには、[アプリを表示] を押してから、全画面表示 全画面表示 を押します。

  1. Ctrl+Shift+J キー(Mac の場合は Command+Option+J キー)を押して DevTools を開きます。
  2. [Network] タブをクリックします。

  3. [キャッシュを無効にする] チェックボックスをオンにします。

  4. ページを再読み込みする。

index.js を読み込むと、[ネットワーク] タブに margherita.js もダウンロードされたことが表示されます。

DevTools の [Network] タブで margherita.js がハイライト表示されている。

自動プリフェッチの仕組み

Next.js はビューポートに表示されるリンクのみをプリフェッチし、Intersection Observer API を使用して検出します。また、ネットワーク接続が遅い場合や、ユーザーが Save-Data を有効にしている場合は、プリフェッチも無効になります。これらのチェックに基づいて、Next.js は <link rel="preload"> タグを動的に挿入して、後続のナビゲーション用のコンポーネントをダウンロードします。

Next.js は JavaScript をフェッチするのみで、実行はしません。そうすれば、ユーザーがリンクにアクセスするまで、プリフェッチされたページでリクエストされる可能性のある追加コンテンツはダウンロードされません。

不要なプリフェッチを回避する

不要なコンテンツをダウンロードしないようにするには、<Link>prefetch プロパティを false に設定して、アクセス頻度の低いページのプリフェッチを無効にします。

<Link href="/pineapple-pizza" prefetch={false}>
  <a>Pineapple pizza</a>
</Link>

この 2 番目のサンプルアプリでは、index.js ページの <Link>pineapple-pizza.js に設定され、prefetchfalse に設定されています。

ネットワーク アクティビティを調べるには、最初の例の手順を行います。index.js を読み込むと、DevTools の [Network] タブに、margherita.js がダウンロードされたことが表示されますが、pineapple-pizza.js はダウンロードされていません。

DevTools の [Network] タブで margherita.js がハイライト表示されている。

カスタム ルーティングによるプリフェッチ

<Link> コンポーネントはほとんどのユースケースに適していますが、独自のコンポーネントを作成してルーティングを行うこともできます。Next.js では、next/router で利用可能なルーター API を使用して、これを簡単に行えます。新しいルートに移動する前になんらかの処理(フォームの送信など)を行う場合は、カスタム ルーティング コードでそれを定義できます。

ルーティングにカスタム コンポーネントを使用する場合は、それらにプリフェッチを追加することもできます。ルーティング コードでプリフェッチを実装するには、useRouterprefetch メソッドを使用します。

次のサンプルアプリの components/MyLink.js をご覧ください。

プリフェッチは useEffect フック内で行われます。<MyLink>prefetch プロパティが true に設定されている場合、href プロパティで指定されたルートは、その <MyLink> がレンダリングされるときにプリフェッチされます。

useEffect(() => {
    if (prefetch) router.prefetch(href)
});

リンクをクリックすると、handleClick でルーティングが行われます。メッセージがコンソールに記録され、push メソッドは href で指定された新しいルートに移動します。

const handleClick = e => {
    e.preventDefault();
    console.log("Having fun with Next.js.");
    router.push(href);
};

このサンプルアプリでは、index.js ページに margherita.jspineapple-pizza.js に対する <MyLink> があります。prefetch プロパティは、/margherita では true に、/pineapple-pizza では false に設定されています。

<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza"  title="Pineapple pizza" prefetch={false} />

index.js を読み込むと、[ネットワーク] タブには margherita.js がダウンロードされていることが表示され、pineapple-pizza.js はダウンロードされていないことが示されます。

DevTools の [Network] タブで margherita.js がハイライト表示されている。

いずれかのリンクをクリックすると、コンソールに「Creating fun with Next.js」と記録され、新しいルートに移動します。

「Next.js を楽しんでいます」というメッセージが表示された DevTools コンソール。

まとめ

<Link> を使用すると、Next.js はリンクされたページのレンダリングに必要な JavaScript を自動的にプリフェッチするため、新しいページにすばやく移動できます。カスタム ルーティングを使用している場合は、Next.js Router API を使用して自分でプリフェッチを実装できます。アクセス頻度の低いページのプリフェッチを無効にして、コンテンツを不必要にダウンロードしないようにします。