浅析如何优化Webpack构建速度:使用可量化工具、配置include、配置缓存、配置多进程多实例thread-loader/parallel、硬件加速、noParse、IgnorePlugin、抽取公共代码、DllPlugin分包、开启webpack内置优化、babel配置优化、可视化分析针对性优化

一、量化

  有时,我们以为的优化是负优化,这时如果有一个量化的指标可以看出前后对比,那将会是再好不过的一件事。

  speed-measure-webpack-plugin 插件可以测量各个插件和loader所花费的时间,使用之后,构建时,会得到类似下面这样的信息:

  对比前后的信息,来确定优化的效果。speed-measure-webpack-plugin 的使用很简单,可以直接用其来包裹 Webpack 的配置

//webpack.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
const config = {
    //...webpack配置
}
module.exports = smp.wrap(config);

二、exclude/include 确定loader规则范围

  我们可以通过 excludeinclude 配置来确保转译尽可能少的文件。顾名思义,exclude 指定要排除的文件,include 指定要包含的文件。exclude 的优先级高于 include,在 includeexclude 中使用绝对路径数组,尽量避免 exclude,更倾向于使用 include

//webpack.config.js
const path = require('path');
module.exports = {
    //...
    module: {
        rules: [
            {
                test: /\.js[x]?$/,
                use: ['babel-loader'],
                include: [path.resolve(__dirname, 'src')]
            }
        ]
    },
}

三、cache-loader

  在一些性能开销较大的 loader 之前添加 cache-loader,将结果缓存中磁盘中。默认保存在 node_modueles/.cache/cache-loader 目录下。

  首先安装依赖:npm install cache-loader -D

  cache-loader 的配置很简单,放在其他 loader 之前即可。修改Webpack 的配置如下:

module.exports = {
    module: {
        //babel-loader耗时比较长,给它配置了cache-loader
        rules: [
            {
                test: /\.jsx?$/,
                use: ['cache-loader','babel-loader']
            }
        ]
    }
}

  如果你跟我一样,只打算给 babel-loader 配置 cache 的话,也可以不使用 cache-loader,给 babel-loader 增加选项 cacheDirectory

  cacheDirectory:默认值为 false。当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 Webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程。设置空值或者 true 的话,使用默认缓存目录:node_modules/.cache/babel-loader。开启 babel-loader的缓存和配置 cache-loader,我比对了下,构建时间很接近。

四、多进程多实例构建:thread-loader

五、开启 JS 多进程压缩:配置 parallel true

  当前 Webpack 默认使用的是 TerserWebpackPlugin,默认就开启了多进程和缓存,构建时,你的项目中可以看到 terser 的缓存文件 node_modules/.cache/terser-webpack-plugin

六、HardSourceWebpackPlugin 硬件加速

  HardSourceWebpackPlugin 为模块提供中间缓存,缓存默认的存放路径是: node_modules/.cache/hard-source

  配置 hard-source-webpack-plugin,首次构建时间没有太大变化,但是第二次开始,构建时间大约可以节约 80%。

七、noParse

  如果一些第三方模块没有AMD/CommonJS规范版本,可以使用 noParse 来标识这个模块,这样 Webpack 会引入这些模块,但是不进行转化和解析,从而提升 Webpack 的构建性能 ,例如:jquerylodash

  noParse 属性的值是一个正则表达式或者是一个 function

//webpack.config.js
module.exports = {
    //...
    module: {
        noParse: /jquery|lodash/
    }
}

八、IgnorePlugin

  webpack 的内置插件,作用是忽略第三方包指定目录。例如 moment (2.24.0版本) 会将所有本地化内容和核心功能一起打包,我们就可以使用 IgnorePlugin 在打包时忽略本地化内容。

//webpack.config.js
module.exports = {
    //...
    plugins: [
        //忽略 moment 下的 ./locale 目录
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ]
}

  在使用时,如果我们需要指定语言,那么需要我们手动的去引入语言包,例如,引入中文语言包

import moment from 'moment';
import 'moment/locale/zh-cn';// 手动引入

  index.js 中只引入 moment,打包出来的 bundle.js 大小为 263KB,如果配置了 IgnorePlugin,单独引入 moment/locale/zh-cn,构建出来的包大小为 55KB

九、DllPlugin

  有些时候,如果所有的JS文件都打成一个JS文件,会导致最终生成的JS文件很大,这个时候,我们就要考虑拆分 bundles

  DllPluginDLLReferencePlugin 可以实现拆分 bundles,并且可以大大提升构建速度,DllPluginDLLReferencePlugin 都是 webpack 的内置模块。

  我们使用 DllPlugin 将不会频繁更新的库进行编译,当这些依赖的版本没有变化时,就不需要重新编译。

十、抽离公共代码

十一、借助 webpack-bundle-analyzer 进一步优化

十二、webpack自身的优化

1、tree-shaking:如果使用ES6的import语法,那么在生产环境下,会自动移除没有使用到的代码

2、scope hosting 作用域提升:变量提升,可以减少一些变量声明。在生产环境下,默认开启

十三、babel 配置的优化

  在不配置 @babel/plugin-transform-runtime 时,babel 会使用很小的辅助函数来实现类似 _createClass 等公共方法。默认情况下,它将被注入(inject)到需要它的每个文件中。但是这样的结果就是导致构建出来的JS体积变大。

  我们也并不需要在每个 js 中注入辅助函数,因此我们可以使用 @babel/plugin-transform-runtime@babel/plugin-transform-runtime 是一个可以重复使用 Babel 注入的帮助程序,以节省代码大小的插件。

  因此我们可以在 .babelrc 中增加 @babel/plugin-transform-runtime 的配置。

{
    "presets": [],
    "plugins": [
        [
            "@babel/plugin-transform-runtime"
        ]
    ]
}
posted @ 2020-05-10 22:29  古兰精  阅读(1193)  评论(0编辑  收藏  举报