隨著專案功能的擴充、版本迭代,我們與Webpack捆綁起來的的專案越來越大,大到開始影響載入速度了。這時我們就該考慮如何對程式碼進行拆分了。
這次我們一起學習一下如何對React專案中的程式碼進行Code-Splitting(程式碼分割、程式碼拆分等各種叫法.....)。
Code-Splitting的思路有很多,很多人選擇的拆分方案是根據不同的路由進行拆分開來實現元件按需載入。存在的弊端就是這樣只是根據頂級路由的區別實現了程式碼的拆分。
而在react官方文件中的“高階指引”部分有提到一個庫—React Loadable。對於React Loadable的介紹用一句話就可以說明,route-centric code splitting is shit, component-centric splitting is cool as shit.(自行體會吧233333)。
那麼讓我們進入正題,說到基於路由拆分和基於元件拆分,git庫的readme中給出了圖解:
可以很直觀的看出來,根據路由拆分程式碼的時候還有很多可以細分的地方,比如某一條路由下包含的某些需要特定操作才展現的ui元件,這種元件沒有必要在父路由載入的時候就跟著載入。
Loadable的本質是一個高階元件,他可以很容易的以react的元件為中心對程式碼進行分割。那麼如何使用React Loadable呢?
借用官方的例子,我們分為3步進行了解,假設我們有兩個元件,元件MyComponent引入並渲染元件Bar,常規操作如下:
下面做一下昇華,當MyComponent需要渲染Bar的時候再渲染它:
這其實就已經開始複雜了,而且仔細一推敲,好多場景都沒有考慮到,比如import失敗的時候、需要做服務端渲染的時候。
這時,就可以拿出我們的Loadable來幫助我們解決這一難題了:
這樣程式碼清晰明瞭,需要考慮的場景loadable已經幫我們完成了。
Tip:當我們使用import()配合webpack2+的時候,將會自動進行程式碼分割,無需額外的配置。這就意味著當import()、webpack2+和React Loadable在一起玩的時候,我們只需要儘可能的考慮到程式碼的拆分點即可。
和常規的拆分操作對比之後,我們來看一下Loadable為我們提供了哪些api:
Loadable:
在渲染模組之前首先渲染它,他將返回一LoadableComponent(後面講到):
Loadable.Map:
允許您並行載入多個資源的高階元件,其中loader選項接收一個函式物件,並且需要一個render方法:
Loadable和Loadable.Map的接收的引數:
·loader 傳入需要載入的元件
·loading 載入中或載入失敗時展示的內容,這個選項為必填項,如果什麼都不想展示則傳入null
·delay 元件展示的延遲時間,此選項將傳遞給元件引數props.pastDelay,預設為200(單位毫秒)
·timeout 元件載入的等待時間,此選項將傳遞給元件引數props.timeOut,預設關閉。
·render 自定義已載入模組的呈現的函式,它接受兩個引數:選項loader接收的物件和props。
·webpack 選填,可以將元件變成“弱”依賴(不會將 module 引入到 bundle)中,當使用babel的時候自動執行。
·modules 選填,由要匯入模組的可選路徑組成的陣列。
LoadableComponent:
這是通過Loadable或Loadable.map返回的元件。
LoadableComponent.preload():
用於提前載入(預載入)LoadableComponent,下面假設有一個元件,點選按鈕後展示,當滑鼠劃入按鈕上的時候就開始預載入:
LoadableComponent可以接收的props:
·error 載入失敗,值為null時代表載入成功,使用案例:
·retry 重新載入(重試),使用案例:
·timeOut 布林值,請求超時時傳遞給元件,使用案例:
·postDelay 布林值,到達時間延遲後返回給元件,使用案例:
以上引數彙總使用案例:
以上就是我為大家總結出的React Loadable的功能和用法。
總結一下React Loadable的原理是通過import()返回的promise物件實現了非同步的操作。
即便如此,其實程式碼的拆分工作也不是那麼簡單,我們要確保選擇拆分的位置能夠均勻地分割程式碼包而不會影響使用者體驗,這也是一大難點。反觀本文開頭給出的對比圖片可以得到些許啟發,在基於路由拆分程式碼的基礎上進行基於元件拆分是一個不錯的起點。
最後大家可以在評論區探討一些自己拆分程式碼的好的方案、心得或者疑惑,讓我們一起探討一下吧~
歡迎大家關注我們的公眾號
Web前端Talk