前端模块化

背景

最近在梳理前端的公众号支付流程,从前端流程微信JSSDK的引入开始查阅文档。
在引入JS文件一小段中,文档中备注:“支持使用 AMD/CMD 标准模块加载方法加载”。
于是,想到对CommonJS、AMD、CMD、ES6Module等概念与代码实例的理解甚是混淆,于是学习、总结此文。

前端模块化


2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。这标志”Javascript模块化编程”正式诞生。
因为老实说,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。NodeJS是CommonJS规范的实现,webpack 也是以CommonJS的形式来书写。

为了提高代码的复用率,方便代码进行管理,我也不知先后(应该CommonJS最早吧)的出现了一系列的模块化的规范:CommonJS、AMD、CMD以及(ES6Module)。

通常来讲:一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。

这三个规范都是为javascript模块化加载而生的,都是在用到或者预计要用到某些模块时候加载该模块,使得大量的系统巨大的庞杂的代码得以很好的组织和管理。模块化使得我们在使用和管理代码的时候不那么混乱,而且也方便了多人的合作。

CommonJS


  • CommonJS是一个更偏向于服务端的规范。Node.js就是CommonJS规范的主要实践者。
  • CommonJS不适用浏览器是因为:此规范是同步加载模块,对于服务器端来说,所有的模块都是在本地磁盘,等待模块时间就是硬盘读取文件时间,很小,但对浏览器而言,设计到网速、代理更原因,同步加载会造成阻塞,浏览器处于“假死”状态,所以浏览器端出现了AMD规范。

代码实现拓展:CommonJS规范

AMD

  • AMD是Asynchronous Module Definition的缩写,即“异步模块定义”,它采用异步方式加载模块(模块的加载不影响它后面语句的运行),且会提前加载。
  • AMD同CommonJS一样也是使用require加载模块,但不同的是,AMD要求两个参数:require([module],callback).

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 // 定义一个模块--math.js
define(function() {
var add = function(x, y) {
return x + y;
}
return {
add: add
}
//加载方法如下
require(['math'], function(math) {
alert(math.add(1, 1));
})
//如果math模块还依赖其他模块,写法如下:
define(['dependenceModule'], function(dependenceModule) {
// todo
})
  • 当require()函数加载math模块的时候,就会先加载dependenceModule模块。当有多个依赖时,就将所有的依赖都写在define()函数第一个参数数组中,所以说AMD是依赖前置的。这不同于CMD规范,它是依赖就近的。

CMD


CMD与AMD最大的不同就是:CMD推崇依赖就近,延迟执行。可以在代码的任意一行写入依赖:
define(factory)
当factory为函数时,表示是模块的构造方法。
执行该构造方法,可以得到模块向外提供的接口。
factory 方法在执行时,默认会传入三个参数:require、exports 和 module.

AMD与CMD代码对比:

1
2
3
4
5
6
7
8
9
10
11
// CMD
define(function(require, exports, module) {
var a = require('./a');
a.doSomething();
var b = require('./b');
b.doSomething();
})
// AMDdefine(['a', 'b'], function(a, b) {
a.doSomething();
b.doSomething();
})

ES6


ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:export和import.
export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。
ES6还提供了export default命令,为模块指定默认输出,对应的import语句不需要使用大括号.

ES6模块与CommonJS模块差异


  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
liugezhou wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
Enjoy Yourself EveryDay!