模块化进程——CommonJs、AMD、CMD、UMD

原因

javascript早期作为一门轻量级语言,用于在 Web 上与用户进行少量的交互,并没有依赖管理的概念。但随着ajax技术的发展,js被要求实现的功能越来越多。全局变量污染,依赖混乱等问题亟待解决。其他语言已经实现的模块化被提上日程。

前驱

在正式的模块化方案发布之前,有人想了其他方法解决变量污染的问题

  1. 雅虎的开源组件库 YUI Library
    采用了类似java命名空间的方式,但是因为调用和封装都太过复杂并没有推广起来
YUI.util.module.doSomthing();
  1. JQuery
    运用了闭包的特性,在加载之初执行函数,把JQuery变量挂载到全局的window对象上
(function(root){
  root.JQuery = root.$ = JQuery
})(window)

正式起航

1、CommonJS -- 最早的解决方案

1.1 背景
  1. mozilla 的工程师为解决用于服务端的js的自动化测试的模块导入问题,制定了一套模块化导入的规范,命名为ServerJS(Modules/0.1),这就是CommonJS的前身。
  2. 后来正式更名为CommonJS(Modules/1.0),从命名可以看出其野心,企图一统所有编程语言的模块化方案。
  3. Node的创始人决定为其包依赖管理寻找解决办法时选择了CommonJS的规范来,我觉得对其的推广起到了极大的促进作用。
1.2 具体实现
  1. 在CommonJS中一个文件就是一个模块,拥有自己独立的作用域,变量及方法;
  2. 定义全局变量require,通过在require中传入唯一的标识来引入文件的依赖模块,其执行结果就是模块暴露的API;
  3. 如果执行失败,require会抛出一个错误;
  4. 模块通过exports向外暴露API,导出的必须是一个object,暴露的API是该对象的属性
//moudleA.js
moudle.exports = {
    a: 1
};
//moudleB.js
var ma = require('./moudleA');
var b = ma.a + 2;
module.exports ={
    b: b
};

分裂统一(AMD、CMD、UMD)

由于CommonJS是起源于服务端的,所以虽然说他是一门很好的模块化解决办法的实现方法,但是其并不能运用于浏览器端。所以浏览器端需要新的实现方法。但是在实现方法上CommonJS内部出现了分歧,从而诞生了AMD、CMD、UMD三种解决方法(当然还有其他小众的方法,因为其使用人数较少这里不做讨论)。

保守派 —— browserify

这一派的理念是不动CommonJS,为配合浏览器实现,可以使用一些其他方法将其转化成浏览器可以理解的方法。跟我们现在的Babel的实现思想是一样的。browserify就是这一观点下的产物。

激进派—— AMD(RequireJS)

这一派的观点是既然不适用了那就改,应该依据浏览器的特点放弃require,改用回调方式。但是其观点并没有被CommonJS社区接受所以这一派最终脱离了CommonJS社区自立门户,起初是专注于RequireJS的开发,后来才起草了AMD 异步模块定义规范(Async Module Definition)。

AMD 作为一个规范,只需定义其语法 API,而不关心其实现。AMD 规范简单到只有一个 API,即 define 函数:

 define(id?, dependencies?, factory);
  1. 定义全局函数 define(id, dependencies, factory),用于定义模块。dependencies 为依赖的模块数组,在 factory 中需传入形参与之一一对应。
  2. 如果 dependencies 的值中有 require、exports 或module,则与 CommonJS 中的实现保持一致。
  3. 如果 dependencies 省略不写,则默认为 ['require', 'exports', 'module'],factory 中也会默认传入三者。
  4. 如果 factory 为函数,模块可以通过以下三种方式对外暴漏 API:return 任意类型;exports.XModule = XModule、module.exports = XModule。
  5. 如果 factory 为对象,则该对象即为模块的导出值。

中间派——CMD、UMD

1. CMD

这一派认为require不用放弃,但export也可以导出除object以外的其他类型。淘宝玉伯写出了SeaJS,提出了CMD(Common Module Definition)规范,其在国内很火,但并未在国外流行。

CMD 规范的主要内容与 AMD 大致相同,不过保留了 CommonJS 中最重要的延迟加载、就近声明(就近依赖)特性。

// moudleA.js
define(function(require, exports, module) {
  module.exports = { 
      a: 1 
  };
});
// moudleB.js
define(function(require, exports, module) {
  var ma = require('./moudleB');
  var b = ma.a + 2;
  module.exports = { 
      b: b 
  };
});
2. UMD

UMD 即 Universal Module Definition 的缩写,它本质上并不是一个真正的模块化方案,而是将 CommonJS 和 AMD 相结合。

((root, factory) => {
    if (typeof define === 'function' && define.amd) {
        //AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        //CommonJS
        var $ = requie('jquery');
        module.exports = factory($);
    } else {
        root.testModule = factory(root.jQuery);
    }
})(this, ($) => {
    //todo
});

正统 —— ES6/ES2015

时间前进到 2016 年 5 月,经过了两年的讨论,ECMAScript 6.0 终于正式通过决议,成为了国际标准。

在这一标准中,首次引入了 importexport 两个 JavaScript 关键字,并提供了被称为 ES Module 的模块化方案。

你可能感兴趣的:(模块化进程——CommonJs、AMD、CMD、UMD)