CommonJS

  • commonJS规范是在nodejs里面的
  • 它有四个重要的环境变量为模块化的实现提供支持:module、exports、require、global

用法

通过 require方法来同步加载所要依赖的其他模块,然后通过 exports 或者 module.exports 来导出需要暴露的接口

  1. // a.js
  2. var x = 5;
  3. var addX = function (value) {
  4. return value + x;
  5. };
  6. module.exports.x = x;
  7. module.exports.addX = addX;
  8. // b.js
  9. var example = require('./a.js');
  10. console.log(example.x); // 5
  11. console.log(example.addX(1)); // 6

优点

CommonJS 规范完成了JavaScript 的模块化,解决了依赖、全局变量污染的问题

缺点

commonJS 用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。这就是AMD规范诞生的背景。

AMD

  • 异步加载模块:这里异步指的是不堵塞浏览器其他任务(dom构建,css渲染等),而加载内部是同步的(加载完模块后立即执行回调)
  • require.js是AMD规范的实现

用法

  1. require(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) {
  2. // 模块加载完立即执行
  3. a.test()
  4. if (false) {
  5. b.foo()
  6. }
  7. })

优点

适合在浏览器环境中异步加载模块。 可以并行加载多个模块。

缺点

不能按需加载,而是必须提前加载所有的依赖。

CMD

  • sea.js 是对CMD规范的实现
  • 按需加载,依赖就近,延迟执行

用法

  1. // 与 commonjs 类似
  2. define(function(require, exports, module) {
  3. var a = require('./a'); //在需要时申明
  4. a.doSomething();
  5. if (false) {
  6. var b = require('./b');
  7. b.doSomething();
  8. }
  9. })

优点

同样实现了浏览器端的模块化加载。 可以按需加载,依赖就近。

缺点

依赖SPM打包,模块的加载逻辑偏重。

UMD

  • 结合 AMD 和 CommonJS 的一种更为通用的 JS 模块解决方案

打包出来的代码

  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
  3. typeof define === 'function' && define.amd ? define(factory) :
  4. (global.Vue = factory());
  5. }(this, (function () { 'use strict';
  6. // ...
  7. })))
  • 首先判断是否为 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 规范,成为浏览器和服务器通用的模块解决方案。

用法

  1. // profile.js
  2. var firstName = 'Michael';
  3. var lastName = 'Jackson';
  4. var year = 1958;
  5. export { firstName, lastName, year };
  6. // main.js
  7. import { firstName, lastName, year } from './profile.js';
  8. function setName(element) {
  9. element.textContent = firstName + ' ' + lastName;
  10. }

es6模块化和commonJs区别

  • CommonJS模块输出的是一个值的拷贝,就算导出的值变了,导入的值也不会改变。ES6 模块输出的是值的引用,导入值会跟随导出值变化
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • ES6模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,可以进行three-shaking的基础
  • commonjs可以多次加载,只会在第一次加载并缓存,以后加载去读缓存里面的,如果想让模块再次运行,必须清除缓存
  • commonjs加载的是整个模块,es6可以单独加载其中某个方法