前言
專案後臺使用antd的元件,一直感覺很好很強大。無奈整體打包的話太大,光是antd的js就有990k(3.1.1),所以著手優化打包後的大小。
使用官方推薦的babel-plugin-import外掛
基本上前期元件使用少的情況下,這個外掛完美解決了問題。這個外掛其實是優化了寫法,將本應該
import Button from 'antd/lib/button';
import 'antd/lib/button/style'; // 或者 antd/lib/button/style/css 載入 css 檔案
複製程式碼
優化成了
import { Button } from 'antd';
複製程式碼
本質上是單獨引入了Button元件,打包的時候當然只會將Button元件打進去。
模板初始情況
-
使用CommonsChunkPlugin外掛將react,,react-dom,react-router-dom包單獨匯出成vendor.js。
-
使用babel-plugin-import外掛按需引入antd元件。
-
專案初始包含兩個頁面,使用HashRouter:主頁(Home.js)->app.js和使用bundle-loader非同步載入的列表頁(List.js)->app-list.js
import ListC from 'bundle-loader?lazy&name=app-list!./List'; const List = Bundle(ListC) ... <Route path={`${match.url}/list`} component={List} /> 複製程式碼
-
模板初始時沒有使用任何ui元件,build後各資源大小如下:
app.js->15k app-list->1.5k vendor.js->150k(包含react,react-dom,react-router-dom) 複製程式碼
使用antd元件配合非同步載入(以Button元件為例,List和Home裡均使用了Button)
-
只在List元件裡使用Button元件
app.js->15k app-list->99k vendor.js->150k 複製程式碼
-
只在Home元件裡使用Button元件
app.js->113k app-list->1.5k vendor.js->150k 複製程式碼
-
Home和List元件都使用Button元件
app.js->113k app-list->1.63k vendor.js->150k 複製程式碼
結論:可以看出antd配合非同步載入Button元件不會重複打包,如果Home和List元件都使用Button元件,只在app.js裡打包了Button元件
使用commonChunk將antd打入vendor,同時開啟antd按需引入(以Button元件為例,List和Home裡均使用了Button)
app.js->94k
app-list->1.64k
vendor.js->1.38M !!!
複製程式碼
結論:也就是說完整的antd被打入vendor,而且按需引用Button元件的時候又打包了一次
使用commonChunk將antd打入vendor,同時關閉antd按需引入:
app.js->15.2k
app-list->1.61k
vendor.js->1.38M !!!
複製程式碼
結論:完整的antd被打入vendor,引用Button的時候雖然沒有重複打包,但是我們強烈需要按需引入,畢竟antd 990k大。
開啟dll打包(react,react-dom,react-router-dom),開啟CommonsChunkPlugin外掛(react,react-dom,react-router-dom),開啟antd按需引用
app.js->113k
app-list->1.61k
vendor.js->1.6k
common-1.0.0.js->161k
複製程式碼
結論:DllPlugin外掛其實與CommonsChunkPlugin作用差不多,區別是CommonsChunkPlugin每次重新打包打出的vendor.js都會改變,而DllPlugin外掛打出的common.js是不變的。如果兩個外掛同時使用並且打包的庫也相同(react,react-dom,react-router-dom),那麼commonChunk打出的vendor內容基本上會全到common.js裡。antd按需引用的元件沒有被重複打包,此種情況也就是說可以省掉commonChunk元件打react,react-dom,react-router-dom的步驟了。
增加多入口(app.js app2.js),關閉commonChunk外掛,開啟dll,開啟antd按需引用
app.js->114k(使用Button元件)
app2.js->4.88k(未使用Button元件)
app-list->1.63k(使用Button元件)
app-list2->105k(使用Button元件)
common-1.0.0.js->161k
複製程式碼
結論:dll外掛可以達到commonChunk的作用,然後用此腳手架為模板新開一個專案,發現common-1.0.0.js在另一個專案中也通用,直到dll外掛中打的庫發生改變(react,react-dom,react-router-dom)
使用webpack的externals屬性,將react,react-dom,react-router-dom通過script引入,不使用antd任何元件,不使用commonChunk和dll.
app.js->12.4k(不使用Button元件)
複製程式碼
使用webpack的externals屬性,將react,react-dom,react-router-dom通過script引入,使用antd Button元件
app.js->115.k(使用Button元件)
app-list->1.63k(使用Button元件)
複製程式碼
使用webpack的externals屬性,將react,react-dom,react-router-dom,antd通過script引入,使用antd Button元件
app.js->16.6k(使用Button元件)
app-list->1.61k(使用Button元件)
複製程式碼
結論:此種方法成功把antd剝離出去了,但是html裡需要引入antd.min.js和antd.min.css和moment.min.js!!!,moment.min.js必須放在antd之前,否則datepicker元件會報錯。同時,.babelrc檔案裡需要去掉babel-plugin-import的使用,如果不去掉,app.js會有115k,也就是說antd的Button元件還是會被打進了app.js裡。
綜上:
- 使用AutoDllPlugin外掛替代webpack自帶的dllPlugin外掛更加方便。
- 使用AutoDllPlugin與commonChunk外掛都可以,如果不要求多專案公用基礎js的話。
- 使用extarnals無法使用按需載入。
- commonChunk+antd按需引入+頁面按需載入使用最方便。
- 使用頁面按需載入時,為防止元件被多個頁面重複打包,可將元件放到根元件上。例如:app-list與app-list頁面均使用Button,但根元件app.js沒有使用,那麼app-list和app-list都會把Button打進各自的js裡,打包時間將會延長,可將Button在app.js裡使用下,這樣app-list和app-list都不會在打Button了。