js开发者对js模块加载的尝试和创新从来都没有停止过,尤其是当nodejs的出现后,模块化加载的必要性更加凸显。本文不讨论如何在nodejs环境来模块化加载(创造者已经利用commonJS机制解决),只讨论在浏览器环境下如何来模块加载的思路,并提出一些我的看法。

浏览器环境与nodejs的环境的最大差异是,对于nodejs的环境,大多数情况下被依赖的模块文件本身就在本地(它们都在服务器上),同步取过来就能用;而对于浏览器的环境,被依赖的模块文件通常还在远程服务器上,并未加载到本地,也就是说必须是先加载(并解析)后执行的机制。

既然已经有了commonJS,在这之上将异步回调的逻辑加入进去,可是异步先加载什么呢?于是就有了依赖的概念。一段时间的发展后,有了AMD、和CMD的解决方案,代表作品是requirejs和seajs,有兴趣的读者可以去了解一下,这里就不展开介绍了。
有必要简单提一下两者的主要区别,CMD推崇依赖就近,可以把依赖写进你的代码中的任意一行,例:

1
2
3
4
5
6
define(function(require, exports, module) {
  var a = require('./a')
  a.doSomething()
  var b = require('./b')
  b.doSomething()
})

代码在运行时,首先是不知道依赖的,需要遍历所有的require关键字,找出后面的依赖。具体做法是将function toString后,用正则匹配出require关键字后面的依赖。显然,这是一种牺牲性能来换取更多开发便利的方法。

而AMD是依赖前置的,换句话说,在解析和执行当前模块之前,模块作者必须指明当前模块所依赖的模块,表现在require函数的调用结构上为:

1
2
3
4
define(['./a','./b'],function(a,b){
   a.doSomething()
   b.doSomething()
})

代码在一旦运行到此处,能立即知晓依赖。而无需遍历整个函数体找到它的依赖,因此性能有所提升,缺点就是开发者必须显式得指明依赖——这会使得开发工作量变大,比如:当你写到函数体内部几百上千行的时候,忽然发现需要增加一个依赖,你不得不回到函数顶端来将这个依赖添加进数组。

细心的读者可能发现,到目前位置我讨论的AMD和CMD的思想的关于依赖的部分,都只讨论的“硬依赖”,也就是执行前肯定需要的依赖,但是这不是全部的情况。有的时候情况是这样的:

1
2
3
4
// 函数体内:
if(status){
  a.doSomething()
}

在这个函数体内,可能依赖a,也可能不依赖a,我把这种可能的依赖成为“软依赖”。对于软依赖当然可以直接当硬依赖处理,但是这样不经济,因为依赖是不一定的,有可能加载了此处的依赖而实际上没有用上。
对于软依赖的处理,我推荐依赖前置+回调函数的实现形式。上面的例子简单表述如下:

1
2
3
4
5
6
// 函数体内:
if(status){
  async(['a'],function(a){
    a.doSomething()
  })
}

至此可以对由commonJS衍生出来的方案做出总结了。在浏览器端来设计模块加载机制,需要考虑依赖的问题。
我们先把依赖分为两种,“强依赖” —— 肯定需要 和“弱依赖” —— 可能需要。
对于强依赖,如果要性能优先,则考虑参照依赖前置的思想设计你的模块加载器,我个人也更推崇这个方案一些;如果考虑开发成本优先,则考虑按照依赖就近的思想设计你的模块加载器。
对于弱依赖,只需要将弱依赖的部分改写到回调函数内即可。
如果现在我要实现一个模块加载器,我会将强依赖前置,弱依赖采用异步回调函数的形式,其它的方法我认为都只是语法糖而已,仅此就够了。

