CMD,AMD,UMD,commonjs,requirejs,seajs

之前一直对这几个东西看似熟悉实则模糊不清,今天查了一些资料,自己理了一下逻辑,大致分析下喽

看了一些别人的博客,又看了官网,还有一些其他的资料,大致算是理清了思路,如有不正确的,欢迎拍砖指正~~

commonjs

commonjs也是一种规范,是服务端模块的规范,nodejs就是采用这个规范。

它的规范机一个单独的文件就是一个模块。加载模块使用require方法,该方法读取文件并执行,最后导出一个exports对象。
commonjs是同步加载模块,加载完成后执行操作。一般服务端都是加载本地硬盘中的文件,速度快,就没有必要采用异步方式的来加载。但是如果我们考虑到浏览器端的话,就肯定知道,
同步加载,阻塞页面的渲染,造成页面白屏,或者卡死等现象,对于用户体验肯定是不友好的,所以就有了AMD,CMD.

AMD,CMD,UMD

AMD

即Asynchronous Module Definition的缩写,字面意思”异步模块定义”,就是一种规范。依赖前置(依赖在使用之前都必须提前加载)。requirejs可以简单理解为AMD规范的一种实现。下面介绍。
AMD写模块的api如下:

1
define(id,dependencies,factory);

id

string类型,一般表示模块名称,或者说标识,是一个可选参数。如果该参数不存在的话。如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。

模块名的格式

模块名用唯一标识定义,它们同样在依赖数组中使用。AMD的模块命名规范是Commonjs模块命名规范的超集。

  • 模块名是由一个或多个单词以正斜杠为分隔符拼接成的字符串
  • 单词须为驼峰形式,或者”.”,”..”
  • 模块名不允许使用文件扩展名的形式,如”.js”
  • 模块名可以为”相对的”或者”顶级的”。如果首字符为”.”或者”..”则为”相对的”模块名
  • 顶级的模块名从根命名空间的概念模块解析
  • 相对的模块名从”require”书写和调用的模块解析
dependencies

数组类型。是定义中模块所依赖模块的一个数组。依赖模块必须根据模块的工厂方法优先级执行,并且执行的结果应该按照数组中的位置顺序以参数的形式传入(定义中模块的)工厂方法中。

依赖的模块名如果是相对的,应该解析为相对定义中的模块。相对名解析为相对于模块的名字,并非相对于寻找该模块的名字和路径。

该参数也是可选参数,如果没有这个参数,它默认为[“require”, “exports”, “module”]。然而,如果工厂方法的形参个数小于3,加载器会选择以函数指定的参数个数调用工厂方法。

factory

值的类型多选。是模块初始化要执行的函数或者对象。如果是函数的话,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。

如果工厂方法返回一个值(对象,函数,或任意强制类型转换为true的值),应该被设置为模块的输出值。

以上引用https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96%87%E7%89%88),原文链接markdown语法限制会跳错,么办法了,只能换成短连接了。

CMD

即Common Module Definition,一个模块就是一个文件,它严格区别推崇职责单一,并依赖就近,实现延迟加载(ps:as lazy as posibile)。什么时候引用什么时候加载,但是加载顺序会按照代码顺序。
seajs基本上算是它的一种实现了。
基本语法:

1
define(factory);

如果factory是一个函数,经常应该是这样的:

1
define(function(require,exports,module){})

UMD

即Universal Module Definition,应该算是AMD和commonjs的一个糅合。
其原理:先判断是否支持nodejs的模块(exports)是否存在,如果存在就是用nodejs模块模式,然后再判断是否支持AMD(define是否存在),如果存在就使用AMD方式加载模块

AMD,CMD 区别

对于依赖,AMD是提前执行,也就是依赖前置,CMD是延迟执行,也就是依赖就近。但是从requirejs2.0开始,也可以延迟执行(写法不同,处理方法不同)

requirejs seajs

这两个分别是ADM,CMD的实现方案,肯定有异同。
相同之处:
两者都是模块加载器,倡导js模块化开发的理念。

不同之处:

  • 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
  • 遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
  • 推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
  • 对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。
  • 插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。

引用https://github.com/seajs/seajs/issues/277