js 模块化规范

模块化的发展历程

按照诞生时间的先后顺序

  1. CommonJs,2009年1月
  2. AMD Asynchronous Module Definition, 2011年2月
  3. CMD Common Module Definition, 2011年4月后
  4. UMD Universal Module Definition, 2014年9月
  5. ESM EcmaScript Module, 2016年5月

CommonJs 模块规范

第一阶段: Modules/1.0, 产物 browserify
第二阶段: Modules/Async, 诞生了 Modules/AsynchronousDefinition 规范
第三阶段: Modules/2.0,基于 CommonJS 规范的实现:BravoJS

  • 运行时加载,一个文件就是一个模块
  • 更适合服务端,node.js 采用了这个规范
  • 同步加载模块,不支持异步
  • 使用 require/exports 关键字

AMD

AMDRequireJS 在推广过程中对模块定义的规范化产出。

  • 一种基于模块的异步加载的js代码机制
  • 通过延迟和按需加载来解决各个模块之间的依赖关系,依赖前置、提前执行
  • define 关键字用于定义模块,require 关键字用来引用模块

CMD

CMD 是阿里的玉伯(王保平)在借鉴了CommonJs 和 AMD 方案后写出的 SeaJS 在推广过程中对模块定义的规范化产出。

  • 与AMD大体相同,也是异步加载
  • 特点是 依赖就近、延迟执行

AMD 和 CMD 的依赖和执行时机的比较

AMD:

// a.js
define(function () {
    console.log('init a.js');
    return {
        getFun: function () {
            return 'I am a';
        }
    };
});
// b.js
define(function () {
    console.log('init b.js');
    return {
        getFun: function () {
            return 'I am b';
        }
    };
});
// index.js
define(function (require) {
    var a = require('./a');
    console.log(a.getFun());
    var b = require('./b');
    console.log(b.getFun());
});


// 输出结果如下 
// init a.js
// init b.js
// I am a
// I am b

CMD:

// a.js
define(function (require, exports, module) {
    console.log('init a');
    exports.getFun = function () {
        return 'I am a';
    }
});
// b.js
define(function (require, exports, module) {
    console.log('init b');
    exports.getFun = function () {
        return 'I am b';
    }
});
// index.js
define(function(require, exports, module) {
    var a = require('./a'); //在需要时申明
    console.log(a.getFun());
    var b = require('./b'); //在需要时申明
    console.log(b.getFun());
});


// 输出 
// init a
// I am a
// init b
// I am b

UMD

  • 前后端跨平台的解决方案
  • 兼容 AMD 和 CommonJS 的规范,并支持传统的声明全局变量的方式
    1. 先判断是否支持 AMD(define是否存在),存在则使用 AMD 方式加载模块
    2. 再判断是否支持 Node.js 模块格式( exports 是否存在),存在则使用 Node.js 模块格式
    3. 前两个都不存在,则将模块公开到全局( window 或 global )
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'underscore'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'), require('underscore'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery, root._);
    }
}(this, function ($, _) {
    //    methods
    function a(){};    //    private because it's not returned (see below)
    function b(){};    //    public because it's returned
    function c(){};    //    public because it's returned

    //    exposed public methods
    return {
        b: b,
        c: c
    }
}));

ESM

2015年6月,ES6/ES2015 正式通过决议,从语言层面提出的一种模块化标准。

  • 编译时加载,模块加载从入口文件开始,最终生成完整的模块实例关系图,过程包含:
    1. 构建:查找,下载,然后把所有文件解析成 module record。
    2. 实例化:为模块分配内存空间,依照导入,导出语句把模块指向对应内存地址。
    3. 运行:把内存空间填充为真实值。
  • node V8.5.0+ 对其进行了支持
  • 使用 import / export 关键字

参考

https://github.com/amdjs/amdjs-api/wiki/AMD
CMD 模块定义规范
Sea.js 与 RequireJS 的异同
https://www.davidbcalhoun.com/2014/what-is-amd-commonjs-and-umd/
https://dev.to/iggredible/what-the-heck-are-cjs-amd-umd-and-esm-ikm
编程时间简史

你可能感兴趣的:(js 模块化规范)