为了理解为什么要使用 webpack,让我们回顾一下在捆绑器出现之前如何在 Web 上使用 JavaScript。
在浏览器中运行 JavaScript 有两种方法。首先,为每个功能包含一个脚本;这种解决方案难以扩展,因为加载太多脚本会导致网络瓶颈。第二种选择是使用包含所有项目代码的大型 .js
文件,但这会导致作用域、大小、可读性和可维护性问题。
IIFE 解决了大型项目的范围问题;当脚本文件被 IIFE 包裹时,可以安全地连接或组合文件,而无需担心范围冲突。
IIFE 的使用导致了 Make、Gulp、Grunt、Broccoli 或 Brunch 等工具的出现。这些工具被称为任务运行器,它们将所有项目文件连接在一起。
但是,更改一个文件意味着必须重新构建整个文件。连接使跨文件重用脚本变得更容易,但使构建优化更加困难。如何才能知道代码是否真的被使用?
即使只使用 lodash 中的单个函数,也必须添加整个库,然后将其压缩在一起。如何对代码的依赖项进行树摇?延迟加载代码块在规模上很难实现,并且需要开发人员进行大量手动操作。
Webpack 运行在 Node.js 上,Node.js 是一个 JavaScript 运行时,可以在浏览器环境之外的计算机和服务器上使用。
Node.js 发布后,一个新时代开始了,它带来了新的挑战。现在 JavaScript 不再在浏览器中运行,Node 应用程序如何加载新的代码块?没有可以添加到其中的 html 文件和脚本标签。
CommonJS 出现了,它引入了 require
,允许你在当前文件中加载和使用模块。这通过按需导入每个模块来立即解决范围问题。
JavaScript 正在以一种语言、一个平台以及一种快速开发和创建快速应用程序的方式接管世界。
但是,浏览器不支持 CommonJS。没有 实时绑定。循环引用存在问题。同步模块解析和加载速度很慢。虽然 CommonJS 是 Node.js 项目的绝佳解决方案,但浏览器不支持模块,因此创建了像 Browserify、RequireJS 和 SystemJS 这样的捆绑器和工具,使我们能够编写在浏览器中运行的 CommonJS 模块。
对于 Web 项目来说,好消息是模块正在成为 ECMAScript 标准中的正式功能。但是,浏览器支持不完整,捆绑仍然比这些早期模块实现更快,并且目前建议使用。
老式的任务运行器,甚至 Google Closure Compiler 都要求您预先手动声明所有依赖项。而像 webpack 这样的捆绑器会根据导入和导出内容自动构建和推断您的 依赖关系图。这与其他 插件 和 加载器 一起,为开发人员提供了很棒的体验。
...拥有一个不仅可以让我们编写模块,而且可以支持任何模块格式(至少在我们使用 ESM 之前),并同时处理资源和资产的东西?
这就是 webpack 存在的原因。它是一个工具,可以让你捆绑你的 JavaScript 应用程序(支持 ESM 和 CommonJS),并且可以扩展以支持许多不同的资产,例如图像、字体和样式表。
Webpack 关心性能和加载时间;它一直在改进或添加新功能,例如异步块加载和预取,以为您和您的用户提供最佳的项目体验。