AMD vs. CommonJS?的更多相关文章

  1. AMD/CMD/CommonJs到底是什么?它们有什么区别?

    知识点1:AMD/CMD/CommonJs是JS模块化开发的标准,目前对应的实现是RequireJs/SeaJs/nodeJs.   知识点2:CommonJs主要针对服务端,AMD/CMD主要针对浏 ...

  2. [译]前端JS面试题汇总 Part 1(事件委托/this关键字/原型链/AMD与CommonJS/自执行函数)

    原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questio ...

  3. JS模块之AMD, CMD, CommonJS、UMD和ES6模块

    CommonJS 传送门 同步加载,适合服务器开发,node实现了commonJS.module.exports和require 判断commonJS环境的方式是(参考jquery源码): if ( ...

  4. AMD,CMD.CommonJs和UMD还有es6的模块化对比

    CommonJS CommonJS是服务器端模块的规范,Node.js采用了这个规范. 根据CommonJS规范,一个单独的文件就是一个模块.加载模块使用require方法,该方法读取一个文件并执行, ...

  5. FW: AMD, CMD, CommonJS和UMD

    javascript 我是豆腐不是渣 4月5日发布 推荐 2 推荐 收藏 32 收藏,486 浏览 今天由于项目中引入的echarts的文件太大,requirejs经常加载超时,不得不分开来加载ech ...

  6. AMD, CMD, CommonJS和UMD

    我的Github(https://github.com/tonyzheng1990/tonyzheng1990.github.io/issues),欢迎star 今天由于项目中引入的echarts的文 ...

  7. js模块系统 - amd|cmd|commonjs|esm|umd

    写过前端代码大概率听说过amd cmd umd commonjs esm这些名词, 想当初我第一次看到这些的时候, 人都麻了, 都是些啥啊. 后来我知道了, 这些都是js的模块规范. amd - 浏览 ...

  8. [转载]AMD 的 CommonJS wrapping

    https://www.imququ.com/post/amd-simplified-commonjs-wrapping.html 它是什么? 为了复用已有的 CommonJS 模块,AMD 规定了 ...

  9. 【转】AMD 的 CommonJS wrapping

    其实本文的标题应该是「为什么我不推荐使用 AMD 的 Simplified CommonJS wrapping」,但太长了不好看,为了美观我只能砍掉一截. 它是什么? 为了复用已有的 CommonJS ...

随机推荐

  1. java 局部变量成员变量区别

    首先,成员变量可直接初始化(即赋值),也可不赋值,不赋值java按照以下类型自动赋值 局部变量调用前必须初始化(赋值),java不会自动处理 局部变量可以和成员变量重名(但不建议),如果在当前对象的方 ...

  2. linux_密钥

    使用密钥文件.       这里假设主机A(192.168.100.3)用来获到主机B(192.168.100.4)的文件.   在主机A上执行如下命令来生成配对密钥: ssh-keygen -t r ...

  3. 存储型XSS的发现经历和一点绕过思路

    再次骚扰 某SRC提现额度竟然最低是两千,而已经有750的我不甘心呐,这不得把这2000拿出来嘛. 之后我就疯狂的挖这个站,偶然发现了一个之前没挖出来的点,还有个存储型XSS! 刚开始来到这个之前挖过 ...

  4. ctpn+crnn 训练数据集生成

    1. https://github.com/Belval/TextRecognitionDataGenerator 2. https://textrecognitiondatagenerator.re ...

  5. 2019年 iPad无法充电

    2019年 iPad无法充电  到售后网点检测没毛病,可能是apple产品做了低温保护逻辑机制低温无法充电,或者说是冬天温度跟iPad电池充电温度要求不符.各位有遇到情况的可以看看是不是这种问题,这问 ...

  6. 大转盘(CocosCreator)

    推荐阅读:  我的CSDN  我的博客园  QQ群:704621321 1.在场景中搭建大转盘场景,假设 奖项有n项,对应的每项旋转角度如下: 第几项 需要旋转的角度 0 360/n/2 1 360/ ...

  7. Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III)

    Leetcode之回溯法专题-216. 组合总和 III(Combination Sum III) 同类题目: Leetcode之回溯法专题-39. 组合总数(Combination Sum) Lee ...

  8. 红黑树以及与AVL树的区别

    http://blog.csdn.net/zwan0518/article/details/12219055 http://blog.csdn.net/v_july_v/article/details ...

  9. Windows Server - SVN 服务器搭建与项目配置、客户端安装与配置

    本教程以Windows Server 2012 R12 为例搭建SVN服务器,安装部署完成后,客户端可通过SVN客户端访问SVN服务器上的项目,也可以访问网上其他SVN服务器上的项目. 一.首先准备三 ...

  10. [企业微信通知系列]Jenkins发布后自动通知

    一.前言 最近使用Jenkins进行自动化部署,但是部署后,并没有相应的通知,虽然有邮件发送通知,但是发现邮件会受限于接收方的接收设置,导致不能及时看到相关的发布内容.而由于公司使用的是企业微信,因此 ...