浅谈AMD/CMD/COMMONJS/ES6模块的区别

504 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

前情提要

其实对于AMD, CMD, COMMONJS模块化早就有所耳闻,可能在实际开发中也用到过,但是对于他们的区别确实模糊不清,跟别人说起他们的区别也是含糊其辞,说的模糊不清。于是便决定总结一篇关于模块化的文章与jym分享,有不对的地方还请jym多多指正。

什么是模块化?

  • 模块化是一种处理复杂系统分解为更好的可管理模块的方式。
  • 模块化是一种开发规范。而所谓的模块化开发指的是将代码中按照功能为单位进行封装,具体到每个模块只实现一个功能的颗粒度,然后提供统一的接口,彼此处于低耦合甚至完全解耦的方式。其存在的意义就是最大化的设计重用,以最少的模块和零部件用最快的速度满足更多的定制化需求。

模块化为什么那么重要?

  • 回想当年的编码方式,基本上都是一个页面一个js文件,不管这页面功能有多少,反正就一股脑的写就完了。
  • 结果造成了一种什么情况呢,功能杂糅在一起,在进行维护或者功能迭代的时候一个小小的功能你可能要找很久很久,结果在外人看来你是能力不行,技术能力有限。这不就BBQ了嘛。
  • 而将杂糅在一起的代码进行解耦,强相关的写在一起,不相关的分隔开,达到高内聚低耦合的模式,以多个js文件的方式实现之后也就实现了最基本的模块化。
  • 由此可见模块的重要性是:
    • 解决代码的可读性
    • 代码或者项目的结构可以更加清晰,定位问题既方便又快速。
    • 提高代码的复用性,总不能每次用到相同或者相似的代码咱们都cv一下对吧。
    • 还有个好处就是解决变量污染的问题。

什么是AMD?

  • AMD的全称是:Asynchronous Module Definition,中文名字的意思是异步模块定义。
  • 解释:顾名思义,它主要是提供基于模块化的异步加载的机制。模块的加载不会阻塞后面代码的执行,而所有依赖该模块的代码都会存放在一个回调当中,当该模块异步加载完毕便会执行该回调中存在的依赖该模块的代码。
  • 方式:通过require的方式进行依赖。但是会接收两个参数,一个是依赖的模块名,一是该模块加载完成后要执行的回调。
  • 实现:而AMD的实现是全局只实现一个方法:define()
    • require引入,define中return暴露接口
    // 实现一个AMD模块化的文件:amd.js
    define(function() {
        return new Date().getTime();
    })
    // 在其他的文件进行依赖: test.js
    const requirejs = require('requirejs')
    requirejs.config({
      path: {
        amd: './amd.js'
      }
    })
    requirejs(['amd'], function(timestamp) {
      console.log(timestamp);
    })
    // 记得使用npm初始化一下项目文件夹,然后安装requirejs
    // 执行npm run xxx<自己定义的命令:具体命令内容可以写:node ./test.js>
    // 最后会打印当前的时间戳
    // 为什么要用requirejs呢,因为如果不使用的话js无法解析define, requirejs([''],fn)
    
  • 代表作:RequireJS
  • 作用端:浏览器

什么是CMD?

  • 全称:Common Module Definition,中文名字意思是:通用模块定义
  • 解释:与AMD类似,但是与之最大的区别是CMD强调的是延迟加载。AMD中要求依赖前置,也就是需要依赖哪个依赖就需要提前写好,然后加载完所有依赖之后才会继续执行接下来的代码。而CMD中要求不要求提前把所有的依赖全部写好,全部加载完再执行,而是可以就近书写,就是哪里用到了依赖只需要在头上引入依赖即可,执行到这里的时候才会进行加载依赖操作。
  • 实现: require引入,module.exports 或者 exorts 暴露接口
  • 代表作:sea.js
  • 作用端:浏览器

什么是COMMONJS?

  • 解释:commonjs是运行时加载,也是同步加载。当运行时会先加载该模块,生成一个对象之后再进行执行下面的代码。
  • 实现:require引入,module.exports暴露接口
  • 代表作:node.js
  • 作用端:服务器

什么是ES6模块?

  • 解释:es6模块是编译时加载,与commonjs不同的是它并不会生成一个对象,而是生成一个对其的引用。commonjs是拷贝,而es6是引用。
  • 实现:import 引入, export 暴露接口
    • 具体代码就不展示,毕竟这种模块化方式我们一直在用。
  • 作用端:浏览器
  • 代表作: