AMD和CMD规范
1.名词解释
AMD:Asynchronous Modules Definition异步模块定义,提供定义模块及异步加载该模块依赖的机制。
CMD:Common Module Definition 通用模块定义,提供模块定义及按需执行模块
RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范,node.js遵循CommonJS规范。规范的不同,导致了两者 API 不同。
2. 提前执行:提前异步并行加载
优点:尽早执行依赖可以尽早发现错误;缺点:容易产生浪费
3. 延迟执行:延迟按需加载
优点:减少资源浪费 缺点:等待时间长、出错时间延后
2.1 AMD与CMD代码模式
AMD代码模式-运行策略
define(['./a', './b'], function(a, b) { //运行至此,a.js和b.js已经下载完成 a模块和b模块已经执行完,直接可用;
a.doing();
// 此处省略500行代码
b.doing();
});
CMD代码模式-运行策略
define(function(require, exports, module) {
var a = require("./a"); //等待a.js下载、执行完
a.doing();
// 此处省略500行代码
var b = require("./b"); //依赖就近书写
b.doing();
});
3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
方案 | 优势 | 劣势 | 特点
AMD | 速度快 | 会浪费资源 | 预先加载所有的依赖,直到使用的时候才执行
CMD | 只有真正需要才加载依赖 | 性能较差 | 直到使用的时候才定义依赖
它们除了希望放在浏览器作为loader也能够放在服务端,提供加载功能。在我看来,AMD擅长在浏览器端、CMD擅长在服务器端。这是因为浏览器加载一个功能不像服务器那么快,有大量的网络消耗。所以一个异步loader是更接地气的。
或者,干脆使用YUI3的模块机制,在上线前进行压制。把互相依赖的模块压在一个文件中。
---------------------------------------------------------------------------------------------------
每一个卓越的思想都有一份朴实的代码实现。所以无论AMD与CMD都要面临以下几个问题:
scriptElement= document.createElement('script');
scriptElement.src = moduleUrl;
scriptElement.async = true;
scriptElement.onload = function(){.........};
document.head.appendChild(scriptElement);
5、模块加载完毕后,获取依赖项(amd、cmd区别),改变模块status,由statuschange后,检测所有模块的依赖项。
由于requirejs与seajs遵循规范不同,requirejs在define函数中可以很容易获得当前模块依赖项。而seajs中不需要依赖声明,所以必须做一些特殊处理才能否获得依赖项。方法将factory作toString处理,然后用正则匹配出其中的依赖项,比如出现require(./a),则检测到需要依赖a模块。
同时满足非阻塞和顺序执行就需要需要对代码进行一些预处理,这是由于CMD规范和浏览器环境特点所决定的。
6、如果模块的依赖项完全加载完毕(amd中需要执行完毕,cmd中只需要文件加载完毕,注意这时候的factory尚未执行,当使用require请求该模块时,factory才会执行,所以在性能上seajs逊于requirejs),执行主模块的factory函数;否则进入步骤3.
AMD规范定义了一个自由变量或者说是全局变量 define 的函数
define( id?, dependencies?, factory );
define("alpha", [ "require", "exports", "beta" ], function( require, exports, beta ){
export.verb = function(){
return beta.verb();
// or:
return require("beta").verb();
}
});
define(["alpha"], function( alpha ){
return {
verb : function(){
return alpha.verb() + 1 ;
}
}
});
define( {
add : function( x, y ){
return x + y ;
}
} );
局部 与 全局 的require
define( ['require'], function( require ){
// ...
} );
or:
define( function( require, exports, module ){
// ...
} );
require(String)
define( function( require ){
var a = require('a'); // 加载模块a
} );
require(Array, Function)
define( function( require ){
require( ['a', 'b'], function( a,b ){ // 加载模块a b 使用
// 依赖 a b 模块的运行代码
} );
} );
require.toUrl( Url )
define( function( require ){
var temp = require.toUrl('./temp/a.html'); // 加载页面
} );
define({ "foo": "bar" });
define('this is {{data}}.');
define( function(require, exports, module) { // 模块代码 });
define( 'module', ['module1', 'module2'], function( require, exports, module ){
// 模块代码
} );
define(function( require, exports ){
var a = require('./a');
a.doSomething();
});
define( function(require, exports, module) {
require.async('.a', function(a){
a.doSomething();
});
});
define(function( require, exports ){
exports.foo = 'bar'; // 向外提供的属性
exports.do = function(){}; // 向外提供的方法
});
define(function( require, exports ){
return{
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});
define({
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
});
define(function( require, exports ){
exports = {
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});
需要这么做
define(function( require, exports, module ){
module.exports = {
foo : 'bar', // 向外提供的属性
do : function(){} // 向外提供的方法
}
});
这种方式通过一个叫做require的方法,同步加载依赖,然后返导出API供其它模块使用,一个模块可以通过exports或者module.exports导出API。CommonJS规范中,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,在一个文件中定义的变量,都是私有的,对其他文件是不可见的。
Well
服务端模块可以很好的复用
这种风格的模块已经很多了,比如npm上基本上都是这种风格的module
简单易用
Less Well
加载模块是同步的,所以只有加载完成才能执行后面的操作
多个模块不能并行加载
像Node.js主要用于服务器的编程,加载的模块文件一般都已经存在本地硬盘,所以加载起来比较快,不用考虑异步加载的方式,所以CommonJS规范比较适用。但如果是浏览器环境,要从服务器加载模块,这是就必须采用异步模式。所以就有了 AMD 、CMD 的解决方案。
CommonJS规范
// moduleA.js
module.exports = function( value ){
return value * 2;
}
// moduleB.js
var multiplyBy2 = require('./moduleA');
var result = multiplyBy2(4);
CommonJS是同步加载模块,但其实也有浏览器端的实现,其原理是将所有模块都定义好并通过id进行索引,这样就可以浏览器进行解析了
服务器端的Node.js遵循CommonJS规范。核心思想是允许模块通过require 方法来同步加载所要依赖的其他模块,然后通过 exports或module.exports来导出需要暴露的接口。
require("module");
require("../file.js");
exports.doStuff = function() {};
module.exports = someValue;
- 服务器端便于重用
- NPM中已经将近20w个模块包
- 简单并容易使用
- 同步的模块方式不适合不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的
- 不能非阻塞的并行加载多个模块
AMD
define("module", ["dep1", "dep2"], function(d1, d2) {
return someExportedValue;
});
require(["module", "../file"], function(module, file) { /* ... */ });
优点:
- 适合在浏览器环境异步加载
- 并行加载多个模块
- 提高开发成本,代码阅读和书写比较困难
- 不符合通用的模块思维方式,是一种妥协的实现
CMD
CMD规范和AMD相似,尽量保持简单,并且与CommonJS和NodeJS的Modules规范保持了很大的兼容性。
define(function(require, exports, module) {
var $ = require('jquery');
var Spinning = require('./spinning');
exports.doSomething = ...
module.exports = ...
})
优点:
- 依赖就近,延迟执行
- 很容易在node中运行
- 依赖SPM打包,模块的加载逻辑偏重
转载:https://www.zhihu.com/question/20351507
http://blog.csdn.net/vuturn/article/details/51970567
AMD和CMD规范的更多相关文章
- amd,cmd规范
AMD 和 CMD 的区别有哪些? AMD规范与CMD规范的区别 回顾:前端模块化和AMD.CMD规范(全) 浅析JS模块规范:AMD,CMD,CommonJS 理解AMD ,CMD,CommonJS ...
- 前端模块化和AMD、CMD规范
前端模块化和AMD.CMD规范 先看下基础:https://github.com/seajs/seajs/issues/547
- src和href 如何做好seo 前端页面有那三层 AMD和CMD 规范的区别 渐进增强
1==>简述一下src与href的区别 src用于替换当前元素: href用于在当前文档和引用资源之间确立联系 2==>.谈谈以前端角度出发做好SEO需要考虑什么? a. 了解搜索引擎如何 ...
- 回顾:前端模块化和AMD、CMD规范(全)
先列举下一些著名言论: "我想定义一个 each 方法遍历对象,但页头的 util.js 里已经定义了一个,我的只能叫 eachObject 了,好无奈." "Requi ...
- AMD、CMD规范
本文原链接:https://cloud.tencent.com/developer/article/1177217 AMD && CMD 前言 一.模块 二.CommonJS 三.AM ...
- JavaSript模块规范 - AMD规范与CMD规范介绍
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题 ...
- JavaSript模块规范 - AMD规范与CMD规范介绍(转)
JavaSript模块规范 - AMD规范与CMD规范介绍 JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者 ...
- JavaSript模块化-AMD规范与CMD规范
JavaScript模块化 在了解AMD,CMD规范前,先来简单地了解下什么是模块化,模块化开发. 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题进行系统性的分解以之处 ...
- JavaSript模块规范 - AMD规范与CMD规范介绍 (转载lovenyf.blog.chinaunix.net)
JavaSript模块化 在了解AMD,CMD规范前,还是需要先来简单地了解下什么是模块化,模块化开发? 模块化是指在解决某一个复杂问题或者一系列的杂糅问题时,依照一种分类的思维把问题 ...
随机推荐
- 【Java基础】2、Java中普通代码块,构造代码块,静态代码块区别及代码示例
Java中普通代码块,构造代码块,静态代码块区别及代码示例.Java中普通代码块,构造代码块,静态代码块区别及代码示例 执行顺序:静态代码块>静态方法(main方法)>构造代码块>构 ...
- Django Rest Framework之用户频率/访问次数限制
内置接口代码基本结构 settings.py: REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES':['api.utils.mythrottle.UserThr ...
- 洛谷P3346 [ZJOI2015]诸神眷顾的幻想乡(广义后缀自动机)
题意 题目链接 Sol 广义SAM的板子题. 首先叶子节点不超过20,那么可以直接对每个叶子节点为根的子树插入到广义SAM中. 因为所有合法的答案一定是某个叶子节点为根的树上的一条链,因此这样可以统计 ...
- vue2.0 element-ui中el-upload的before-upload方法返回false时submit()不生效解决方法
我要实现的功能是在上传文件之前校验是否表格中存在重复的数据,有的话,需要弹窗提示是否覆盖,确认之后继续上传,取消之后,就不再上传. 项目中用的element-ui是V1.4.3 <el-uplo ...
- 不要拿ERP的报表忽悠领导!——一个报表引发的企业经营反思
文 | 帆软数据应用研究院船长 本文出自:知乎专栏<帆软数据应用研究院>——数据干货&资讯集中地 领导的经营决策能只依赖于ERP报表吗? 不能! 1. ERP报表个性化不足:企业经 ...
- Kotlin入门(8)空值的判断与处理
上一篇文章介绍了如何对循环语句进行操作,末尾还演示了发现空串时直接继续下一循环,只是在初始化字符串数组时使用了“val poem2Array:Array<String?> = ***”,该 ...
- mysql的varchar字段可以存储多少个中文字符
创建数据库,并创建一张表mytb进行测试 ******************************************************************************* ...
- Python机器学习入门
# NumPy Python科学计算基础包 import numpy as np # 导入numpy库并起别名为npnumpy_array = np.array([[1,3,5],[2,4,6]])p ...
- 洗礼灵魂,修炼python(31)--面向对象编程(1)—面向对象,对象,类的了解
面向对象 1.什么是面向对象 (图片来自网络) 哈哈,当然不是图中的意思. 1).面向对象(Object Oriented,OO)是软件开发方法.利用各大搜索引擎得到的解释都太官方,完全看不懂啥意思对 ...
- python第三天 变量 作业
作业1,模拟登陆:1. 用户输入帐号密码进行登陆2. 用户信息保存在文件内3. 用户密码输入错误三次后锁定用户 使用文件:user_file.txt 用户列表文件. 格式:{'张三':'12 ...