使用 Quicklink 在 React 中加快瀏覽速度

針對 React 單頁應用程式,使用快速連結自動預先載入檢視區內的連結。

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

預先擷取是一種技術,可提前下載下一頁的資源,加快導覽速度。Quicklink 是一種程式庫,可讓您在連結進入檢視畫面時,自動預先擷取連結,以便大規模實作這項技術。

在多頁應用程式中,程式庫會為檢視區內的連結預先擷取文件 (例如 /article.html),以便使用者點選這些連結時,系統可從 HTTP 快取中擷取這些文件。

單頁應用程式通常會使用一種稱為「路徑導向程式碼分割」的技術。如此一來,網站只會在使用者前往特定路徑時載入該路徑的程式碼。這些檔案 (JS、CSS) 通常稱為「區塊」。

不過,在這些網站中,預先擷取文件的做法並非最佳做法,而是在網頁需要這些區塊之前預先擷取這些區塊,才能獲得最大的效能提升。

要達成這項目標,我們面臨了一些挑戰:

  • 在抵達特定路徑 (例如 /article) 之前,判斷哪些區塊 (例如 article.chunk.js) 與該路徑相關聯並不容易。
  • 由於新式模組套件組合器通常會使用長期雜湊法進行版本控制 (例如 article.chunk.46e51.js),因此無法預測這些區塊的最終網址名稱。

本指南說明 Quicklink 如何解決這些挑戰,並讓您在 React 單頁應用程式中大規模預先載入。

判斷與每個路徑相關聯的區塊

quicklink 的核心元件之一是 webpack-route-manifest,這是一個 webpack 外掛程式,可讓您產生路徑和區塊的 JSON 字典。這樣一來,程式庫就能知道應用程式的每個路徑需要哪些檔案,並在路徑進入檢視畫面時預先擷取這些檔案。

將外掛程式整合至專案後,系統會產生 JSON 資訊清單檔案,將每個路徑與其對應的區塊建立關聯:

{
  '/about': [
    {
      type: 'style',
      href: '/static/css/about.f6fd7d80.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/about.1cdfef3b.chunk.js',
    },
  ],
  '/blog': [
    {
      type: 'style',
      href: '/static/css/blog.85e80e75.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/blog.35421503.chunk.js',
    },
  ],
}

您可以透過兩種方式要求這個資訊清單檔案:

  • 透過網址,例如 https://site_url/rmanifest.json
  • 透過視窗物件 (位於 window.__rmanifest)。

為可視區內路徑預先擷取區塊

資訊清單檔案可供使用後,下一步就是執行 npm install quicklink 來安裝 Quicklink。

接著,您可以使用高階元件 (HOC) withQuicklink(),指出連結進入檢視畫面時,應預先擷取特定路徑。

以下程式碼屬於 React 應用程式的 App 元件,該元件會轉譯包含四個連結的頂端選單:

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

如要告知 Quicklink,這些路徑應在進入檢視畫面時預先擷取,請按照下列步驟操作:

  1. 在元件開頭匯入 quicklink HOC。
  2. 使用 withQuicklink() HOC 包裝每個路徑,並將網頁元件和選項參數傳遞給該 HOC。
const options = {
  origins: [],
};
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() HOC 會使用路徑做為索引鍵,從 rmanifest.json 取得相關聯的區塊。實際上,當連結進入檢視畫面時,程式庫會在每個區塊的網頁中插入 <link rel="prefetch"> 標記,以便預先擷取。瀏覽器會以最低優先順序要求預先擷取的資源,並將這些資源保留在 HTTP 快取中 5 分鐘,之後就會套用資源的 cache-control 規則。因此,當使用者點選連結並移動至特定路徑時,系統會從快取中擷取區塊,大幅縮短轉譯該路徑所需的時間。

結論

預先載入可大幅縮短日後導覽的載入時間。在 React 單頁應用程式中,您可以先載入與各路徑相關聯的區塊,再讓使用者前往這些路徑。Quicklink 的 React SPA 解決方案會使用 webpack-route-manifest 建立路徑和區塊對應表,以便在連結進入檢視畫面時,判斷要預先擷取哪些檔案。在整個網站中實作這項技術,可大幅改善導覽功能,讓導覽功能幾乎即時顯示。