透過 Quicklink 在建立回應應用程式中預先擷取

Addy Osmani
Addy Osmani
Anton Karlovskiy
Anton Karlovskiy
Demián Renzulli
Demián Renzulli

本程式碼研究室將說明如何在 React SPA 示範中實作 Quicklink 程式庫,以示範預先擷取如何加快後續導覽的速度。

測量

在新增最佳化功能之前,建議您先分析應用程式的目前狀態。

  • 按一下「Remix to Edit」,讓專案可供編輯。
  • 如要預覽網站,請按下「查看應用程式」,然後按下「全螢幕」圖示 全螢幕

這個網站是使用 create-react-app 建構的簡易示範網站,

在新開啟的分頁中完成下列操作:

  1. 按下 `Control+Shift+J 鍵 (在 Mac 上為 Command+Option+J 鍵) 開啟開發人員工具。
  2. 按一下 [網路] 分頁標籤。
  3. 勾選「停用快取」核取方塊。
  4. 「Throttling」下拉式清單中選取「Fast 3G」,模擬緩慢的連線類型。
  5. 重新載入應用程式。
  6. 在「篩選文字方塊」中輸入 chunk,即可隱藏名稱中不含 chunk 的任何資源。

顯示首頁區塊的網路面板。

網站採用路徑式程式碼分割,因為一開始只需要索取必要的程式碼。

  1. 清除開發人員工具中的網路要求
  2. 在應用程式中按一下「網誌」連結,前往該網頁。

系統會載入新路徑的 JS 和 CSS 區塊,以轉譯網頁。

顯示網誌頁面區塊的網路面板。

接下來,請在這個網站實作 Quicklink,以便在首頁中預先擷取這些區塊,加快瀏覽速度。

這可讓您結合兩項頂尖技術:

  • 路徑式程式碼分割會指示瀏覽器在網頁載入時,只以較高的優先順序載入必要的區塊。
  • 預先擷取功能會指示瀏覽器在瀏覽器閒置期間,以最低優先順序載入檢視中連結的區塊。

設定「webpack-route-manifest

第一步是安裝並設定 webpack-route-manifest。Webpack 外掛程式可讓您產生資訊清單檔案,將路徑與對應的區塊建立關聯。

通常您需要安裝程式庫,但我們已為您完成這項程序。以下是您需要執行的指令:

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

config-overrides.js 是放置在專案根目錄中的檔案,您可以在不退出專案的情況下覆寫 webpack 設定的現有行為。

  • 如要查看原始碼,請按下「檢視原始碼」

開啟 config-overrides.js 進行編輯,並在檔案開頭新增 webpack-route-manifest 依附元件:

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

接下來,將下列程式碼新增至 config-overrides.js 底部,藉此設定 webpack-route-manifest 外掛程式:

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() 包裝的路徑預先擷取區塊。

再次評估

重複執行「Measure」中的前 6 個步驟。暫時不要前往網誌頁面。

首頁載入該路徑的區塊時。之後,快速連結會預先擷取可視區域連結的路線區塊:

顯示首頁預先擷取區塊的網路面板。

這些區塊的請求優先順序最低,且不會封鎖網頁。

下一部:

  1. 再次清除網路記錄。
  2. 停用「停用快取」核取方塊。
  3. 按一下「網誌」連結即可前往該網頁。

顯示網誌頁面的網路面板,其中含有從快取中擷取的區塊。

「Size」欄表示這些區塊是從「預先擷取快取」而非網路中擷取。在沒有 Quicklink 的情況下載入這些區塊約需 580 毫秒。使用程式庫現在需要 2 毫秒,代表減少了 99%