您的当前位置:首页前端模块化的发展史

前端模块化的发展史

2020-11-27 来源:哗拓教育

原文参考 玉伯 大神些的,我整理了一下。

咱们今天主题说下前端模块化发展的历史,主要就是针对AMD CMD 的发展,这两个东西是一种规范,他们实际产物是 AMD是RequireJS,CMD的产物是seajs,他们的出现都是在COMMONjs基础上发展而来的,那咱们得先说说COMMONjs。

COMMONJS

大概 09 年 – 10 年期间,CommonJS 社区大牛云集。CommonJS 原来叫 ServerJS,推出 Modules/1.0 规范后,在Node.js 环境下取得了很不错的实践。09年下半年这帮牛逼爱折腾的大神们想把 ServerJS 的成功经验进一步推广到浏览器端,于是将社区改名叫 CommonJS,同时激烈争论 Modules 的下一版规范。分歧和冲突由此诞生,逐步形成了三大流派:Modules/1.x (完全基于1.0的功能,只是增加一个转换功能),Modules/Async ,Modules/2.0 。

Modules/1.x 流派:这个观点觉得 1.x 规范已经够用,只要移植到浏览器端就好。要做的是新增 Modules/Transport 规范,即在浏览器上运行前,先通过转换工具将模块转换为符合 Transport 规范的代码。现在值得关注的有两个实现:component 和es6 module。

Modules/Async 流派:这个观点觉得浏览器有自身的特征,不应该直接用 Modules/1.x 规范。这个观点下的典型代表是 AMD 规范及其实现 RequireJS。这个稍后再细说。

Modules/2.0 流派:这个观点觉得浏览器有自身的特征,不应该直接用 Modules/1.x 规范,但应该尽可能与 Modules/1.x 规范保持一致。这个观点下的典型代表是 BravoJS 和 FlyScript 的作者。BravoJS 作者对 CommonJS 的社区的贡献很大。FlyScript 的作者提出了 Modules/Wrappings 规范,这规范是 CMD 规范的前身。可惜的是 BravoJS 太学院派,FlyScript 后来做了自我阉割,将整个网站(flyscript.org)下线了。这个故事有点悲壮,就不细讲了。

上面是产生的三大流派,也就是说Modules/2.0开始的产物都无疾而终了 ,而当时Modules/1.x 规范的 ES6还不成熟,在后来就是以Modules/Async 为规范的 RequireJS 发展的很火热。

但是AMD 的RequireJS 的 执行时机有异议,模块书写风格有争议,一直没有被CommonJS社区认同,咱们详细的说下这两个点:

AMD 里提前下载 a.js 是浏览器的限制,没办法做到同步下载,这个社区都认可,但执行,AMD 里是 提前执行,二在基础Modules/1.0 规范里是第一次 require的时候才执行。这个差异很多人不能接受,包括持有Modules/2.0 观点的人也不能接受AMD的这个观点,这个差异,也导致实质上 Node 的模块与 AMD 模块是无法共享的,存在潜在冲突;

另外一个就是:模块书写风格有争议

AMD 风格下,通过参数传入依赖模块,破坏了 就近声明 原则,就近原则就是在用的时候才会用,而不需要提前声明模块。最后,AMD 从 CommonJS 社区独立了出去,单独成为了 AMD 社区,后来你们就知道了 RequireJS 特别火!

其实这个时候 脱离了 CommonJS 社区的 AMD 规范,实质上演化成了 RequireJS 的附属品,后来RequireJS 社区有很多人反馈想用 require 的方式,最后 RequireJS 作者妥协,才有了这个半残的支持。(注意这个是伪支持,背后依旧是 AMD 的运行逻辑,比如提前执行)AMD 的流行,很大程度上取决于 RequireJS 作者的推广,AMD 规范的演进,离不开 RequireJS。

Modules/2.0

BravoJS 的作者 Wes Garland 有很深厚的程序功底,在 CommonJS 社区也非常受人尊敬。但 BravoJS 本身非常学院派,是为了论证 Modules/2.0-draft 规范而写的一个项目。学院派在实用派的 RequireJS 面前不堪一击,现在基本上只留存了一些美好的回忆。

这时,Modules/2.0 阵营也有一个实战派:FlyScript,提出了非常简洁的Modules/Wrappings 规范:这个简洁的规范考虑了浏览器的特殊性,同时也尽可能兼容了 Modules/1.0 规范。悲催的是,FlyScript 在推出正式版和官网之后,RequireJS 当时正直红火。期间 FlyScript 作者 和 RequireJS 作者 James Burke 有过一些争论。再后来,FlyScript 作者做了自我阉割,将 GitHub 上的项目和官网都清空了,官网上当时留了一句话,模糊中记得是:我会回来的,带着更好的东西。

这中间究竟发生了什么,不得而知。后来玉伯发邮件给 FlyScript作者 询问,对方给了两点挺让我尊重的理由,大意是:

  1. 我并非前端出身,RequireJS 的作者 James Burke 比我更懂浏览器。

  2. 我们应该协同起来推动一个社区的发展,即便它不是你喜欢的。

这两句话对玉伯影响很大。也是那之后,开始仔细研究 RequireJS,并通过邮件等方式给 RequireJS 提出过不少建议。再后来,在实际使用 RequireJS 的过程中,遇到了很多坑。那时 RequireJS 虽然很火,但真不够完善。期间也在寻思着 FlyScript 离开时的那句话:“我会回来的,带着更好的东西”

玉伯说我没 FlyScript 的作者那么伟大,在不断给 RequireJS 提建议,但不断不被采纳后,开始萌生了自己写一个 loader 的念头。

这就是 SeaJS。SeaJS 借鉴了 RequireJS 的不少东西,比如将 FlyScript 中的 module.declare 改名为 define 等。SeaJS 更多地来自 Modules/2.0 的观点,但尽可能去掉了学院派的东西,加入了不少实战派的理念。这个就是CMD的间接产物,SeaJs。

好了基本的历史都说完了,不知道我说的能不能让大家听明白,大概的总结下就是 最先有的COMMONJS,因为COMMONJS用于是服务端的,不能直接用于浏览器,对于怎样将这个规范用在浏览器,新生事物必然有争论,也的就产生了不同的观念和论点,所以也就出现了适用于浏览器的AMD规范,CMD规范,AMD的存在的一些问题不被COMMONJS社区认同,最后独立运作,当然RequireJS也确实也大火了一段时间,后来CMD的产物seajs被玉伯开发出来。

到现在来看这两个产物估计是已经过时了,当然还有在用的,毕竟后来的webpack es6的发展势不可挡,webpakc对三种规范完全支持,后面的时间还会给大家分享下webpack的一些知识,对于前端模块化发展历史就说到这里,对于初学前端的人了解历史发展还是很有必要的。其实这原文是玉伯写的,我只是更改了下变成了我自己的化,方便大家理解,大家也可以去搜下关于前端模块化历史那点事,这里没有说为什么需要模块化 大家也可以先了解下,带着问题去学习才会学的更快。

显示全文