webpack性能优化 | 8月更文挑战

250 阅读3分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战

首先说明优化目的:

1、加速打包时间

2、减少打包后的体积

一、加速打包时间

要加速打包时间,就需要先缩⼩⽂件搜索范围,一般影响整体打包的时间主要是loader和plugin两个的编译构建的过程。需要先压缩,再优化,可以减少很多打包时间。所以我们要先减少搜索文件的过程,提前编译和缓存等几个方法实现

1、优化loader查找文件范围

可以使用test、include、exclude三个配置项来缩⼩loader的处理范围,推荐include

//string
    include: path.resolve(__dirname, "./src"),
//array
include: [
     path.resolve(__dirname, 'app/styles'),
     path.resolve(__dirname, 'vendor/styles')
]

注:exclude 优先级要优于 include 和 test ,所以三个都配置时, exclude 会优先于其他两 个配置

2、优化resolve.modules配置

reslove.modules用于配置webpack打包后在哪个目录下查找模块,默认是node_modules,可以配置:

module.exports={
     resolve:{
         modules: [path.resolve(__dirname, "./node_modules")]
     }
}

3、优化resolve.alias配置

resolve.alias主要是配置别名,把原路径映射为一个新配置的路径,我们可以直接指定文件路径,避免查找的耗时

alias: {
     "@": path.join(__dirname, "./pages"),
     react: path.resolve(
         __dirname,
         "./node_modules/react/umd/react.production.min.js"
     ),
     "react-dom": path.resolve(
         __dirname,
         "./node_modules/react-dom/umd/react-dom.production.min.js"
     )
},
resolve: {
     alias: {
         "@assets": path.resolve(__dirname, "../src/images/"),
     },
}

 //html-css中使⽤
 .sprite3 {
     background: url("~@assets/s3.png");
 }

4、优化resolve.extensions配置

resolve.extensions在导入语句没写入文件后缀时,webpack会自动带入后缀,并尝试查找文件是否存在

默认配置:extensions:['.js','.json','.jsx','.ts']

所以我们在开发过程中,尽量带入后缀,减少查找文件的时间

5、使用cache缓存

webpack打包的核心是js文件的打包,js使用babel-loader。所以打包时间长主要是babel-loader执行太慢导致的,这时需要使用exclude和include来准确的确定转换内容的范围,并减少重复文件的转换,造成打包后文件体积过大,也会增大编译速度。

使用cacheDirectory配置给babel编译时指定的目录,并且用于缓存加载的结果,但是默认是false,需要手动设置为true,默认的缓存目录是node_modules/.cache/babel-loader ,但是如果在任何根⽬录下都没有找到 node_modules ⽬录,就会降级回退到操作系统默认的临时⽂件⽬录。

rules: [
     {
         test: /\.js$/,
         loader: 'babel-loader',
         options: {
             cacheDirectory: true
         },
     }
];

二、减少打包后的体积

除了构建之外,压缩打包后的体积也比较重要,除了上面提到的cache还可以使用terser-webpack-plugin的时候配置使用多线程和缓存实现。

题外话:在2017年的时候,刚会vue一年,因为项目中必须使用jq,打包后体积太大,成为当时一大难题,弄了一两天才解决,真的是各个方面都要考虑到,解决办法下面会提到

const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
     optimization: {
         minimizer: [
             new TerserPlugin({
                 cache: true, // 开启缓存
                 parallel: true // 多线程
             })
         ]
     }
};

还可以使用cdn地址或者自己服务器的地址存放一些静态资源文件,这样在打包的时候就不需要打包一大堆东西了,可以很大程度的减少打包后的体积,比如:超大的背景图片,jq地址使用cdn,echarts图表类的等,

如果需要在使用的时候可以通过import的方法引入jq(import $ from 'jquery')或echarts并且不会对其打包,可以尝试配置externals

//webpack.config.js
module.exports = {
     externals: {
         //jquery通过script引⼊之后,全局中即有了 jQuery 变量
         'jquery': 'jQuery'
     }
}

CSS的压缩

使用optimize-css-assets-webpack-plugin,是一个压缩css的插件,默认引擎是cssnano,css-loader已经集成了cssnano,可以使用optimize-css-assets-webpack-plugin来自定义规则

//安装命令
npm install cssnano -D
npm i optimize-css-assets-webpack-plugin -D
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
new OptimizeCSSAssetsPlugin({
     cssProcessor: require("cssnano"), // 可以指定引擎,默认是 cssnano
     cssProcessorOptions: {
         discardComments: { removeAll: true }
     }
})

HTML的压缩

//使用html-webpack-plugin
new htmlWebpackPlugin({
     title: "京东商城",
     template: "./index.html",
     filename: "index.html",
     minify: {
         // 压缩HTML⽂件
         removeComments: true, //删掉HTML里的注释
         collapseWhitespace: true, // 删除空⽩符和换⾏符
         minifyCSS: true // 压缩内联css
     }
})

JS的压缩

虽然webpack会自动压缩js,但是还是推荐使用terser-webpack-plugin,也是webpack官方维护的插件。

const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
     optimization: {
         minimizer: [new TerserPlugin(
             parallel: true //使用并开启多线程减少压缩的耗时
         )]
     }
};