移動端H5預載入方案

advence-liz發表於2019-06-04

移動端H5預載入方案

最近對移動端預載入方案進行了一些調研整理此文備忘分享

prefetch

prefetch是一種瀏覽器機制,其利用瀏覽器空閒時間來下載或預取使用者在不久的將來可能訪問的文件。網頁向瀏覽器提供一組預取提示,並在瀏覽器完成當前頁面的載入後開始靜默地拉取指定的文件並將其儲存在快取中。當使用者訪問其中一個預取文件時,便可以快速的從瀏覽器快取中得到。

<link rel="prefetch" href="/images/big.jpeg">
複製程式碼

Can I use

preload

<link> 元素的 rel 屬性的屬性值preload能夠讓你在你的HTML頁面中 <head>元素內部書寫一些宣告式的資源獲取請求,可以指明哪些資源是在頁面載入完成後即刻需要的。對於這種即刻需要的資源,你可能希望在頁面載入的生命週期的早期階段就開始獲取,在瀏覽器的主渲染機制介入前就進行預載入。這一機制使得資源可以更早的得到載入並可用,且更不易阻塞頁面的初步渲染,進而提升效能。本文提供了一個如何有效使用preload機制的基本說明。

 <link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
複製程式碼

Can I use

prefetch & preload 小結

上文主要擷取了MDN上的文章簡要介紹一下prefetch和preload的特性,看起來其實都還不錯但是相容性有些堪憂對於多數的業務開發看起來是並不能投入使用的,如果想了解更多關於 prefetch和 preload 的細節可以閱讀文章底部的參考連結

webpack對prefetch 和 preload的支援

現在大多數人都是使用webpack做為構建工具如果你所參與的專案只需要相容較高的版本的瀏覽器那麼你可以輕鬆的依靠webpack 完成預載入功能,webpack 魔法註釋就可以完成向引用的頁面自動新增 preload & prefetch link 標籤的能力。

webpack 魔法註釋

通過新增內聯的註釋賦予import()動態載入語法更多實用的特性,比如給chunk命名,使用不同的webpackMode,prefetch,preload 等。

import(
  /* webpackInclude: /\.json$/ */
  /* webpackExclude: /\.noimport\.json$/ */
  /* webpackChunkName: "my-chunk-name" */  `賦予 chunk 指定的名字`
  /* webpackMode: "lazy" */  `這個是預設值使用import()你什麼也不加預設就是這個mode`
  /* webpackPrefetch: true */ `賦予 chunk prefetch能力`
  /* webpackPreload: true */`賦予 chunk preload能力`
  `./locale/${language}`
);
複製程式碼

webpack魔法註釋佔位符

在 webpack 2.6.0 支援倆個佔位符[index][request]一個是自增id,一個是變數匹配的檔名

import(/* webpackChunkName: "[request]" */ `../${component}/index`)//最終生成的chunkname就是對應元件的目錄名稱類似這種'_some-component_index-[hash].js`
複製程式碼

react-loadable 預載入

因為我們使用的react技術棧且同時也正在使用react-loadable載入非同步元件,且react-loadable也自帶預載入功能所以最終選擇的使用react-loadable的預載入功能。

react-loadable預載入跟webpack自動插入link標籤的方式不同它是在觸發preload方法時直接將對應的script標籤插入body下,下載完畢直接執行,好處能就是這個不需要考慮相容性穩穩的都可以,美中不足呢就是直接執行了js不過影響不大因為只是執行的非同步元件的定義,而元件的生命週期函式並沒有執行(稍微解釋一下為什麼只執行定義而不執行生命週期,因為在使用非同步載入元件必然都會配合react-router使用,所以在A頁面預載入B但是並不會執行B生命週期函式)

// 官方DEMO
const LoadableBar = Loadable({
  loader: () => import('./Bar'),
  loading: Loading,
});

class MyComponent extends React.Component {
  state = { showBar: false };

  onClick = () => {
    this.setState({ showBar: true });
  };

  onMouseOver = () => {
    LoadableBar.preload();
  };

  render() {
    return (
      <div>
        <button
          onClick={this.onClick}
          onMouseOver={this.onMouseOver}>
          Show Bar
        </button>
        {this.state.showBar && <LoadableBar/>}
      </div>
    )
  }
}
複製程式碼

總結

preload & prefetch 等等新標準看起來都很美好只是瀏覽器支援情況不是那麼理想很難直接投入使用,網上介紹這些特性的文章蠻多的不過讀的時候要注意時效性。

webpack 內建支援了preload & prefetch相信不久的將來通過webpack輕鬆的完成預載入會是最廣泛簡單的做法

react-loadable 外掛解決了當前的燃眉之急可以相容低版本的瀏覽器作為專案預載入方案使用

參考

一籮筐的預載入技術

prefetch和預載入實踐

preload,prefetch 和它們在chrome中的優先順序

react程式碼分割

相關文章