CommonJS·AMD·UMD·ES6

4,639 阅读2分钟

前言

本篇文章并不会深入原理,更着重表层上每一种模块规范之间的差异的表现。深入的原理以及实现的细节,希望以后有机会可以深入研究。

CommonJS

  1. 使用requireexports关键字和模块系统进行交互
  2. CommonJS不支持异步加载
  3. 一个文件就是一个模块

Nodejs的模块规范受到了CommonJS的影响,但Nodejs支持使用module.exports导出对象,而CommonJS只使用exports。CommonJS模块在未经编译前无法使用。示例如下。

1

// modules/physics.js
module.exports = {
  lorentzTransformation () {
  },
  maxwellSEquations () {
  }
}
// index.js
const physics = require('./modules/physics')

physics.lorentzTransformation()
physics.maxwellSEquations()

module.exports 和 exports

module是一个带有exports属性的对象,exports是普通的js变量,是module.exports的引用。如果设置exports.name = '叶奈法',相当于设置module.exports.name = '叶奈法'。但是,如果给exports设置了一个新的对象,exportsmodule.exports将不再是同一个对象。

// 简化的理解
var module = { exports: {} }
var exports = module.exports

AMD

AMD诞生的原因是,是因为CommonJS不支持异步加载,不适合浏览器环境。RequireJS实现了AMD API。示例如下。

2

index.html中使用<script/>标签加载RequireJS,通过data-main属性指定主文件。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>AMD</title>
  <!-- require.js -->
  <script data-main='./index.js' src="./require.js"></script>
</head>
<body>
</body>
</html>

define关键字用于定义模块,模块分为独立模块(不依赖其他模块的模块)以及非独立模块(依赖其他模块的模块)

// 独立模块
// libs/geometry.js
define(function() {
  'use strict';
  return {
    pythagoreanTheorem(a, b) {
      return a * a + b * b
    }
  }
})
// 非独立模块,本模块引用了geometry模块
// libs/math.js
define(['./geometry.js'], function(geometry) {
  'use strict';
  return {
    geometry: {
      pythagoreanTheorem: geometry.pythagoreanTheorem
    }
  }
})

require关键字用来引用模块

// index.js
// 加载math模块
require(['./libs/math'], function (math) {
  var c = math.geometry.pythagoreanTheorem(1, 2)
  alert(c)
})

ES6

ES6在语言层面上实现了模块机制,与CommonJS与AMD规范不同的是ES6的模块是静态的,不能在文件的任何地方使用。这种行为使得编译器编译时就可以构建依赖关系树,但是在ES6模块没法在浏览器中完全实现,需要使用babel,webpack。

3

// src/modules/physics.js
export function maxwellSEquations () {
  alert('maxwellSEquations')
}
// src/main.js
import { maxwellSEquations } from './modules/physics'

maxwellSEquations()

UMD

UMD模块是一种通用的模式,用于兼容AMD和CommonJS的规范。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 ($) {
  // ...
}));

参考