載入時間從 4.6s 降到 0.7s,谷歌開源 quicklink
近日,Google 團隊在 GitHub 上開源了一個專案 quicklink,quicklink 能在空閒時預取 viewport 內的連結來加快後續頁面的載入速度。具體的技術原理和實現過程請看下文。
工作原理
quicklink 通過以下措施加快後續頁面的載入速度:
-
檢測 viewport 中的連結,使用 Intersection Observer 。
-
等待瀏覽器空閒,使用 requestIdleCallback 。
-
檢查使用者的連線速度(使用 navigator.connection.effectiveType)或者是否啟用了 data-saver(使用 navigator.connection.saveData);
-
預取連結(使用
或 XHR),可以控制請求優先順序(如果支援,可以切換到 fetch())。
為什麼要推出 quicklink?
quicklink 旨在成為根據使用者 viewport 中的連結預取內容的簡易解決方案,而且要保持很小的體積(壓縮後小於 1KB)。
安裝
複製程式碼
npminstall--save quicklink
也可以從 unpkg.com/quicklink
下載 quicklink。
用法
在初始化後,quicklink 將自動在空閒時預取 viewport 內的連結。
複製程式碼
<!-- Include quicklink from dist --> <scriptsrc="dist/quicklink.umd.js"></script> <!-- Initialize (you can do this whenever you want) --> <script> quicklink(); </script>
例如,你可以在 load 事件觸發後進行初始化:
複製程式碼
<script> window.addEventListener('load', () =>{ quicklink(); }); </script>
ES 模組匯入:
複製程式碼
import quicklink from"quicklink/dist/quicklink.mjs"; quicklink();
上面的選項最適合多頁面網站。單頁應用程式也有幾個可用的選項:
- 在完成新路由導航後呼叫 quicklink();
- 針對特定的 DOM 元素 / 元件呼叫 quicklink();
- 使用自定義 URL 呼叫 quicklink({urls:[…]}) 進行預取。
API
quicklink 可以接受帶有以下引數的可選選項物件:
-
el:包含需要預取的連結的 DOM 元素;
-
urls:要預取的 URL 陣列(不是在 viewport 中檢測到的文件或 DOM 元素的連結);
-
timeout:requestIdleCallback 超時時間,瀏覽器執行預取的時間(以毫秒為單位),預設為 2 秒;
-
timeoutFn:用於指定超時的函式,預設為 requestIdleCallback,也可以替換為 networkIdleCallback 等自定義函式;
-
priority:布林值,指定預取優先順序,預設為 false。如果設定為 true,將嘗試使用 fetch() API(而不是 rel=prefetch);
-
origins:允許預取的 URL 主機名字串陣列。預設為與域名相同的 origin,防止跨 origin 請求;
-
ignores:一個 RegExp 函式或陣列,用於決定是否應該預取某個 URL。在 orign 匹配之後執行。
待完成事項:
-
檢測資源的副檔名,並使用 rel=preload 進行高優先順序預取;
-
使用 Priority Hints 進行重要性提示。
polyfill
quicklink:
-
可以回退到 requestIdleCallback;
-
需要支援 IntersectionObserver,請參閱 CanIUse 。我們建議使用 Polyfill.io 等服務來有條件地 polyfill 該功能:
複製程式碼
<scriptsrc="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
一些示例
設定自定義的資源預取超時時間
預設為 2 秒(通過 requestIdleCallback),在這裡我們將其設定為 4 秒:
複製程式碼
quicklink({ timeout:4000 });
設定包含預取 URL 的 DOM 元素
如果不設定,預設為 document。
複製程式碼
constelem =document.getElementById('carousel'); quicklink({ el: elem });
設定預取 URL 陣列
如果你想要直接提供預取 URL 的列表,而不是去檢測 viewport,可以使用 URL 陣列。
複製程式碼
quicklink({ urls: ['2.html','3.html','4.js'] });
設定預取的請求優先順序
預設為低優先順序(rel=prefetch 或 XHR)。對於高優先順序(priority: true),嘗試使用 fetch(),或者回退到 XHR。
複製程式碼
quicklink({priority: true });
指定 origin 自定義列表
提供可預取的主機名列表。預設情況下只允許來自相同 origin 的 URL。
複製程式碼
quicklink({ origins: [ // add mine 'my-website.com', 'api.my-website.com', // add third-parties 'other-website.com', 'example.com', // ... ] });
允許所有 origin
啟用所有跨 origin 請求。
複製程式碼
quicklink({ origins: true, // or origins: [] });
自定義 Ignore 模式
這些過濾器在 origin 匹配之後執行,對於避免下載大檔案或動態響應 DOM 屬性來說非常有用。
複製程式碼
// Same-origin restraint is enabled by default. // // This example will ignore all requests to: // - all "/api/*" pathnames // - all ".zip" extensions // - all <a> tags with "noprefetch" attribute // quicklink({ ignores: [ /\/api\/?/, uri=>uri.includes('.zip'), (uri, elem) =>elem.hasAttribute('noprefetch') ] });
你可能希望忽略包含 URL 片段的 URL(例如 index.html #top)。如果你在頁面中使用了錨點或為單頁面應用程式設定了 URL 片段,希望避免觸發此類 URL 的預取, 那麼這項功能非常有用。
複製程式碼
quicklink({ ignores: [ uri => uri.includes('#') // or RegExp: /#(.+)/ // or element matching: (uri, elem) => !!elem.hash ] });
瀏覽器支援
quicklink 提供的預取可以被視為一種漸進式增強。跨瀏覽器支援情況如下:
-
沒有 polyfill:Chrome、Firefox、Edge、Opera、Android Browser, Samsung Internet。
-
使用 Intersection Observer polyfill:Safari、IE11。
-
上面的再加上 Set() 和 Array.from polyfill:IE9 和 IE10。 Core.js 提供了 Set() 和 Array.from() 填充,也可以考慮 es6-shim 。
提供了某些功能的分層支援:
-
Network Information API ,用於檢查使用者的連線型別(通過 navigator.connection.effectiveType),僅適用於 Chrome 61+ 和 Opera 57+。
-
如果選擇{priority: true}並且 Fetch API 不可用,則將使用 XHR。
直接使用 prefetcher
quicklink 包含一個 prefetcher,可以單獨匯入到其他專案中使用。在將 quicklink 作為依賴項安裝好以後,可以按如下方式使用它:
複製程式碼
<scripttype="module"> importprefetchfrom'../src/prefetch.mjs'; consturls = ['1.html','2.html']; constpromises = urls.map(url=>prefetch(url)); Promise.all(promises); </script>
演示
這裡是一個 WebPageTest 演示 。
通過使用 quicklink,將頁面載入時間減少了 4 秒。這裡是進行預取前後的比較 視訊 。
出於演示的目的,我們在 Firebase 上部署了一個谷歌部落格,然後我們又部署了另一個版本,在主頁上添加了 quicklink,並測試從主頁導航到文章的速度,結果預取版本的載入速度更快。
請注意:這並不是一個針對 viewport 內連結預取優缺點的詳盡基準測試,我們只是演示了這個方法可以為我們帶來的潛在改進。
英文原文: https://github.com/GoogleChromeLabs/quicklink
更多內容,請關注前端之巔。