前言
看标题,可能会有人疑惑,RequireJS解决的是前端模块化,webpack是打包工具,这两种怎么能放在一起谈论比较? 的确,RequireJS常出现在amd/cmd/esm等模块化话题下,而与webpack比较的,常常是gulp/rollup/esbuil等构建工具。但如果将视角调整到它们诞生前后,可以看到两者的一些微妙关联。
构建需求的出现和发展
构建最初解决的是什么问题呢? 是前端的预编译问题:es6到es5,less到saas,自动雪碧图等等。
此时很多新的问题出现了,比如图片可以合并为雪碧图,那么js或css是否可以合并呢?当然是可以的,这是个合理且先进的需求。
为了维护性和复用性,前端的功能封装越来越细,js的合并拆分/按需加载成为了一个强需求。
js合并的难点
js合并,从文件处理的角度并不难。
但哪些模块需要合并,合并后的js中,这些模块的先后关系是什么,如何处理业务文件对组件文件的按需关系,RequireJS时代,并没有工具能解决这些问题。
当时流行的gulp本身就是基于流处理文件,至于流的定义和顺序,完全由开发者控制。模块的依赖加载顺序,模块合并通常也需要自行在模块文件中判断。模块合并后,运行时代码的依赖顺序自然也需要调整,这是一个额外的工作量和心智负担。因此模块之间的关系,在开发时就需要确定好最合理的顺序,不仅要考虑该模块的依赖关系,还需要考虑构建后整体项目的依赖先后加载关系,这会给开发带来极大的心智负担。
Webpack的出现正式解决了这个问题,它从入口文件开始,生成一个依赖图,以此解决模块的合并、拆分问题。因此构建只是它的表象,它实质上是一个模块加载器,所有的构建都是为了它的模块加载服务的。
也因此,前端项目进入了一个新的时代。最直观的现象就是,前端项目中的依赖飞速扩大,以前一个项目有20个外部依赖就很多了,而现在,直接或间接依赖的npm模块动辄成千上万。
而requireJS和webpack,分别就是这新旧两个前端时代的最典型代表。
结论
可能有人认为,是esm战胜了amd,才导致了requireJS的没落。
但在我看来,esm战胜amd既是webpack流行的因,也是它的果。如果没有webpack,gulp也会有插件将esm转为amd然后交给requireJS加载,只是可能仍然需要考虑运行时和编译后的依赖关系。而webpack融合了构建与模块加载,确实是一个划时代的创举。
这篇文章在草稿箱里躺了几年,虽然这个话题早已经过时,但是这个看问题的视角,我觉得还是有些分享价值的。