各种模块化简介及演变过程

 
第一阶段 : 无模块化

 
说明:
简单的将所有的js文件统统放在一起。但是这些文件的顺序还不能出错,比如jquery需要先引入,才能引入jquery插件,才能在其他的文件中使用jquery。
 
使用方法:
 
缺点:
  • 污染全局作用域。 因为每一个模块都是暴露在全局的,简单的使用,会导致全局变量命名冲突,当然,我们也可以使用命名空间的方式来解决。
  • 对于大型项目,各种js很多,开发人员必须手动解决模块和代码库的依赖关系,后期维护成本较高。
  • 依赖关系不明显,不利于维护。 比如main.js需要使用jquery,但是,从上面的文件中,我们是看不出来的,如果jquery忘记了,那么就会报错。
 
 
第二阶段: CommonJS规范

 
说明:
CommonJS就是一个JavaScript模块化的规范。
  • 每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。
  • 核心思想:
  1. 通过 require 方法来同步加载所要依赖的其他模块,
  2. 通过 module.exports 来导出需要暴露的接口
 
使用方法:
 
优点:
在服务器端率先完成了JavaScript的模块化,解决了依赖、全局变量污染的问题,这也是js运行在服务器端的必要条件
 
缺点:
  • CommonJS 是同步加载模块的,只有加载完成,才能执行后面的操作
  • 由于 CommonJS 是同步加载模块的,在服务器端,文件都是保存在硬盘上,所以同步加载没有问题,但是对于浏览器端,需要将文件从服务器端请求过来,那么同步加载就不适用了,所以,CommonJS是不适用于浏览器端的。
 
 
第三阶段: AMD规范

说明:
  • 非同步加载模块,允许指定回调函数。因此浏览器端一般采用AMD规范。
  • AMD规范的实现:require.js
  1. 定义模块:define(id, [depends], callback)
第一个参数 id 为字符串类型,表示了模块标识,为可选参数。若不存在则模块标识应该默认定义为在加载器中被请求脚本的标识。如果存在,那么模块标识必须为顶层的或者一个绝对的标识。
第二个参数,dependencies ,是一个当前模块依赖的,已被模块定义的模块标识的数组字面量。
第三个参数,factory,是一个需要进行实例化的函数或者一个对象。
  1. 加载模块:require([module], callback) 支持CommonJS的模块导出方式
 
使用方法:
 
优点:
  • 适合在浏览器环境中异步加载模块。
  • 可以并行加载多个模块。
 
缺点:
  • 提高了开发成本
  • 不能按需加载,而是必须提前加载所有的依赖
 
 
第四阶段: CMD规范

说明:
和requirejs非常类似,即一个js文件就是一个模块,但是CMD的加载方式更加优秀,是通过按需加载的方式。
 
使用方法:
 
优点:
  • 实现了浏览器端的模块化加载。
  • 可以按需加载,依赖就近。
 
缺点:
  依赖SPM打包,模块的加载逻辑偏重。 
 
 
特殊存在: UMD规范

背景:
Modules/Wrappings是出于对NodeJS模块格式的偏好而包装下使其在浏览器中得以实现, 而且它的格式通过某些工具(如r.js)也能运行在NodeJS中。事实上,这两种格式同时有效且都被广泛使用。
AMD以浏览器为第一(browser-first)的原则发展,选择异步加载模块。它的模块支持对象(objects)、函数(functions)、构造器(constructors)、字符串(strings)、JSON等各种类型的模块。因此在浏览器中它非常灵活。
CommonJS以服务器端为第一(server-first)的原则发展,选择同步加载模块。它的模块是无需包装的(unwrapped modules)且贴近于ES.next/Harmony的模块格式。但它仅支持对象类型(objects)模块。 
这迫使一些人又想出另一个更通用格式 UMD(Universal Module Definition)。希望提供一个前后端跨平台的解决方案。
 
说明:
UMD的实现很简单,先判断是否支持NodeJS模块格式(exports是否存在),存在则使用NodeJS模块格式。
再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。前两个都不存在,则将模块公开的全局(window或global)。
 
第五阶段:ES6模块化(推荐使用)

说明:
  • ES6的模块化方案是真正的规范
  • 使用:
  1. 引入模块:使用 import
  2. 导出模块:通过 exprot
  • 目前无法在浏览器中执行,需通过babel将不被支持的import编译为当前受到广泛支持的 require
 
使用方法:
 
优点:
和requir区别不大,但是推荐使用ES6,毕竟官方
 
缺点:
  ES6目前无法在浏览器中执行,所以,我们只能通过babel将不被支持的import编译为当前受到广泛支持的 require 
 
 
 
 
无模块化
CommonJS规范
AMD规范
CMD规范
ES6模块化
适用
 
服务端
浏览器端
浏览器端
浏览器端
加载方式
 
同步加载
异步加载、
模块开始加载所有依赖
按需加载
 
实现库
   
requireJs
seajs
 
来源
 
前端社区
前端社区
前端社区
官方
是否需要bebal编译
 
 
AMD和CMD的区别

  1. AMD 对于依赖的模块提前执行, CMD延迟执行
  2. AMD 推崇依赖前置, CMD推崇依赖就近,即只在需要用到某个模块的时候再require
参考资料:

原文地址:https://www.cnblogs.com/ailsa-qin/p/8494219.html