小站利用React
全家桶開發,在上線以後,發現第三方bundle
(2Mb左右)下載用了近20
秒。 最初發現的問題是nginx
壓縮配置gzip
沒有添加application/javascript
這個MIME
類型,可是仍然花了近5
秒。javascript
起初,個人配置文件(webpack.dll.js
)內容以下:html
這個配置文件獨立於你應用的
webpack.dev.js
或webpack.prod.js
等配置文件java
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
,更多配置參數請參見官網react
運行這個配置文件以後,這樣會在/project/dll
目錄中生成兩個文件:webpack
vendors.js
vendors.manifest.json
咱們須要在inedx.html
頁面(也在項目根目錄下)中將vendors.js
引入nginx
<script src="/dll/vendors.js"></script>
複製代碼
在你的webpack.dev.js
或webpack.prod.js
配置的plugins
屬性中添加對這些包的引用:web
const manifestFile = path.relove('dll, 'vendors.manifest.json'); // manifest.json 文件地址
const config = {
plugins: [
new webpack.DllReferencePlugin({
manifest: manifestFile
})
]
}
複製代碼
考慮到瀏覽器併發請求數默認爲6
個,我開始拆分第三方包(webpack.dll.js
):json
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
插件:bash
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 變量寫個函數循環生成
我發現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
,因此我改回了第一種使用方法,可是仍然是按需打包,問題有待查找。
謝謝閱讀,若有謬誤,懇請斧正。