webpack提升构建速度

目录

    • 配置优化
      • 减少 `resolve` 的解析
      • 把 loader 应用的文件范围缩小
      • 减少 plugin 的消耗
      • 选择合适的 devtool
    • 使用工具
      • thread-loader
      • DLLPlugin
    • 流程优化
      • 拆分构建步骤
      • 拆分项目代码
    • 版本更新
    • 总结

在这里插入图片描述

前端项目随着时间推移和业务发展,页面可能会越来越多,或者功能和业务代码会越来越多,又或者依赖的外部类库会越来越多,这个时候原本不足为道的 webpack 构建时间消耗就会慢慢地进入我们的视野。

构建消耗的时间变长了,如果是使用 CI 服务来做构建,大部分情况下我们无需等待,其实影响不大。但是本地的 webpack 开发环境服务启动时的速度和我们日常开发工作息息相关,在一些性能不是特别突出的设备上(例如便携式笔记本等等),启动时的长时间等待可能会让你越来越受不了。

博主亲身经历的一个项目,使用 webpack 构建的时长可以达到 6 分钟左右,这种场景下,就算用 CI 服务,在遇见需要紧急发布修复问题时,也会让人很抓狂。

也许某一天你负责的项目也会到了需要优化 webpack 构建性能的时候,所以这一章节我们来聊聊如何提升 webpack 的构建速度。

提升 webpack 构建速度本质上就是想办法让 webpack 少干点活,活少了速度自然快了,尽量避免 webpack 去做一些不必要的事情,记得这个主要方向,后续的针对构建速度的优化都是围绕着这一方向展开。

配置优化

减少 resolve 的解析

在前边第三小节我们详细介绍了 webpack 的 resolve 配置,如果我们可以精简 resolve 配置,让 webpack 在查询模块路径时尽可能快速地定位到需要的模块,不做额外的查询工作,那么 webpack 的构建速度也会快一些,下面举个例子,介绍如何在 resolve 这一块做优化:

resolve: {modules: [path.resolve(__dirname, 'node_modules'), // 使用绝对路径指定 node_modules,不做过多查询],// 删除不必要的后缀自动补全,少了文件后缀的自动匹配,即减少了文件路径查询的工作// 其他文件可以在编码时指定后缀,如 import('./index.scss')extensions: [".js"], // 避免新增默认文件,编码时使用详细的文件路径,代码会更容易解读,也有益于提高构建速度mainFiles: ['index'],
},

上述是可以从配置 resolve 下手提升 webpack 构建速度的配置例子。

我们在编码时,如果是使用我们自己本地的代码模块,尽可能编写完整的路径,避免使用目录名,如:import './lib/slider/index.js',这样的代码既清晰易懂,webpack 也不用去多次查询来确定使用哪个文件,一步到位。

把 loader 应用的文件范围缩小

我们在使用 loader 的时候,尽可能把 loader 应用的文件范围缩小,只在最少数必须的代码模块中去使用必要的 loader,例如 node_modules 目录下的其他依赖类库文件,基本就是直接编译好可用的代码,无须再经过 loader 处理了:

rules: [ {test: /\.jsx?/,include: [ path.resolve(__dirname, 'src'), // 限定只在 src 目录下的 js/jsx 文件需要经 babel-loader 处理// 通常我们需要 loader 处理的文件都是存放在 src 目录],use: 'babel-loader',},// ...
],

如上边这个例子,如果没有配置 include,所有的外部依赖模块都经过 Babel 处理的话,构建速度也是会收很大影响的。

减少 plugin 的消耗

webpack 的 plugin 会在构建的过程中加入其它的工作步骤,如果可以的话,适当地移除掉一些没有必要的 plugin。

区分 mode 会让 webpack 的构建更加有针对性,更加高效。例如当 mode 为 development 时,webpack 会避免使用一些提高应用代码加载性能的配置项,如 UglifyJsPlugin,ExtractTextPlugin 等,这样可以更快地启动开发环境的服务,而当 mode 为 production 时,webpack 会避免使用一些便于 debug 的配置,来提升构建时的速度,例如极其消耗性能的 Source Maps 支持。

选择合适的 devtool

前边的内容我们提过,devtool 可以用于配置 webpack 构建出来的 sourcemap 相关的内容,输出详细的 sourcemap 是相当影响 webpack 的构建速度的,所以这里需要做一个取舍,在构建生产环境代码时不输出 sourcemap,而开发环境时一般选用 eval-cheap-source-map 来确保 sourcemap 基本可用的情况下还有着不错的构建速度。

使用工具

thread-loader

thread-loader 是官方提供的一个可以利用多进程加速 loader 执行的 loader,如果项目中 loader 的运行处理占用比较多的时间,例如 babel 或者 typescript 解析和编译的代码量很大,或者 image—webpack-loader 处理图片耗时比较久,那么可以尝试使用 thread-loader 来提速。下边是基础使用的例子:

const threadLoader = require('thread-loader');const threadLoaderOptions = {// 这里填写对应 thread-loader 的配置// 预热时的配置和使用 thread-loader 时的配置要一致,所以这里统一使用一个变量来管理// 配置参考官方文档:https://github.com/webpack-contrib/thread-loader
}// thread-loader 的预热,可以加速启动
threadLoader.warmup(threadLoader, ['babel-loader',// 更多其他需要使用 thread-loader 的 loader
]);module.exports = {// ...module: {rules: [{test: /\.jsx?/, // 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀use: [// 在你需要的 loader 前加上 thread-loader{loader: 'thread-loader',options: threadLoaderOptions},{loader: 'babel-loader', // 指定使用的 loaderoptions: {presets: ['@babel/preset-env'],},},]},// ...],
}

值得注意的是,由于 thread-loader 新启动进程也需要耗时,所以如果不是运算特别多的 loader 使用 thread-loader 的话可能速度会更慢。

DLLPlugin

DLLPlugin 是 webpack 官方提供的一个插件,也是用来分离代码的,和 optimization.splitChunks有异曲同工之妙,之所以把 DLLPlugin 放到 webpack 构建性能优化这一部分,是因为它的配置相对繁琐,如果项目不涉及性能优化这一块,基本上使用 optimization.splitChunks 即可。

我们来看一下 DLLPlugin 如何使用,使用这个插件时需要额外的一个构建配置,用来打包公共的那一部分代码,举个例子,假设这个额外配置是 webpack.dll.config.js

module.exports = {name: 'vendor',entry: ['react', 'react-dom'], // 这个例子我们打包 react & react-dom 作为公共类库output: {path: path.resolve(__dirname, "dist"),filename: "vendor.js",library: "vendor_[hash]" // 打包后对外暴露的类库名称},plugins: [new webpack.DllPlugin({name: 'vendor_[hash]',path: path.resolve(__dirname, "dist/manifest.json"), // 使用 DLLPlugin 在打包的时候生成一个 manifest 文件})],
}

然后就是我们正常的应用构建配置,在那个的基础上添加两个一个新的 webpack.DllReferencePlugin 配置:

module.exports = {plugins: [new webpack.DllReferencePlugin({manifest: path.resolve(__dirname, 'dist/manifest.json'), // 指定需要用到的 manifest 文件,// webpack 会根据这个 manifest 文件的信息,分析出哪些模块无需打包,直接从另外的文件暴露出来的内容中获取}),],
}

在构建的时候,我们需要优先使用 webpack.dll.config.js 来打包,如 webpack --config webpack.dll.config.js --mode production,构建后生成公共代码模块的文件 vendor.jsmanifest.json,然后再进行应用代码的构建。

你会发现构建结果的应用代码中不包含 react 和 react-dom 的代码内容,这一部分代码内容会放在 vendor.js 这个文件中,而你的应用要正常使用的话,需要在 HTML 文件中按顺序引用这两个代码文件,如:

<script src="vendor.js"></script>
<script src="main.js"></script>

作用是不是和 optimization.splitChunks 很相似,但是有个区别,DLLPlugin 构建出来的内容无需每次都重新构建,后续应用代码部分变更时,你不用再执行配置为 webpack.dll.config.js 这一部分的构建,沿用原本的构建结果即可,所以相比 optimization.splitChunks,使用 DLLPlugin 时,构建速度是会有显著提高的。

但是很显然,DLLPlugin 的配置要麻烦得多,并且需要关心你公共部分代码的变化,当你升级 lodash(即你的公共部分代码的内容变更)时,要重新去执行 webpack.dll.config.js 这一部分的构建,不然沿用的依旧是旧的构建结果,使用上并不如 optimization.splitChunks 来得方便。这是一种取舍,根据项目的实际情况采用合适的做法。

还有一点需要注意的是,html-webpack-plugin 并不会自动处理 DLLPlugin 分离出来的那个公共代码文件,我们需要自己处理这一部分的内容,可以考虑使用 add-asset-html-webpack-plugin,关于这一个的使用就不讲解了,详细参考官方的说明文档:使用 add-asset-html-webpack-plugin。

流程优化

拆分构建步骤

这里拿图片的压缩作为一个例子讲解,我们在前边的小节提到图片可以使用 webpack 的 image-webpack-loader 来压缩图片,在对 webpack 构建性能要求不高的时候,这样是一种很简便的处理方式,但是要考虑提高 webpack 构建速度时,这一块的处理就得重新考虑一下了,思考一下是否有必要在 webpack 每次构建时都处理一次图片压缩。

我们可以直接使用 imagemin 来做图片压缩,编写简单的命令即可。然后使用 pre-commit 这个类库来配置对应的命令,使其在 git commit 的时候触发,并且将要提交的文件替换为压缩后的文件。

这样提交到代码仓库的图片就已经是压缩好的了,以后在项目中再次使用到的这些图片就无需再进行压缩处理了,image-webpack-loader 也就没有必要了。

使用同样的思路去考虑其他构建步骤,是否有必要在每次构建时处理,可以考虑用 git hooks 或者工作流的一些机制来触发一些构建工作,来减少 webpack 的构建压力。

拆分项目代码

webpack 的构建性能优化是比较琐碎的工作,当我们需要去考虑 webpack 的构建性能问题时,往往面对的是项目过大,涉及的代码模块过多的情况。在这种场景下你单独做某一个点的优化其实很难看出效果,你可能需要从我们上述提到的多个方面入手,逐一处理,验证,有些时候你甚至会觉得吃力不讨好,投入产出比太低了,这个时候我们可以考虑换一个角度来思考我们遇到的问题。

例如,拆分项目的代码,根据一定的粒度,把不同的业务代码拆分到不同的代码库去维护和管理,这样子单一业务下的代码变更就无须整个项目跟着去做构建,这样也是解决因项目过大导致的构建速度慢的一种思路,并且如果处理妥当,从工程角度上可能会给你带来其他的一些好处,例如发布异常时的局部代码回滚相对方便等等。

版本更新

官方发布的 webpack 4.0 更新日志来看,webpack 4.0 版本做了很多关于提升构建性能的工作,我觉得比较重要的改进有这么几个:

  • AST 可以直接从 loader 直接传递给 webpack,避免额外的解析,对这一个优化细节有兴趣的可以查看这个 PR。
  • 使用速度更快的 md4 作为默认的 hash 方法,对于大型项目来说,文件一多,需要 hash 处理的内容就多,webpack 的 hash 处理优化对整体的构建速度提升应该还是有一定的效果的。
  • Node 语言层面的优化,如用 for of 替换 forEach,用 MapSet 替换普通的对象字面量等等,这一部分就不展开讲了,有兴趣的同学可以去 webpack 的 PRs 寻找更多的内容。
  • 后续更新的版本把 uglifyjs-webpack-plugin 换成了 terser-webpack-plugin,可以更好地针对 ES6 的代码进行处理。

更多关于性能优化的 webpack 迭代可以查看官方的 release 文档:webpack release,搜索 performance 关键字就好。

webpack 5 的大版本,针对性能优化还有更棒的持久化缓存方案推出,让每一次的构建打包可以向我们的 webpack-dev-server 一样,只针对变化部分做增量构建,可以极大地提高构建性能,这个值得期待一下,有兴趣的同学可以使用 webpack 5 beta 版本来测试一下。

总结

本文我们首先介绍了如何从多个配置优化的方式来提高 webpack 的构建速度:

  • 减少 resolve 的解析
  • 把 loader 应用的文件范围缩小
  • 减少 plugin 的消耗
  • 选择合适的 devtool

在必要的时候,我们可以使用 thread-loader 和 DLLPlugin 来帮助我们进一步优化 webpack 的构建性能,但是从另外的角度考虑,在不过分依赖 webpack 构建的情况下,我们可以从流程优化上着手,如提交代码前就压缩图片,拆分构建的代码库等,以此来减少 webpack 构建的工作量。

同时,更新 Node 版本和 webpack 版本都有助于让我们的构建变得更快,勤劳的程序员们一直在优化代码库的性能,别辜负了他们的努力,尽可能让构建跑在最新的运行环境上吧。

你工作中遇到的项目是否有哪些部分是可以考虑使用上述的优化方法来提升构建速度的?你是否有其他的一些构建优化的方法呢?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/140582.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是安全平行切面

安全平行切面的定义 通过嵌入在端—管—云内部的各层次切点&#xff0c;使得安全管控与业务逻辑解耦&#xff0c;并通过标准化的接口为安全业务提供内视和干预能力的安全基础设施。安全平行切面是一种创新的安全体系思想&#xff0c;是实现“原生安全”的一条可行路径。 为什…

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测

分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测 目录 分类预测 | Matlab实现PSO-LSTM粒子群算法优化长短期记忆神经网络的数据多输入分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现PSO-LSTM粒子群算法优化长短…

下载并安装DevEco Studio 3.1,初尝鸿蒙编程

摘自华为官网 DevEco Studio 3.1配套支持HarmonyOS 3.1版本及以上的应用及服务开发&#xff0c;提供了代码智能编辑、低代码开发、双向预览等功能&#xff0c;以及轻量构建工具DevEco Hvigor 、本地模拟器&#xff0c;持续提升应用及服务开发效率。 下载 官网下载地址 HUAWEI…

用python将csv表格数据做成热力图

python的开发者为处理表格和画图提供了库的支持&#xff0c;使用pandas库可以轻松完成对csv文件的读写操作&#xff0c;使用matplotlib库提供了画热力图的各种方法。实现这个功能首先需要读出csv数&#xff0c;然后设置自定义色条的各种属性如颜色&#xff0c;位置&#xff0c;…

19、Flink 的Table API 和 SQL 中的自定义函数及示例(3)

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

CoRL 2023 获奖论文公布,manipulation、强化学习等主题成热门

今年大模型及具身智能领域有了非常多的突破性进展&#xff0c;作为机器人学与机器学习交叉领域的全球顶级学术会议之一&#xff0c;CoRL也得到了更多的关注。 CoRL 是面向机器人学习的顶会&#xff0c;涵盖机器人学、机器学习和控制等多个主题&#xff0c;包括理论与应用。今年…

初探地理编码(2023.11.12)

地理编码相识 2023.11.12 引言1、地理编码简介2、地理编码API和服务&#xff08;解决方案供应商 / 厂商&#xff09;2.1 高德2.2 百度2.3 超图2.4 天地图2.5 ArcGIS2.6 MapBox2.7 Cesium2.8 MapLocation 3、python实例3.1 pip安装依赖库&#xff08;python 3.6&#xff09;3.2 …

MVVM框架:图片加载有问题

一、前言&#xff1a;在我使用ImageView加载图片的时候添加如下代码发现报错 app:imageUrl"{viewModel.observableField.assetImg}"报错如下错误 二、原因&#xff1a;是啥我不太清楚好像是没有imageView的适配器&#xff0c;后来我看了一下确实没有 public class I…

AD9371 Crossbar 和 I、Q数据 映射JESD204B传输层

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

linux 安装 mini conda,linux下安装 Miniconda

下载地址 https://docs.conda.io/projects/miniconda/en/latest/index.html 安装conda mkdir -p ~/miniconda3 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh bash ~/miniconda3/miniconda.sh -b -u -p ~/mini…

微信开发者工具如何使用

首先是下载微信开发者工具 链接: https://pan.baidu.com/s/1ri-fRCUQsz9vLxbTqtdPUQ 提取码: 8rhn 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 安装完打开就是以下界面 接下来进入正题 第一步新建或导入 新建 获取AppID 第一步&#xff1a;通过微信公众平…

第12章 PyTorch图像分割代码框架-3:推理与部署

推理模块 模型训练完成后&#xff0c;需要单独再写一个推理模块来供用户测试或者使用&#xff0c;该模块可以命名为test.py或者inference.py&#xff0c;导入训练好的模型文件和待测试的图像&#xff0c;输出该图像的分割结果。inference.py主体部分如代码11-7所示。 代码11-7 …

vue做的一个一点就转的转盘(音乐磁盘),点击停止时会在几秒内缓慢停止,再次点击按钮可以再次旋转,

先看效果&#xff1a; 代码&#xff1a;主要部分我会红线画出来 css:部分&#xff1a; 源码&#xff1a; vue部分&#xff1a; <template><div class"song-lyric"><div><div class"type"><div class"right">&l…

如何用自然语言 5 分钟构建个人知识库应用?我的 GPTs builder 尝试

开发者的想象力闸门一旦打开&#xff0c;迎接我们的必然是目不暇接的 AI 应用浪潮冲击。 兴奋 早晨&#xff0c;我突然发现 ChatGPT 最新的 Create GPTs 功能可以用了。 这太让我意外了&#xff0c;没想到这么快。根据页面上的提示&#xff0c;我一直以为还得等上一周左右。于是…

3C制造RFID产线智能化升级改造设计方案

3C行业需求 近年来&#xff0c;随着政策的支持、相关技术的进步以及市场需求的推动&#xff0c;3C行业迅速发展&#xff0c;我国的3C市场已经进入了稳定发展阶段&#xff0c;作为仅次于汽车产业的大市场&#xff0c;3C产业在智能制造的推动下&#xff0c;越来越多的物联网技术…

软考网络工程师知识点总结(四)

目录 61、FTP文件传输服务 62、DHCP动态主机配置协议 63、电子邮件服务 64、各种新技术相关概念及功能的考查 65、Windows的ipconfig命令 66、Windows的其它命令及说明 67、Linux系统关机和重启命令 68、Linux系统文件属性命令 69、SNMP协议版本 70、SNMP协议的报文类…

【OpenCV(3)】linux arm aarch 是 opencv 交叉编译与使用

文章目录 1、直接找github 别人编译好的2、自主编译参考 3使用CMake检查 参考 1、直接找github 别人编译好的 测试很多&#xff0c;找到一个可用的。 https://github.com/dog-qiuqiu/libopencv 它用了超级模块&#xff01; OpenCV的world模块也称为超级模块&#xff08;supe…

Zeitgeist ZTG Token以及其预测市场加入Moonbeam生态

波卡上的首选多链开发平台Moonbeam宣布与Zeitgeist达成XCM集成&#xff0c;将ZTG Token引入Moonbeam。此集成将使波卡内的Moonbeam和Zeitgeist网络之间的流动性得以流动&#xff0c;并通过Moonbeam的互连合约实现远程链集成。 Zeitgeist是一个基于波卡的Substrate区块链框架构…

5个最佳开源RPA框架

在最近两年中&#xff0c;RPA加上AI&#xff0c;即智能自动化流程&#xff0c;已经成为频繁讨论的话题&#xff0c;特别是在企业和机构的数字化转型过程中。自动化与智能化成为了提高效率的关键手段&#xff0c;而RPA便是迈向这一未来的起始步骤。 可以将RPA视为人体的躯干神经…

[MySQL] MySQL库的基础操作

文章目录 一、数据库的创建 1、1 库的创建 1、2 字符集与校验规则 1、2、1 查看字符集与校验规则 1、2、2 字符集与校验规则的设置 1、2、3 校验规则对数据库的影响 二、数据库的操作 2、1 查看数据库 2、2 删除数据库 2、3 修该数据库 2、4 数据库删除和备份 2、5 显示创建语…