《前端那些事》聊聊前端的按需加載

樹醬但願將前端的樂趣帶給你們 本文已收錄 github.com/littleTreem… 喜歡就star✨html

前沿:按需加載是性能優化其中的一個環節,能夠是圖片的按需加載,也就是lazyload來實現按需加載的場景,也能夠是組件庫的引入,只需部分組件的使用而無需全局引入整個組件庫的場景,又能夠是路由的按需加載,當路由被訪問的時候才加載對應組件的場景,以此來實現更高效率的使用等等,本文把「懶加載」也劃分爲按需加載前端

1.圖片按需加載

場景:當一個頁面存在須要多個圖片加載的場景時,能夠經過咱們常常看到的所謂「懶加載」,當滑動到圖片相應的位置時再加載圖片的信息,以此來實現按需加載,舉個最簡單的例子,你去逛淘寶的時候,電商網站圖片信息是不少的,這個時候若是把當前頁面下的圖片都將資源請求過來,是很消耗資源的,對網站的體驗也是極其很差,只須要加載你當前「視線」下的圖片便可,vue技術棧中vue-lazyload便可實現,下面聊聊它的使用和原理vue

1.1 vue-lazyload是什麼

本質上懶加載就是,在適當的時候加載用戶須要看的資源(可視區域),當頁面開發時將src路徑先預先設置好屬性,這樣頁面加載時圖片就不會立刻向服務器請求資源,而是當圖片滾動到可視區內時,再給src賦值並加載資源,而vue-lazyload就是基於這個概念實現的一個vue的工具庫,官方介紹:A Vue.js plugin for lazyload your Image or Component in your application。使用文檔點我👈webpack

1.2 正確使用姿式

  • 安裝
npm i vue-lazyload 
複製代碼
  • 如何使用

在main.js中經過vue實例加載插件git

import Vue from 'vue'
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload);
複製代碼

頁面中的使用,經過給圖片定義v-lazy屬性,以下所示github

<ul>
  <li v-for="img in list">
    <img v-lazy="img.src" >
  </li>
</ul>
複製代碼

1.3實現原理

經過幾個核心的點來介紹下vue-lazyload原理web

  • 定義LazyClass核心函數並獲取lazy對象

經過Lazy和LazyClass獲得了lazy這個對象,看看Lazy類的構造函數,源碼連接點我vue-cli

  • 定義自定義指令lazy,區分vue版本 1x和2x的定義

vue-lazyload是經過指令的方式來實現的,定義v-lazy指令,該指令對應的幾個回調函數:bind、update、componentUpdated和unbind分別綁定的是lazy對象的add、update、lazyLoadHandler和remove方法,以下所示npm

關於vue指令能夠看官方文檔進一步瞭解:官方文檔element-ui

  • 經過addLazyBox給圖片dom綁定scroll事件,並push到監聽隊列(listener queue)

指令被bind時會建立一個listener,並將其添加到listener queue裏面, 而且搜索target dom節點,爲其註冊dom事件

  • 經過checkInView檢測判斷當前dom是否能夠加載圖片

checkInView方法被封裝到_lazyloadHandler的方法,本質上是lazy構造器中使用的lazyloadHandler()函數,經過checkInView()函數檢測位置是否須要加載,若是須要返回true,並觸發load函數加載圖片

它還經過throttle節流函數來限制一個函數在必定時間內只能執行一次,由於像scroll這些事件觸發頻率高,不作限制的話,一秒以內可能執行幾十次

2.組件的按需加載

場景:當我須要使用某個組件庫的某個組件時,不想所有加載整個組件庫,這個時候就須要按需加載了,能夠解決一個首屏加載問題,下降首屏加載時間,舉個例子,我如今須要用到element-ui庫中的button組件,那我應該如何按需加載呢?

2.1 組件庫的按需加載

以element-ui爲例子,若是全局加載,會致使打包出來的包體積過大,影響交互體驗,以下所示就是一個webpack打包後的webpack-bundle-analyzer工具分析出來的report,你能夠經過 vue-cli中的命令生成report.html查看

"scripts": {
    "build": "vue-cli-service build --report",
 }
複製代碼

那怎麼去經過按需加載去使用組件庫,答案是經過babel插件:babel-plugin-component(element 經過fork ant-design庫的 )

在babel轉碼的時候,把整個庫element-ui的引用,變爲element-ui/lib/button具體模塊的引用。這樣webpack收集依賴module就不是整個element-ui,而是裏面的button

相似如何的轉換

如何安裝

npm install babel-plugin-component –D
複製代碼

使用以下所示👇

在main.js中使用以下

2.2 項目中組件的按需加載

簡單理解就是把咱們的組件變成了一個函數,起初不執行它,只有你須要它的時候,也就是頁面加載時,才觸發它加載進來。

3.路由中的按需加載

簡單而言則是路由懶加載,當咱們用webpack打包並構建應用時,輸出的bundle 包會變得很是大,影響頁面加載和體驗。若是能將不一樣路由對應的組件分割成不一樣的代碼塊,而後當路由被訪問的時候才加載對應組件,而不是一開始所有加載,這樣就更加高效了

3.1 vue的異步組件加載

能夠將異步組件定義爲返回一個 Promise (返回的 Promise 應該 resolve 組件自己)

3.2 結合Webpack 2和ES語法使用import()

咱們能夠使用動態 import語法來定義代碼分塊點 (split point)

咱們看看import一個組件返回的是什麼? promise!

那麼如何定義一個可以被 Webpack 自動代碼分割的異步組件呢?以下所示

若是你使用的是 Babel去支持import加載,則須要添加 syntax-dynamic-import 插件,才能使 Babel 能夠正確地解析語法,不然會報語法錯誤,以下所示

3.3 webpack的require.ensure() [不推薦]

使用webpack的require.ensure來實現按需加載,不過目前已經被上一節提到的 import() 取代

往期文章

相關文章
相關標籤/搜索