CommonJS
- commonJS规范是在nodejs里面的
- 它有四个重要的环境变量为模块化的实现提供支持:module、exports、require、global
用法
通过 require方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口
// a.js
var x = 5;
var addX = function (value) {
return value + x;
};
module.exports.x = x;
module.exports.addX = addX;
// b.js
var example = require('./a.js');
console.log(example.x); // 5
console.log(example.addX(1)); // 6
优点
CommonJS 规范完成了JavaScript 的模块化,解决了依赖、全局变量污染的问题
缺点
commonJS 用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。这就是AMD规范诞生的背景。
AMD
- 异步加载模块:这里异步指的是不堵塞浏览器其他任务(dom构建,css渲染等),而加载内部是同步的(加载完模块后立即执行回调)
- require.js是AMD规范的实现
用法
require(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) {
// 模块加载完立即执行
a.test()
if (false) {
b.foo()
}
})
优点
适合在浏览器环境中异步加载模块。 可以并行加载多个模块。
缺点
不能按需加载,而是必须提前加载所有的依赖。
CMD
- sea.js 是对CMD规范的实现
- 按需加载,依赖就近,延迟执行
用法
// 与 commonjs 类似
define(function(require, exports, module) {
var a = require('./a'); //在需要时申明
a.doSomething();
if (false) {
var b = require('./b');
b.doSomething();
}
})
优点
缺点
依赖SPM打包,模块的加载逻辑偏重。
UMD
- 结合 AMD 和 CommonJS 的一种更为通用的 JS 模块解决方案
打包出来的代码
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Vue = factory());
}(this, (function () { 'use strict';
// ...
})))
- 首先判断是否为 node 环境:exports 为一个对象,并且 module 存在
- 如果是 node 环境就用 module.exports = factory() 把 vue 导出 (通过 require(‘vue’) 进行引用)
- 如果不是 node 环境判断是否支持 AMD:define 为 function 并且 define.amd 存在
- 如果支持 AMD 就使用 define 定义模块,(通过 require([‘vue’]) 引用)
- 否则的话直接将 vue 绑定在全局变量上(通过 window.vue 引用)
ES6 modules
- 之前的几种模块化方案都是前端社区自己实现的,只是得到了大家的认可和广泛使用
- ES6 在语言标准的层面上,实现了模块功能,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
用法
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };
// main.js
import { firstName, lastName, year } from './profile.js';
function setName(element) {
element.textContent = firstName + ' ' + lastName;
}
es6模块化和commonJs区别
- CommonJS模块输出的是一个值的拷贝,就算导出的值变了,导入的值也不会改变。ES6 模块输出的是值的引用,导入值会跟随导出值变化
- CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
- ES6模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,可以进行three-shaking的基础
- commonjs可以多次加载,只会在第一次加载并缓存,以后加载去读缓存里面的,如果想让模块再次运行,必须清除缓存
- commonjs加载的是整个模块,es6可以单独加载其中某个方法