第一阶段 : 无模块化
说明:
简单的将所有的js文件统统放在一起。但是这些文件的顺序还不能出错,比如jquery需要先引入,才能引入jquery插件,才能在其他的文件中使用jquery。
使用方法:
缺点:
- 污染全局作用域。 因为每一个模块都是暴露在全局的,简单的使用,会导致全局变量命名冲突,当然,我们也可以使用命名空间的方式来解决。
- 对于大型项目,各种js很多,开发人员必须手动解决模块和代码库的依赖关系,后期维护成本较高。
- 依赖关系不明显,不利于维护。 比如main.js需要使用jquery,但是,从上面的文件中,我们是看不出来的,如果jquery忘记了,那么就会报错。
第二阶段: CommonJS规范
说明:
CommonJS就是一个JavaScript模块化的规范。
- 每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。
- 核心思想:
- 通过 require 方法来同步加载所要依赖的其他模块,
- 通过 module.exports 来导出需要暴露的接口
使用方法:
优点:
在服务器端率先完成了JavaScript的模块化,解决了依赖、全局变量污染的问题,这也是js运行在服务器端的必要条件
缺点:
- CommonJS 是同步加载模块的,只有加载完成,才能执行后面的操作
- 由于 CommonJS 是同步加载模块的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以,CommonJS是不适用于浏览器端的。
第三阶段: AMD规范
说明:
- 非同步加载模块,允许指定回调函数。因此浏览器端一般采用AMD规范。
- AMD规范的实现:require.js
- 定义模块:define(id, [depends], callback)
第一个参数 id 为字符串类型,表示了模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。如果存在,那么模块标识必须为顶层的或者一个绝对的标识。
第二个参数,dependencies ,是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。
第三个参数,factory,是一个需要进行实例化的函数或者一个对象。
- 加载模块:require([module], callback) 支持CommonJS的模块导出方式
使用方法:
优点:
- 适合在浏览器环境中异步加载模块。
- 可以并行加载多个模块。
缺点:
- 提高了开发成本
- 不能按需加载,而是必须提前加载所有的依赖
第四阶段: CMD规范
说明:
和requirejs非常类似,即一个js文件就是一个模块,但是CMD的加载方式更加优秀,是通过按需加载的方式。\
使用方法:
优点:
- 实现了浏览器端的模块化加载。
- 可以按需加载,依赖就近。
缺点:
依赖SPM打包,模块的加载逻辑偏重。
特殊存在: UMD规范
背景:
Modules/Wrappings是出于对NodeJS模块格式的偏好而包装下使其在浏览器中得以实现, 而且它的格式通过某些工具(如 )也能运行在NodeJS中。事实上,这两种格式同时有效且都被广泛使用。
AMD以浏览器为第一(browser-first)的原则发展,选择异步加载模块。它的模块支持对象(objects)、函数(functions)、构造器(constructors)、字符串(strings)、JSON等各种类型的模块。因此在浏览器中它非常灵活。
CommonJS以服务器端为第一(server-first)的原则发展,选择同步加载模块。它的模块是无需包装的(unwrapped modules)且贴近于ES.next/Harmony的模块格式。但它仅支持对象类型(objects)模块。
这迫使一些人又想出另一个更通用格式 (Universal Module Definition)。希望提供一个前后端跨平台的解决方案。
说明:
UMD的实现很简单,先判断是否支持NodeJS模块格式(exports是否存在),存在则使用NodeJS模块格式。
再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。前两个都不存在,则将模块公开的全局(window或global)。
第五阶段:ES6模块化(推荐使用)
说明:
- ES6的模块化方案是真正的规范
- 使用:
- 引入模块:使用 import
- 导出模块:通过 exprot
- 目前无法在浏览器中执行,需通过babel将不被支持的import编译为当前受到广泛支持的 require
使用方法:
优点:
和requir区别不大,但是推荐使用ES6,毕竟官方
缺点:
ES6目前无法在浏览器中执行,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require
无模块化 | CommonJS规范 | AMD规范 | CMD规范 | ES6模块化 | |
适用 | 服务端 | 浏览器端 | 浏览器端 | 浏览器端 | |
加载方式 | 同步加载 | 异步加载、 模块开始加载所有依赖 | 按需加载 | ||
实现库 | requireJs | seajs | |||
来源 | 前端社区 | 前端社区 | 前端社区 | 官方 | |
是否需要bebal编译 | 否 | 否 | 否 | 否 | 是 |
AMD和CMD的区别
- AMD 对于依赖的模块提前执行, CMD延迟执行
- AMD 推崇依赖前置, CMD推崇依赖就近,即只在需要用到某个模块的时候再require
参考资料: