前言
小站利用React
全家桶開發,在上線之後,發現第三方bundle
(2Mb左右)下載用了近20
秒。
最初發現的問題是nginx
壓縮配置gzip
沒有新增application/javascript
這個MIME
型別,但是仍然花了近5
秒。
解決過程
初始
起初,我的配置檔案(webpack.dll.js
)內容如下:
這個配置檔案獨立於你應用的
webpack.dev.js
或webpack.prod.js
等配置檔案
const path = require(`path`);
const webpack = require(`webpack`);
const vendors = [
`react`,
`antd`,
`lodash`
... // 其他第三方庫
]
const config = {
entry: { vendors },
output: {
filename: `[name].js`,
library: `[name]_library`, // 與 DllPlugin 的 name 保持一致
},
plugins: [
new webpack.DllPlugin({
path: path.resolve(`dll`, `[name].manifest.json`),
name: `[name]_library`, // 這裡的命名要遵循變數命名規範,它是最終的包變數名
})
]
}
複製程式碼
注
:只附關鍵程式碼,專案根目錄為project
,更多配置引數請參見官網
執行這個配置檔案之後,這樣會在/project/dll
目錄中生成兩個檔案:
vendors.js
vendors.manifest.json
我們需要在inedx.html
頁面(也在專案根目錄下)中將vendors.js
引入
<script src="/dll/vendors.js"></script>
複製程式碼
在你的webpack.dev.js
或webpack.prod.js
配置的plugins
屬性中新增對這些包的引用:
const manifestFile = path.relove(`dll, `vendors.manifest.json`); // manifest.json 檔案地址
const config = {
plugins: [
new webpack.DllReferencePlugin({
manifest: manifestFile
})
]
}
複製程式碼
改進1
考慮到瀏覽器併發請求數預設為6
個,我開始拆分第三方包(webpack.dll.js
):
const Libs = {
ui: [
`antd`
],
base: [
`lodash`
],
frame: [
`react`
]
}
const config = {
entry: { ...Libs },
... // 其他配置,同上
}
複製程式碼
執行之後,會生成三個.js
和.manifest.json
檔案,同樣你需要將.js
引用加入到你的index.js
頁面:
<script src="/dll/ui.js"></script>
<script src="/dll/base.js"></script>
<script src="/dll/frame.js"></script>
複製程式碼
而在你的webpack.dev.js
和webpack.prod.js
中,你需要多次呼叫DllReferencePlugin
外掛:
const manifestFileUi = path.relove(`dll`, `ui.manifest.json`);
const manifestFileBase = path.relove(`dll`, `base.manifest.json`);
const manifestFileFrame = path.relove(`dll`, `frame.manifest.json`);
const config = {
... // 其他配置
plugins: [
new webpack.DllReferencePlugin({
manifest: manifestFileUi
}),
new webpack.DllReferencePlugin({
manifest: manifestFileBase
}),
new webpack.DllReferencePlugin({
manifest: manifestFileFrame
})
... // 其它 plugin
]
}
複製程式碼
建議根據 Libs 變數寫個函式迴圈生成
改進2
我發現antd
、lodash
打包出來仍然很大,那麼就按需載入(webpack.dll.js
):
const Libs = {
ui: [
`antd/es/button`,
`antd/es/input`,
... // 其他你專案中用到的 UI 元件
],
base: [
`lodash/fp/get`,
`lodash/fp/set`,
... // 其他你專案中用到的函式
]
... // frame
}
複製程式碼
最終的載入時間為1
秒左右。
問題
lodash
按需載入的話,它使用方法改變如下:
// 之前
import _ from `lodash`;
_.get(...);
// 之後
import get from `lodash/fp/get;
get(...)
複製程式碼
但是第二種方法總是返回undefined
,所以我改回了第一種使用方法,但是仍然是按需打包,問題有待查詢。
結束
謝謝閱讀,如有謬誤,懇請斧正。