前言
小站利用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
,所以我改回了第一种使用方法,但是仍然是按需打包,问题有待查找。
结束
谢谢阅读,如有谬误,恳请斧正。