Open zhaobinglong opened 3 years ago
对于vue,vuex,vue-router,axios,echarts,swiper等我们可以利用webpack的externals参数来配置,这里我们设定只需要在生产环境中才需要使用。
entry: {
entry: './src/main.js',
vendor: ['vue', 'vue-router', 'vuex', 'element-ui']
},
// externals这里去扩展需要加载的第三方包,这样它们就不会再打包到js中
externals: {
echarts: 'echarts',
_: 'lodash',
jquery: "jQuery"
},
加载CDN后打包报错:Error: Cannot call .tap() on a plugin that has not yet been defined. Call plugin('html').use(
) first.
// 以loads库为例,如果只是使用到了库中的一个函数
import { name } from 'loadsh'
//不要这样写
import _ from 'loadsh'
本质上是Webpack 跟踪整个应用程序的 import/export 语句,因此,如果它看到导入的东西最终没有被使用,它会认为那是“死代码”,并会对其进行 tree-shaking 。
在编写支持 tree-shaking 的代码时,导入方式非常重要。应该避免将整个库导入到单个 JavaScript 对象中。当这样做时,是在告诉 Webpack 你需要整个库, Webpack 就不会摇它。以流行的库 Lodash 为例。一次导入整个库是一个很大的错误,但是导入单个的模块要好得多。当然,Lodash 还需要其他的步骤来做 tree-shaking,但这是个很好的起点。
// 全部导入 (不支持 tree-shaking)
import _ from 'lodash';
// 具名导入(支持 tree-shaking)
import { debounce } from 'lodash';
// 直接导入具体的模块 (支持 tree-shaking)
import debounce from 'lodash/lib/debounce';
// 配置webpack启动tree shake优化 Base Webpack Config for Tree Shaking
const config = {
mode: 'production',
optimization: {
usedExports: true,
minimizer: [
new TerserPlugin({...})
]
}
};
动态 polyfill 指的是根据不同的浏览器,动态载入需要的 polyfill。 Polyfill.io 通过尝试使用 polyfill 重新创建缺少的功能,可以更轻松地支持不同的浏览器,并且可以大幅度的减少构建体积。Polyfill Service 原理:识别 User Agent,下发不同的 Polyfill
// 在html头部插入下面的代码
<script crossorigin="anonymous" src="https://polyfill.io/v3/polyfill.min.js"></script>
const CompressionPlugin = require("compression-webpack-plugin")
chainWebpack: config => {
// 开启js、css 文件的 gzip 压缩。
// 注意,gzip 压缩需要后端配合使用。如果后端没有开发 gzip 。请关闭功能。
// 更多相关知识请查阅:
// https://blog.csdn.net/weixin_44869002/article/details/106717640
if (process.env.NODE_ENV === 'production') {
config.plugin('compressionPlugin')
.use(new CompressionPlugin({
test:/\.js$|\.html$|.\css/, // 匹配文件名
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false // 不删除源文件
}))
}
},
占楼
对于vue项目而言,不可避免的会使用一些第三方的库,这些库本身并不会运行,我们也不会修改这些库的代码,但是每当我们修改了业务代码之后,这些库也会被重新打包,极大的浪费了时间,这时我们就需要使用工具预先把静态资源提前打包,以后修改源文件再打包时就不会打包这些静态资源文件了。而webpack在打包的时候,对于一些不经常更新的第三方库,比如 d3,lodash,我们希望能和自己的代码分离开,也就是单独打包。
使用多进程并行运行来提高构建速度。并发运行的默认数量为 os.cpus().length - 1,可以显著加快构建速度,因此强烈推荐开启多进程,把这个 loader 放置在其他 loader 之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker【worker pool】 池里运行,一个worker 就是一个nodeJS 进程【node.js proces】,每个单独进程处理时间上限为600ms,各个进程的数据交换也会限制在这个时间内。
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
// 创建一个 js worker 池
use: [
'thread-loader',
'babel-loader'
]
}
]
module.exports = {
module: {
rules: [
{
test: /\.ext$/,
use: ['cache-loader', ...loaders],
include: path.resolve('src'),
},
],
},
};
如果 插件 1kb,业务逻辑代码 1Kb,改动一次业务代码,重新打包一次,每次打包就会是 2KB,如果我们采用代码分割的方式,把插件打包到一个js中,业务逻辑代码打包到一个js中,每次改动业务逻辑代码,就会只打包业务逻辑 js,只有1Kb,节省打包的时间,这就是 代码分割的主要意思。
optimization: {
usedExports: true,
splitChunks: {
chunks: 'all' // 代码分割
}
},
module: {
// 项目中使用的 jquery 并没有采用模块化标准,webpack 忽略它
noParse: /jquery/,
}
module.exports = {
optimization: {
minimizer: [
new TerserPlugin({
parallel: true,
}),
],
},
};
## 参考
https://juejin.im/post/6844904071736852487
https://www.npmjs.com/package/speed-measure-webpack-plugin
占楼
很多时候,我们由于项目人员变动比较大,参与项目的人也比较多,在分析项目时,我发现了一些问题,诸如:有些文件引入进来的库没有被使用到也没有及时删除,例如:
import a from 'abc';
在业务中并没有使用到a 模块,但webpack 会针对该import 进行打包一遍,这无疑造成了性能的浪费。
module.exports = {
chainWebpack: config => {
// 修复HMR
config.resolve.symlinks(true);
}
};
webpack默认打包js代码时,是将从入口js模块开始,将入口js模块所依赖的js以及模块逐层依赖的模块,全部以入口js模块为主体全部打包至生成的对应js文件中。即使是多个js入口依赖链模块依赖了同一个模块也会被重复打包至不同的js文件中,这种打包方式会产生比较大的代码冗余。
const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
new CommonsChunkPlugin({
// 从哪些 Chunk 中提取
chunks: ['a', 'b'],
// 提取出的公共部分形成一个新的 Chunk,这个新 Chunk 的名称
name: 'common'
})
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
占楼
webpack性能优化方向
分析webpack打包速度
分析webpack打包体积
参考
https://www.cnblogs.com/lzkwin/p/11878509.html https://www.jianshu.com/p/481e7214a134 https://www.jianshu.com/p/b358a91bdf2d