JavaScript中常说的模块规范

  • CommonJS 规范
  • AMD 规范
  • UMD 规范
  • ES6 模块 规范


CommonJS 规范

CommonJS 规范定义了模块应该怎样进行编写,从而各个模块系统之间可以进行相互操作。

var beta = require('beta');

function verb {

  return beta.verb();

}

module.exports = {

  verb: verb

};

CommonJS 有以下特点:

  • 一个文件就是一个模块;
  • 使用require()载入模块,使用module.exports输出模块,因此各个模块间可以进行交互;
  • 不支持异步加载

AMD 规范

顾名思义,异步模块定义(AMD)主要为了解决异步加载模块而提出,它通过指定模块和依赖项的方式来定义模块。

define("alpha", ["require", "exports", "beta"], function (

  require,

  exports,

  beta

) {

  exports.verb = function () {

    return beta.verb();

    // 或者可以这么写

    return require("beta").verb();

  };

});

在该示例中,导出 ID 为 alpha 的模块,依赖了 ID 为 beta 的模块。

现在我们知道,Node.js 环境中的模块系统基于 CommonJS 规范,而浏览器环境中需要使用 AMD 实现。

那么如果我们有一个模块,需要同时能运行在 Node.js 环境和浏览器环境中,要怎么办?我们可以使用 UMD 模式。

UMD 规范

为了兼容 AMD 和 CommonJS 的规范,通用模块定义(UMD)模式被提出,它在兼容两者的同时,也支持了传统的全局变量模式。

(function (root, factory) {

  if (typeof define === "function" && define.amd) {

    // AMD

    define(["jquery"], factory);

  } else if (typeof exports === "object") {

    // CommonJS

    module.exports = factory(require("jquery"));

  } else {

    // 全局变量

    root.returnExports = factory(root.jQuery);

  }

})(this, function ($) {

  // ...

});

UMD 模块头部通常都会有用来判断模块加载器环境的代码,并根据不同的环境提供了不同的方式进行加载。

ES6 模块 规范

// import 导入

import BaseTask, { TaskType } from "./BaseTask";

// export 导出

export { BaseTask };

在该示例中,使用import加载模块,使用export输出模块。

ES6 模块的特点如下:

  • 使用import加载和export输出;
  • 一个模块只会加载一次(CommonJS 也是一样);
  • 导出的模块为变量引用,因此可以在内存中共享。

现在大多数前端项目中都使用 ES6 模块,由于 ES6 模块化目的是编译阶段确定模块间依赖关系,因此我们需要在编译的时候使用 Babel、Webpack 等方式构建依赖关系树。

除此之外,ES6 模块化在各个浏览器里的兼容性差异较大,因此同样需要进行 Babal 编译以及 Webpack 进行打包,这个过程我们称之为 前端代码构建.