🗒️相关背景

来自官网 https://webpack.js.org/concepts/why-webpack/

在 bundlers 出现之前,在 web 中使用 JavaScript 有两种方法:

  1. 为每个功能都 include 一个 scirpt

    • 问题:很难扩展,因为加载太多脚本会导致网络瓶颈

  2. 使用一个 big .js 文件,它包含了所有的项目代码

    • 问题:这会导致作用域、文件大小、可读性和可维护性方面的问题

1. IIFE

IIFE, Immediately invoked function expression, 立即调用的函数表达式。

IIFE 解决了 large 项目的作用域问题。IIFE 的使用催生了 Make, Gulp, Grunt, Broccoli 和 Brunch 等工具,这些工具称为任务执行器(task runner),它们将所有项目文件拼接(concatenate)在一起。

但是,修改一个文件就意味着必须 rebuild 整个文件。拼接让跨文件复用脚本变得更容易,但是让 build 优化变得更加困难。

  • 如何判断代码是否真的被使用了?

  • 如何 treeshake 代码依赖?即使只用到了 lodash 中的一个函数,我们也必须添加整个库,然后将它们压缩在一起。

  • 难以大规模地实现延迟加载 chunks,这需要进行大量的手动工作

2. Node.js 和 JS 模块

webpack 运行在 Node.js 中。JavaScript module 的诞生归功于 Node.js。

当 Node.js 发布时,一个新时代开始了,它带来了新的挑战。既然 JavaScript 不是运行在浏览器中了,那么 Node 程序要如何加载新的代码 chunks 呢?因为没有可以添加到其中的 html 文件和 script 标签了。

CommonJS 的问世引入了 require,它允许在当前文件中 load 和 use 一个模块。import 每个 module 解决了作用域的问题。

3. npm + Node.js + modules,大规模分发

JavaScript 既是一种语言,又是一个平台,还可以快速开发应用程序。但浏览器不支持 CommonJS,也不支持 live binding(实时绑定),还存在循环引用的问题,此外同步模块的解析和加载速度也很慢。

尽管 CommonJS 是 Node.js 项目的一个很好的解决方案,但浏览器不支持 modules,因而产生了 Browserify, RequireJS 和 SystemJS 等 bundlers(打包工具)和 tools,以让我们编写能在浏览器中运行的 CommonJS 模块。

4. ES 模块

对 web 项目而言,好消息是 module 正在成为 ECMAScript 标准的官方功能。然而,浏览器支持不完整,所以 bundle 依然是当前的推荐方式。

5. 自动的依赖收集

老派的 Task Runners 甚至 Google Closure Compiler 都要求我们在顶部手动声明所有的依赖。而像 webpack 这样的 bundlers(打包器)会根据 import 和 export 的内容自动 build(构建)和 infer(推断)依赖关系图,再加上 plugins 和 loader 会让开发者有更好的体验。

6. 写在最后

是否可以有一种方式,不仅能让我们编写 modules,还支持各种 module 格式(至少在 ESM 可用之前),还能同时处理 resources 和 assets?

这就是 webpack 存在的原因。它是一个可以 bundle(打包)JavaScript 应用程序(同时支持 ESM 和 CommonJS)的工具,还可以进行扩展以支持许多不同的 assets,比如 mages, fonts, stylesheets。

webpack 关心性能和加载时间,它一直在改进或添加新功能,例如异步 chunk(块)loading 和 prefetching,以提供最好的体验。

Last updated