webpack构建性能优化

减少模块解析

什么叫做模块解析

在这里插入图片描述

模块解析包括:抽象语法树分析、依赖分析、模块语法替换

不做模块解析会怎样

在这里插入图片描述

如果某个模块不做解析,该模块经过 loader 处理后的代码就是最终代码。

如果没有 loader 对该模块进行处理,该模块的源码就是最终打包结果的代码。

如果不对某个模块进行解析,可以缩短构建时间。

哪些模块不需要解析

模块中无其他依赖:一些已经打包好的第三方库,比如 jquery。

如何让某个模块不要解析

配置 module.noParse,它是一个正则,被正则匹配到的模块不会解析。

优化 loader 性能

进一步限制 loader 的应用范围

对于某些库,不使用 loader,例如:babel-loader 可以转换 ES6 或更高版本的语法,可是有些库本身就是用 ES5 语法书写的,不需要转换,使用 babel-loader 反而会浪费构建时间。

lodash 就是这样的一个库,lodash 是在 ES5 之前出现的库,使用的是 ES3 语法。

通过 module.rule.excludemodule.rule.include,排除或仅包含需要应用 loader 的场景

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /lodash/,
                use: "babel-loader"
            }
        ]
    }
}

如果暴力一点,甚至可以排除掉 node_modules 目录中的模块,或仅转换 src 目录的模块

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                //或
                // include: /src/,
                use: "babel-loader"
            }
        ]
    }
}

这种做法是对 loader 的范围进行进一步的限制,和 noParse 不冲突,想想看,为什么不冲突

缓存 loader 的结果

我们可以基于一种假设:如果某个文件内容不变,经过相同的 loader 解析后,解析后的结果也不变,于是,可以将 loader 的解析结果保存下来,让后续的解析直接使用保存的结果。

cache-loader 可以实现这样的功能。

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                use: ['cache-loader', ...loaders]
            },
        ],
    },
};

有趣的是,cache-loader 放到最前面,却能够决定后续的 loader 是否运行,实际上,loader 的运行过程中,还包含一个过程,即 pitch

在这里插入图片描述

cache-loader 还可以实现各自自定义的配置,具体方式见文档。

在 webpack5 中自带缓存功能。

为 loader 的运行开启多线程

thread-loader会开启一个线程池,线程池中包含适量的线程,它会把后续的loader放到线程池的线程中运行,以提高构建效率,由于后续的 loader 会放到新的线程中,所以,后续的 loader 不能:

  • 使用 webpack api 生成文件
  • 无法使用自定义的 plugin api
  • 无法访问 webpack options

在实际的开发中,可以进行测试,来决定thread-loader放到什么位置

特别注意,开启和管理线程需要消耗时间,在小型项目中使用thread-loader反而会增加构建时间。

热替换 HMR

热替换并不能降低构建时间(可能还会稍微增加),但可以降低代码改动到效果呈现的时间

当使用 webpack-dev-server 时,考虑代码改动到效果呈现的过程。

在这里插入图片描述

而使用了热替换后,流程发生了变化。

在这里插入图片描述

启用 HMR

此功能可以很大程度提高生产效率。我们要做的就是更新 webpack-dev-server 配置, 然后使用 webpack 内置的 HMR 插件。

webpack-dev-server v4.0.0 开始,模块热替换是默认开启的。

webpack.config.js

const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")

module.exports = {
    context: path.resolve(__dirname, "src"),
    entry: {
        index: "./index",
    },
    devtool: "source-map",
    devServer: {
        hot: true,
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "index.html",
            title: "webpack",
        }),
    ],
}

默认情况下,webpack-dev-server 不管是否开启了热更新,更改代码,重新打包后,都会调用 location.reload 刷新页面。

index.js

if (module.hot) {
    module.hot.accept() // 接受热更新
}

当开启了热更新后,webpack-dev-server 会向打包结果中注入 module.hot 属性,如果运行了 module.hot.accept(),将改变自动刷新页面的行为。更多关于 HMR API 的信息,请查看文档

module.hot.accept() 的作用是让 webpack-dev-server 通过 socket 管道,把服务器更新的内容发送到浏览器

在这里插入图片描述

然后,将结果交给插件 HotModuleReplacementPlugin 注入的代码执行,插件 HotModuleReplacementPlugin 会根据覆盖原始代码,然后让代码重新执行。

所以,热替换发生在代码运行期

样式热替换

对于样式也是可以使用热替换的,但需要使用 style-loader ,因为热替换发生时,HotModuleReplacementPlugin 只会简单的重新运行模块代码,因此 style-loader 的代码一运行,就会重新设置 style 元素中的样式。

mini-css-extract-plugin ,由于它生成文件是在构建期间,运行期间并会也无法改动文件,因此它对于热替换是无效的。
热替换发生时,HotModuleReplacementPlugin 只会简单的重新运行模块代码,因此 style-loader 的代码一运行,就会重新设置 style 元素中的样式。

mini-css-extract-plugin ,由于它生成文件是在构建期间,运行期间并会也无法改动文件,因此它对于热替换是无效的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值