CommonJS
服务器端的 Node.js 遵循 CommonJS规范,该规范的核心思想是允许模块通过 require
方法来同步加载所要依赖的其他模块,然后通过 exports
或 module.exports
来导出需要暴露的接口。
使用
引入模块
let express = require('express');
导出模块
module.exports.test1 = function () {}
exports.test2 = {}
优缺点
优点
- 服务器端模块便于重用
- NPM中已经有超过45万个可以使用的模块包
- 简单并容易使用
缺点
- 同步的模块加载方式不适合浏览器环境,同步意味着阻塞加载,浏览器资源是异步加载的
- 不能非阻塞的并行加载多个模块
实现
- 服务器端的 Node.js
- Browserify,浏览器端的 CommonJS 实现,可以使用 NPM 的模块,但是编译打包后的文件体积可能很大
- modules-webmake,类似Browserify,还不如 Browserify 灵活
- wreq,Browserify 的前身
AMD
Asynchronous Module Definition 规范其实只有一个主要接口,define(id?, dependencies?, factory)
,它要在声明模块的时候指定所有的依赖dependencies
,并且还要当做形参传到factory
中,对于依赖的模块提前执行,依赖前置。
使用
定义模块
define('module', ['dep1', 'dep2'], function (d1, d2) {
return {}
});
引入模块
require(['module', '../file'], funtion(module, file) {
// ...
})
优缺点
优点
- 适合在浏览器环境中异步加载模块
- 可以并行加载多个模块
缺点
提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义不顺畅
-
不符合通用的模块化思维方式,是一种妥协的实现
实现
CMD
Common Module Definition 规范和 AMD 很相似,尽量保持简单,并与 CommonJS 和 Node.js 的 Modules 规范保持了很大的兼容性。
使用
定义
define(function (require, exports, module) {
var $ = require('jquery');
var Sprinning = require('./spinning');
exports.test1 = {};
module.exports = {};
});
引入
define(function (require, exports, module) {
var $ = require('jquery');
$('div')...
});
优缺点
优点
- 依赖就近,延迟执行
- 可以很容易在Node.js中运行
缺点
- 依赖SPM打包,模块的加载逻辑偏重
实现
ES6 模块
EcmaScript6 标准增加了 JavaScript 语言层面的模块体系定义。ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
使用
定义
export default {
a: 10,
b: function () {
// ...
}
}
引入
import 'jquery';
import Vue from 'vue'
import { render } from 'react-dom'
优缺点
优点
- 容易进行静态分析
- 面向未来的ECMAScript标准
缺点
原生浏览器还没有实现标准
-
全新的命令字,新版的Node.js才支持
实现
期望的模块系统
可以兼容多种模块风格,尽量可以利用已有的代码,不仅仅只是 JavaScript 模块化,还有 CSS、图片、字体等资源也需要模块化。