【整理】 JavaScript模块化规范AMD 和 CMD 的区别有哪些?
根据玉伯等人在知乎上的回答整理。整理中。。。
AMD 规范在这里:https://github.com/amdjs/amdjs-api/wiki/AMD
CMD 规范在这里:https://github.com/seajs/seajs/issues/242
背景
要想将JavaScript提升到和其他编程语言一个级别的编程体验,包管理是一个必须之物。
早期如labjs首先解决的是js文件加载管理的问题。
LABjs 的核心是 LAB(Loading and Blocking):Loading 指异步并行加载,Blocking 是指同步等待执行。LABjs 通过优雅的语法(script 和 wait)实现了这两大特性,核心价值是性能优化。LABjs 是一个文件加载器。
RequireJS 和 SeaJS 则是模块加载器,倡导的是一种模块化开发理念,核心价值是让 JavaScript 的模块化开发变得更简单自然。
模块加载器一般可降级为文件加载器用,因此使用 RequireJS 和 SeaJS,也可以达成 LABjs 的性能优化目的。
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。还有不少⋯⋯
这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。目前这些规范的实现都能达成浏览器端模块化开发的目的。一般来说,AMD擅长在浏览器端、CMD擅长在服务器端。
AMD与CMD区别
对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
还有一些细节差异,具体看这个规范的定义就好,就不多说了。
另外,SeaJS 和 RequireJS 的差异,可以参考:https://github.com/seajs/seajs/issues/277
RequireJS 和 SeaJS区别
RequireJS 和 SeaJS 都是很不错的模块加载器,两者区别如下:
两者定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端
两者遵循的标准有差异。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
两者社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,而采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
两者代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。
两者对调试等的支持有差异。SeaJS 通过插件,可以实现 Fiddler 中自动映射的功能,还可以实现自动 combo 等功能,非常方便便捷。RequireJS 无这方面的支持。
两者的插件机制有差异。RequireJS 采取的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采取的插件机制则与 Node 的方式一致:开放自身,让插件开发者可直接访问或修改,从而非常灵活,可以实现各种类型的插件。
还有不少细节差异就不多说了。
总之,SeaJS 从 API 到实现,都比 RequireJS 更简洁优雅。如果说 RequireJS 是 Prototype 类库的话,则 SeaJS 是 jQuery 类库。
其他人经验
用了5年多的RequireJs,和一段时间的SeaJs,补充一下区别吧,
1、对于第3点,其实,RequireJS早有了Shim等支持,不需要修改第三方类库就可以完全支持.如Ember,JQuery等引用,都直接可以异步加载为一个模块.
2、对于调试的支持,RequireJS2.1版本也支持了.
3、RequireJs的打包功能很强大,很适合在CI下做各种配置下的打包发布,非常灵活方便,SeaJs这方面略力不从心.
4、对于模块的语法,RequireJs比较灵活,支持类似于SeaJs的语法
5、总体来说两个框架都很不错.SeaJs借鉴了前人框架的很多优点,发展势头不错.
RequireJs支持更全面一些,如Txt等文本文件的依赖,多版本的Js依赖,多语言支持,打包比SeaJs要简单些,在Jenkins等CI环境中,不受系统环境的限制.文档和范例比SeaJs全多了.缺点是:官方更新比较快,有好多次新版本都有些不兼容,如果你英文比较吃力,看文档可能就比较痛苦了.
SeaJs很简洁,很多功能也在慢慢完善,但底层细节暴露比较多,文档需要再补充些.希望在以后能再接再厉,加以改进.
其他人经验二
就我个人使用来看,requirejs上手就比seajs容易的多。
1.seajs打包spm实在是太难了,这跟r.js比起来简直不是一个档次。
2.requirejs支持css @import依赖的打包,对于不喜欢使用less的童鞋,就方便多了。
3.对于非AMD规范的js插件,require js提供了shim支持,非常方便。
4.requirejs目前支持了sourcemap,配合grunt,简直爽爆了。
出于从上手和配置上的方便性来看,我最终抛弃了seajs。
【整理】 JavaScript模块化规范AMD 和 CMD 的区别有哪些?的更多相关文章
- javaScript模块化规范ADM与CMD
模块化:模块化是指在解决某一个复杂问题时,依照一种分类的思维把问题进行系统性的分解处理,可以想象一个巨大的系统代码,被整合优化分割成逻辑性很强的模块时,对于软件是一种何等意义的存在. 模块化系统所必须 ...
- 前端模块化,AMD与CMD的区别
最近在研究cmd和amd,在网上看到一篇不错的文章,整理下看看. 在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可:如今CPU.浏览器性能得到了极大的提升,很多页面逻辑迁移到 ...
- js模块化规范AMD、CMD、CommonJS...
1. AMD 1.1 什么是AMD? AMD 英文名 Asynchronous Module Definition ,中文名 异步模块定义 .这是一个浏览器模块化开发的规范. 由于浏览器环境执行环境的 ...
- JavaScript中的模块化之AMD和CMD
前言: 为什么我们需要模块化开发,模块化开发的好处有哪些? 首先我们先说一下非模块化的开发方式带来的弊端. 非模块化开发中会导致一些问题的出现,变量和函数命名可能相同,会造成变量污染和冲突,并且出错时 ...
- 前端模块化和AMD、CMD规范
前端模块化和AMD.CMD规范 先看下基础:https://github.com/seajs/seajs/issues/547
- Javascript模块化规范
Javascript模块化规范 一.前端js模块化由来与演变 CommonJS 原来叫 ServerJS,推出 Modules/1.0 规范后,在 Node.js 等环境下取得了很不错的实践.09年下 ...
- 浅析JS中的模块规范AMD和CMD
一.AMD AMD就只有一个接口:define(id?,dependencies?,factory); 它要在声明模块的时候制定所有的依赖(dep),并且还要当做形参传到factory中,像这样: d ...
- javascript 模块化规范
服务器端规范 - CommonJS Node.js 浏览器端规范 - AMD RequireJS - CMD SeaJS
- AMD 和 CMD 的区别有哪些
在说AMD 和 CMD 的区别之前,先说明commonjs,它的回调和amd.cmd的不同于:commomjs加载完了所有模块,才执行回调amd和cmd是加载对应的模块,就可以执行回调中对应的代码 1 ...
随机推荐
- Atitit. Api 设计 原则 ---归一化
Atitit. Api 设计 原则 ---归一化 1.1. 叫做归一化1 1.2. 归一化的实例:一切对象都可以序列化/toString 通过接口实现1 1.3. 泛文件概念.2 1.4. 游戏行业 ...
- Jenkins的系统设置
1.登录Jenkins进入以下界面: 2.点击 系统管理 3.点击 系统设置 (下图的系统设置是已经设置好的) 4.这里设置主要设置 Jenkins URL (这里我是测试的所以使用默认的)与 邮件的 ...
- MVC利用URLRoute实现伪静态
routes.MapRoute( "Default", // Route name "{con ...
- cordova填坑
cordova填坑
- MySQL5.7.13源码编译安装指南
系统 CenterOs 6.5 1.安装依赖包(cmake make gcc等,其实好多都有了,不需要更新,为了防止世界被破坏,就装下) yum install gcc gcc-c++ -yyum i ...
- 快速入门系列--MVC--05行为
Action执行包含内容比较多,主要有同步/异步Action的概念和执行过程,Authorationfilter, ActionFiltor, ResultFilter, ExceptionFilte ...
- angularJS之事件处理
angularJS的事件不像js一样,会默认有冒泡和捕获,还有angularJS之间的同名控制器之间,也只是同名, 不会让他们关联起来,就是这个名字的控制器的数据的改变不会影响到另一个同名的控制器. ...
- ionic+nodejs开发遇到的跨域和post请求数据问题
最近学习ionic+nodejs开发混合app中遇到了一些问题,在此总结一下. 开发环境搭建 项目地址 https://github.com/ytudt/nodejsApp 代码和问题都会在之后的学习 ...
- Azure ARM (10) ARM模式下的虚拟机和Classic Model虚拟机的区别
<Windows Azure Platform 系列文章目录> 本文内容比较多,请大家仔细阅读,谢谢! 请读者注意,在Azure ARM平台,有两种虚拟机模式:经典虚拟机和ARM虚拟机 A ...
- 基于HTML5 Canvas实现工控2D叶轮旋转
之前在拓扑上的应用都是些静态的图元,今天我们将在拓扑上设计一个会动的图元——叶轮旋转. http://www.hightopo.com/guide/guide/core/serialization/e ...