Poon随笔

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

参考:

JavaScript模块化-CommonJS、AMD、CMD、UMD、ES6

前端模块化——彻底搞懂AMD、CMD、ESM和CommonJS

 

在JS早期,使用script标签引入JS,会造成以下问题:

  1. 加载的时候阻塞网页渲染,引入JS越多,阻塞时间越长。
  2. 容易污染全局变量。
  3. js文件存在依赖关系,加载必须有顺序。项目较大时,依赖会错综复杂。
  4. 引入的JS文件过多,不美观,且不易于管理。

NodeJS诞生之后,它使用CommonJS的模块化规范。从此,js模块化开始快速发展。模块化的开发方式可以提供代码复用率,方便进行代码的管理。通常来说,一个文件就是一个模块,有自己的作用域,只向外暴露特定的变量和函数。目前流行的js模块化规范有CommonJS、AMD、CMD、UMD以及ES6的模块系统。

一、CommonJS规范

NodeJS是CommonJS规范的主要实践者,它有四个重要的环境变量为模块化的实现提供支持:moduleexportsrequireglobal。实际使用时,用module.exports定义当前模块对外输出的接口(不推荐直接用exports),用require加载模块。

二、AMD规范

AMD规范采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。

在使用时,需引入require.js,通过require.js实现AMD规范的模块化:用require.config()指定引用路径等,用definde()定义模块,用require()加载模块。

AMD是依赖前置模块。

三、CMD规范

CMD规范同样采用异步方式加载模块,它与AMD很类似,不同点在于:AMD推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行

在使用时,需引入sea.js,通过sea.js实现CMD规范的模块化:1.使用define()定义模块,使用require()加载模块;2.使用seajs.use加载使用模块。

四、UMD规范

UMD(Universal Module Definition)通用模块定义,为了兼容AMD、CMD和无模块化开发规范

/**
 * UMD-Universal Module Definition 通用模块定义
 * */
 (function (root, factory) {
     // 判断是否是AMD/CMD
     if (typeof define === 'function') {
         define([], factory)
     } else if (typeof exports === 'object') {
         // Node CommonJS规范
         module.exports = factory()
     } else {
         // 浏览器环境
         root.someAttr = factory
     }
 })(this, function () {
     let add = function (a, b) {
         return a + b
     }
     return {
         add,
         module: 'UMD'
     }
 })

 

五、ES6模块

ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,旨在成为浏览器和服务器通用的模块解决方案。其模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

六、总结

  1. AMD/CMD/CommonJs 是js模块化开发的规范,对应的实现是require.js/sea.js/Node.js。

  2. CommonJs 主要针对服务端,AMD/CMD/ES Module主要针对浏览器端,容易混淆的是AMD/CMD。(顺便提一下,针对服务器端和针对浏览器端有什么本质的区别呢?服务器端一般采用同步加载文件,也就是说需要某个模块,服务器端便停下来,等待它加载再执行。这里如果有其他后端语言,如java。而浏览器端要保证效率,需要采用异步加载,这就需要一个预处理,提前将所需要的模块文件并行加载好。)

  3. AMD/CMD区别,虽然都是并行加载js文件,但还是有所区别,AMD是预加载,在并行加载js文件同时,还会解析执行该模块(因为还需要执行,所以在加载某个模块前,这个模块的依赖模块需要先加载完成);而CMD是懒加载,虽然会一开始就并行加载js文件,但是不会执行,而是在需要的时候才执行。

  4. AMD/CMD的优缺点.一个的优点就是另一个的缺点, 可以对照浏览。
    AMD优点:加载快速,尤其遇到多个大文件,因为并行解析,所以同一时间可以解析多个文件。
    AMD缺点:并行加载,异步处理,加载顺序不一定,可能会造成一些困扰,甚至为程序埋下大坑。

    CMD优点:因为只有在使用的时候才会解析执行js文件,因此,每个JS文件的执行顺序在代码中是有体现的,是可控的。

    CMD缺点:执行等待时间会叠加。因为每个文件执行时是同步执行(串行执行),因此时间是所有文件解析执行时间之和,尤其在文件较多较大时,这种缺点尤为明显。(PS:重新看这篇文章,发现这里写的不是很准确。确切来说,JS是单线程,所有JS文件执行时间叠加在AMD和CMD中是一样的。但是CMD是使用时执行,没法利用空闲时间,而AMD是文件加载好就执行,往往可以利用一些空闲时间。这么来看,CMD比AMD的优点还是很明显的,毕竟AMD加载好的时候也未必就是JS引擎的空闲时间!)

  5. CommonJS 和 ES Module 区别:CommonJS 模块输出的。是一个值的拷贝,ES6 模块输出的是值的引用。

  6. 如何使用?CommonJs 的话,因为 NodeJS 就是它的实现,所以使用 node 就行,也不用引入其他包。AMD则是通过<script>标签引入require.js,CMD则是引入sea.js。

  7. UMD通用模块定义,为了兼容AMD、CMD和无模块化开发规范。

 

posted on 2023-03-03 13:07  Poon5555  阅读(150)  评论(0编辑  收藏  举报