from Require.js to Webpack(why)

时间:2022-10-03 20:19:51

写在前面:

本文主要参考 From Require.js to Webpack - Part 1 (the reasons),原文作者将项目从 require.js 转移到了 webpack 并详细说明了原因以及好处。

  • commonjs (webpack 默认 commonjs,很显然,commonjs 同步书写 js 的方式比 AMD 舒服很多)
  • 客户端单元测试(node 具有丰富的测试框架,webpack 使得客户端测试也可以使用这些框架)
  • 模块复用(node 和客户端的模块复用)
  • NPM(天然支持 NPM,因为 NPM 本身发布的就是 commonjs 模块)
  • 更简单的 ES6 支持以及更多的插件支持(比如 webpack 自带的 uglify 等等)

诚然,作者只是从模块组织方式去对比,并没有牵扯到构建工具这块。而如果说到构建工具,webpack 可能还有更多其他的优势,比如热重载,打包时间大大缩短,css 打包,等等,这些应该和 gulp 等去比较。

尽管 webpack 本身也支持 AMD,但是总觉得 webpack+AMD 有点 Vue/React+JQ 的既视感,而且也不能很好地结合 NPM 使用,所以个人觉得如果要迁移,还是要迁移地彻底一点,毕竟 AMD 的支持只会越来越少。

Webpack has been a huge help to our client-side code base and developer experience in general. It's allowed greater parity and reuse between our client-side and node code, it's made testing our code much easier and it's allowed us to cut way down on the config and extra support code needed to maintain two different module systems in the same code base. The most important thing it has provided though is access to the NPM ecosystem in the browser. Coding will never be the same again :)

CommonJS

Node 用习惯后,我们便会爱上它的 commonjs 的组织方式。使用 webpack 后,我们便可以使用所有的 node 模块,这简直太酷了!很显然,越来越多的模块会支持 commonjs 但是却并没有兼容 AMD。

在这点上 require.js 和 webpack 的区别是(也是 AMD 和 commonjs 的区别):

  1. 前者使用 return,后者使用 module.export
  2. webpack 用 . 代表相对路径, 作用和 path.resolve() 类似
  3. webpack 可以方便搭配 NPM 使用

客户端单元测试

让 mocha 支持 require.js 非常费力,但是如果使用 webpack 就不一样了。只要代码没有基于 DOM,就可以被当作普通的 node 模块一样进行单元测试。

复用和模块化

复用和模块化,AMD 也有啊?有什么不同呢?

  1. node 本身就是 commonjs 方式进行代码组织,这就意味着我们可以把写 node 时的一些最佳实践,设计模式等无缝迁移到客户端代码的书写中。
  2. 我们可以把服务端的一些 commonjs 模块直接用到 客户端,而不是需要改造成 AMD(比如 date/time formatting 以及一些工具模块)

NPM

尽管 commonjs 语法本身比 AMD 优雅,并且还有以上的各种好处,但是迁移到 webpack 最大的好处是对于 NPM 的支持。尽管 require.js 本质上也能够搭配 NPM 使用,但是非常麻烦。

NPM 搭配 require.js:

  1. 需要暴露 node_modules 文件夹路径(commonjs 会自动去寻找 node_modules,但是 AMD 不会)
  2. 需要在配置文件 config.js 中为模块添加 alias(因为 npm install 的模块内部是 commonjs 的组织方式,如果直接 require 并不能找到,需要设置 alias)
  3. 确定你 install 的模块本身没有依赖(因为依赖本身并不会生效)
  4. define('your-module', function(yourModule) { });

而 NPM 搭配 webpack 只需要:

  1. require() the module.

成熟的 ES6 以及插件支持

webpack 对于 ES6 的支持(babel-loader)以及一些内置的插件支持(uglify)比 require.js 强大。

作者在原文举了个简单的例子,他想在 require.js 中使用 ES6 Class,但是需要两步,首先需要 babel 将 ES6 转为 ES5,然后再使用 es6 require.js plugin,但是用 babel-loader 就方便多了。