クイックリンクを使用した create-react-app でのプリフェッチ

この Codelab では、React SPA のデモに Quicklink ライブラリを実装し、プリフェッチによって後続のナビゲーションがいかに高速化されるかを示す方法を示します。

測定

最適化を追加する前に、まずアプリケーションの現在の状態を分析することをおすすめします。

  • [Remix to Edit] をクリックして、プロジェクトを編集可能にします。
  • サイトをプレビューするには、[アプリを表示] を押します。[ 全画面表示 全画面表示

このウェブサイトは、create-react-app で構築されたシンプルなデモです。

開いた新しいタブで、次の手順を行います。

  1. Ctrl+Shift+J キー(Mac の場合は Command+Option+J キー)を押して DevTools を開きます。
  2. [ネットワーク] タブをクリックします。
  3. [キャッシュを無効にする] チェックボックスをオンにします。
  4. [Throttling] プルダウン リストで [Fast 3G] を選択して、低速の接続タイプをシミュレートします。
  5. アプリを再読み込みします。
  6. [フィルタ] テキスト ボックスに「chunk」と入力して、名前に chunk を含まないリソースを非表示にします。

ホームページのチャンクを表示するネットワーク パネル。

このサイトではルートベースのコード分割が使用されているため、最初に必要なコードのみがリクエストされます。

  1. DevTools でネットワーク リクエストをクリアします
  2. アプリ内の [ブログ] リンクをクリックして、そのページに移動します。

新しいルートの JavaScript チャンクと CSS チャンクが読み込まれ、ページがレンダリングされます。

ブログページのチャンクを表示するネットワーク パネル。

次に、このサイト内に Quicklink を実装して、これらのチャンクをホームページでプリフェッチできるようにし、ナビゲーションを高速化します。

これにより、両方の手法の長所を組み合わせることができます。

  • ルートに基づいてコード分割を行うと、ブラウザはページの読み込み時に、必要なチャンクのみを高い優先度で読み込むように指示できます。
  • プリフェッチはブラウザのアイドル時間に、ビューポート内のリンクのチャンクを最も低い優先度で読み込むようにブラウザに指示します。

webpack-route-manifest の設定

まず、webpack-route-manifest をインストールして構成します。この Webpack プラグインを使用すると、ルートを対応するチャンクに関連付けるマニフェスト ファイルを生成できます。

通常はライブラリをインストールする必要がありますが、すでにインストールされています。次のコマンドを実行する必要があります。

npm install webpack-route-manifest --save-dev

config-overrides.js はプロジェクトのルート ディレクトリに配置されたファイルで、プロジェクトを排除することなく、webpack 設定の既存の動作をオーバーライドできます。

  • ソースを表示するには、[View Source] を押します。

config-overrides.js を編集用に開き、ファイルの先頭に webpack-route-manifest 依存関係を追加します。

const path = require('path');
const RouteManifest = require('webpack-route-manifest');

次に、以下を追加して webpack-route-manifest プラグインを構成します。 config-overrides.js の末尾に追加します。

module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: {
      '@assets': `${path.resolve(__dirname, 'src/assets')}`,
      '@pages': `${path.resolve(__dirname, 'src/pages')}`,
      '@components': `${path.resolve(__dirname, 'src/components')}`,
    },
  };

  config.plugins.push(
    new RouteManifest({
      minify: true,
      filename: 'rmanifest.json',
      routes(str) {
        let out = str.replace('@pages', '').toLowerCase();
        if (out === '/article') return '/blog/:title';
        if (out === '/home') return '/';
        return out;
      },
    }),
  );

  return config;
};

新しいコードにより、次の処理が行われます。

  • config.resolve は、ページ、アセット、コンポーネントへの内部ルートを持つ変数を宣言します。
  • config.plugins.push()RouteManifest オブジェクトを作成して構成を渡します。これにより、サイトのルートとチャンクに基づいて rmanifest.json ファイルを生成できるようになります。

manifest.json ファイルが生成され、https://site_url/rmanifest.json で利用できるようになります。

この時点で、プロジェクトに Quicklink ライブラリをインストールする必要があります。わかりやすくするため、すでにプロジェクトに追加しています。次のコマンドを実行する必要があります。

npm install --save quicklink

src/components/App/index.js を編集用に開きます。

まず、Quicklink の高次コンポーネント(HOC)をインポートします。

import React, { lazy, Suspense } from 'react';
import { Route } from 'react-router-dom';

import Footer from '@components/Footer';
import Hero from '@components/Hero';
import style from './index.module.css';
import { withQuicklink } from 'quicklink/dist/react/hoc.js';

const Home = lazy(() => import(/* webpackChunkName: "home" */ '@pages/Home'));
const About = lazy(() => import(/* webpackChunkName: "about" */ '@pages/About'));
const Article = lazy(() => import(/* webpackChunkName: "article" */ '@pages/Article'));
const Blog = lazy(() => import(/* webpackChunkName: "blog" */ '@pages/Blog'));

次に、Blog 変数宣言の後に options オブジェクトを作成し、quicklink を呼び出すときに引数として使用します。

const options = {
    origins: []
};

最後に、各ルートを withQuicklink() の高階コンポーネントでラップし、そのルートのターゲット コンポーネントと options パラメータを渡します。

const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading...</div>}>
        <Route path="/" exact component={withQuicklink(Home, options)} />
        <Route path="/blog" exact component={withQuicklink(Blog, options)} />
        <Route
          path="/blog/:title"
          component={withQuicklink(Article, options)}
        />
        <Route path="/about" exact component={withQuicklink(About, options)} />
      </Suspense>
    </main>
    <Footer />
  </div>
);

上記のコードは、リンクがビューに入ったときに、withQuicklink() でラップされたルートのチャンクをプリフェッチするように指示しています。

再測定

[測定] から最初の 6 つのステップを繰り返します。まだブログページに移動しないでください。

ホームページが読み込まれると、そのルートのチャンクが読み込まれます。その後、Quicklink はビューポート内のリンクのルートのチャンクをプリフェッチします。

ホームページのプリフェッチ チャンクが表示されているネットワーク パネル。

これらのチャンクは、ページをブロックすることなく、最も低い優先度でリクエストされます。

次のステップ:

  1. ネットワーク ログをもう一度消去します。
  2. [キャッシュを無効にする] チェックボックスをオフにします。
  3. [ブログ] をクリックして、そのページに移動します。

キャッシュからピックアップされたブログページが表示されているネットワーク パネル。

[Size] 列は、これらのチャンクがネットワークではなく「プリフェッチ キャッシュ」から取得されたことを示します。クイックリンクを使用せずにこれらのチャンクを読み込むには、約 580 ミリ秒かかりました。ライブラリを使用した場合、2 ミリ秒になりました。これは 99% の削減に相当します。