一、缩小文件搜索范围
1. 减少loader处理的文件
loader对文件的转换操作很耗时,因此我们最好精准匹配要转换的文件
loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
babel-loader
用于转换ES6代码,文档说了它的几个特点:
- 慢!
- 代码体积变大!
```javascript
// 转换前Vue-Cli默认配置:
{
}test: /\.m?jsx?$/, // 项目中如果只有js文件就写js就好,提高正则表达式性能
exclude: [
function () { /* omitted long function */ }
],
use: [
/* config.module.rule('js').use('babel-loader') */
{
loader: 'D:\\CS\\Repositories\\project\\erabbit-pc-vue-project\\node_modules\\babel-loader\\lib\\index.js',
options: {
cacheCompression: false,
cacheDirectory: 'D:\\CS\\Repositories\\project\\erabbit-pc-vue-project\\node_modules\\.cache\\babel-loader',
cacheIdentifier: '26fa99d2'
}
}
]
// 修改配置 { test: /.js$/, use: [ { loader: ‘babel-loader’, options: { cacheDirectory: true } } ], include: path.resolve(__dirname, ‘src’) }
<a name="UwKna"></a>
## 2. 优化resolve.modules
用于配置去哪找第三方模块,默认值是 ['node_modules'],含义是先去当前目录下的 ./node_modules 目录下去找想找的模块,如果没找到就去上一级目录 ../node_modules 中找,再没有就去 ../../node_modules 中找,以此类推<br />当安装的第三方模块都放在项目根目录下的 ./node_modules 目录下时,没有必要按照默认的方式去一层层的寻找,可以指明存放第三方模块的绝对路径,以减少寻找.
```javascript
// vue-cli默认配置
modules: [
'node_modules',
'D:\\CS\\Repositories\\project\\erabbit-pc-vue-project\\node_modules',
'D:\\CS\\Repositories\\project\\erabbit-pc-vue-project\\node_modules\\@vue\\cli-service\\node_modules'
]
// 修改
resolve: {
modules: [path.resolve(__dirname, 'node_modules')]
}
3. 优化 resolve.mainFields 配置
用于配置第三方模块使用哪个入口文件,与target配置有关。
由于一些第三方模块可能可以支持不同的环境,会有多个不同的入口,但大多数都是以main
为入口,不过我觉得这一项还是不要改好。
resolve: {
// 只采用 main 字段作为入口文件描述字段,以减少搜索步骤
mainFields: ['main'],
},
4. 配置resolve.alias
用于配置导入第三方模块时要加载的文件路径,比如一个包有一个入口文件,依赖于很多其它的文件,每次加载都需要去解析所有文件,一般包都会有一份打包好的生产环境的文件,可以配置别名为该文件路径,这样就可以直接加载,但是这样无法配置treeshaking去除重复代码。
5. 优化rsolve.extensions
当省略文件后缀时会采用该配置列表中的后缀去查找,列表越小越好,
// 默认
resolve: {
// 尽可能的减少后缀尝试的可能性
extensions: ['.js', '.json'],
},
// 修改
extensions: ['.js']
6. 优化 module.noParse 配置
用于配置不需要解析的文件,忽略对部分没采用模块化的文件的递归解析处理,这样做的好处是能提高构建性能。如
const path = require('path');
module.exports = {
module: {
// 独完整的 `react.min.js` 文件就没有采用模块化,忽略对 `react.min.js` 文件的递归解析处理
noParse: [/react\.min\.js$/],
},
};
二、thread-loader多进程处理
官方的一个loader(文档)
一般可以用于对babel-loader开启多进程,仅在耗时的操作中使用此 loader!
可能我的项目中js文件不多,感觉没啥提升
// 安装
yarn add thread-loader -D
// 在耗时的loader如babel-loader前配置即可
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'thread-loader'
},
{
loader: 'babel-loader',
options: {
cacheDirectory: true
}
}
],
include: path.resolve(__dirname, 'src')
}
]
},
三、构建速度分析插件
// 安装
yarn add -D speed-measure-webpack-plugin
// 导入使用
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
configureWebpack: smp.wrap({
//...webpack的配置
})
打包之后会在控制台输出,
四、使用 ParallelUglifyPlugin
由于压缩 JavaScript 代码需要先把代码解析成用 Object 抽象表示的 AST 语法树,再去应用各种规则分析和处理 AST,导致这个过程计算量巨大,耗时非常多。
插件github
// 安装
yarn add webpack-parallel-uglify-plugin -D
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
plugins: [
// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
new ParallelUglifyPlugin({
// 传递给 UglifyJS 的参数
uglifyJS: {
output: {
// 最紧凑的输出
beautify: false,
// 删除所有的注释
comments: false
},
compress: {
// 在UglifyJs删除没有用到的代码时不输出警告,这一项报错说不支持wrnings
// warnings: false,
// 删除所有的 `console` 语句,可以兼容ie浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true
}
}
})
]
配置完打包发现时间反而上去了,插件自己就花了一秒多。