上一篇咱们讲到,webpack3.x 升级 4.x 时遇到的问题、缘由和解决方案,今天讲一下 webpack 4.x
的打包优化。node
在优化以前咱们须要清楚项目的打包状况,npm run build
后 webpack
会将打包信息打印到终端,像这样:webpack
可以看到有好几个文件比较大,可是并不清楚具体包含哪些模块,哪些模块适合单独提取,哪些模块不适合提取,这个时候就须要用到打包分析的工具。nginx
如下摘自 webpack 文档:git
Bundle Anlysis - 打包分析github
一旦开始分割代码,分析输出以检查模块在哪里结束将颇有用。official analyze tool 是一个很好的起点。 还有一些其余社区支持的选项:web
- webpack-chart: 用于 webpack 统计信息的交互式饼图
- webpack-visualizer: 可视化和分析您的包,以查看哪些模块正在占用空间,哪些多是重复的。
- webpack-bundle-analyzer: 一个插件和 CLI 实用程序,将包内容表示为方便的交互式可缩放树形图。
- webpack bundle optimize helper: 此工具将分析您的捆绑包,并为您提供切实可行的建议,以进行改进以减少捆绑包的大小。
- bundle-stats: 生成捆绑报告(捆绑大小,资产,模块),并比较不一样版本之间的结果。
这里咱们使用的是 webpack-bundle-analyzer
,交互式可缩放树形图,便于咱们对打包状况有一个比较直观的了解。npm
安装插件element-ui
npm i -D webpack-bundle-analyzer
复制代码
引入插件浏览器
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()],
};
复制代码
而后咱们再试着构建如下,看会怎么样缓存
npm run build
复制代码
插件会自动在浏览器中打开连接:http://127.0.0.1:8888/ ,以交互式可缩放树形图展现了当前项目的打包状况,能够清楚的看到各个文件包含的模块,针对性的处理:
分析上面 👆 的树形图,概括了如下几个能够优化的点:
将 optimization.splitChunks
属性的默认值删除,而后在 cacheGroups
中配置以下:
webpack.prod.js
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
optimization: {
splitChunks: {
- chunks: "async",
- minSize: 30000,
- maxSize: 0,
- minChunks: 1,
- maxAsyncRequests: 5,
- maxInitialRequests: 3,
- automaticNameDelimiter: "~",
- automaticNameMaxLength: 30,
- name: true,
cacheGroups: {
+ common: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-common',
+ minSize: 0,
+ minChunks: 2, // 最少被2个chunk引用
+ chunks: 'initial',
+ priority: 1 // 优先级,默认是0,能够为负数
+ },
+ other: {
+ test: /[\\/]node_modules[\\/]/,
+ name: 'vendors-other',
+ chunks: 'initial',
+ priority: -10
+ },
- defaultVendors: {
- test: /[\\/]node_modules[\\/]/,
- priority: -10
- },
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
// ..
});
// ..
module.exports = webpackConfig;
复制代码
咱们再次构建,看看
npm run build
复制代码
能够看到拆分出了几个包含 node_modules
的大文件:
swiper
,单个组件中引入的依赖,webpack
会自动提取)比较一下代码拆分先后的两个入口加载文件大小的不一样:
入口 2 没有变化,入口 1 的加载文件大小减小的 0.62MB
,缩小将近 25%
,固然这是没有进行 gzip
压缩的状况,在 nginx
服务器上启用 gzip
压缩总体大小会更小,这里就不展开了
若是你想单独将某些依赖,单独提取出来,能够看看官方的这个例子,若是你的项目依赖较少,你彻底能够按你喜欢的组合,手动拆分你的项目依赖到多个文件中。
当访问网页时,请求的文件会存储在浏览器的缓存中,当下次再访问时,若是知足HTTP 缓存机制,浏览器能够从缓存中读取文件,而没必要从服务器读取,甚至不用发起请求,能够显著提高加载速度并减小流量消耗。
可是若是项目从新构建,而用户浏览器中的缓存还未过时,想要快速更新并继续保留部分缓存,该怎么作呢?
更多细节请看,HTTP 缓存-废弃和更新缓存的响应
对此 webpack
打包须要优化一下几点:
webpack.prod.js
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
output: {
// ..
- filename: utils.assetsPath('js/[name].[chunkhash].js')
+ // 根据文件内容生成的 hash,文件内容改变时 hash 也随之改变
+ filename: utils.assetsPath('js/[name].[contenthash].js')
},
optimization: {
+ // 运行时块包含模块间的引用关系,将它提取出来做为单独的文件,引用关系发生改变时,不会致使无关的文件内容发生改变
+ runtimeChunk: 'single',
+ // 由于使用 hashed,当本地新增或减小依赖时,不会影响其余模块的 ID(默认状况下 ID 的值是根据解析顺序递增的)
+ moduleIds: 'hashed'
// ...
}
});
// ..
module.exports = webpackConfig;
复制代码
更多细节请看,webpack 文档-缓存(快取)
代码拆分的过程当中,有尝试过基于现有配置的基础上,单独拆分出指定依赖(如 Element-UI
,由于不常改动且文件较大),可是会破坏现有的拆分,屡次尝试以后无果,最接近的时候是这样的,入口 1 会将其包含在文件中,可是入口 2 不会,当前项目有两个入口:
采用以下配置:
// ..
const webpackConfig = merge(baseWebpackConfig, {
// ..
optimization: {
splitChunks: {
cacheGroups: {
common: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
name: 'vendors-common',
minSize: 0,
minChunks: 2, // 最少被2个chunk引用
chunks: 'initial',
priority: 1 // 优先级,默认是0,能够为负数
},
other: {
- test: /[\\/]node_modules[\\/]/,
+ test: /[\\/]node_modules[\\/]((?!(element-ui)).)+[\\/]/,
name: 'vendors-other',
chunks: 'initial',
priority: -10
},
+ 'element-ui': {
+ test: /[\\/]node_modules[\\/](element-ui)[\\/]/,
+ name: 'vendor-element-ui',
+ chunks: 'initial',
+ priority: -15
+ },
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
// ..
});
// ..
module.exports = webpackConfig;
复制代码
后续有处理方案后会更新,到这里打包大小优化就告一段了,下一篇会讲讲如何对打包速度进行优化。