cmd 是阿里大神玉伯提出的基于浏览器的前端模块化规范,并在 seajs 中实现了这个规范。相对于另一个在国外比较流行的前端模块化规范 amd,cmd 对于 nodejs 的使用者来说更加友好,使得类似 commonJS 模块的写法可以在浏览器中使用,同时解决了浏览器中模块异步加载的困扰。
关于 cmd 更详细的内容可以移步 https://github.com/cmdjs/specification/blob/master/draft/module.md
今天,我们一起来学习如何实现一个浏览器端的简单的 cmd loader。
模块加载流程
下图展示了一个 cmd loader 的模块加载大体流程:
- 首先,通过 use 方法来加载入口模块,并接收一个回调函数, 当模块加载完成, 会调用回调函数,并传入对应的模块。use 方法会 check 模块有没有缓存,如果有,则从缓存中获取模块,如果没有,则创建并加载模块。
- 获取到模块后,模块可能还没有 load 完成,所以需要在模块上绑定一个 “complete” 事件,模块加载完成会触发这个事件,这时候才调用回调函数。
- 创建一个模块时,id就是模块的地址,通过创建 script 标签的方式异步加载模块的代码(factory),factory 加载完成后,会 check factory 中有没有 require 别的子模块:
- 如果有,继续加载其子模块,并在子模块上绑定 “complete” 事件,来触发本身 的 “complete” 事件;
- 如果没有则直接触发本身的 “complete” 事件。
- 如果子模块中还有依赖,则会递归这个过程。
- 通过事件由里到外的传递,当所有依赖的模块都 complete 的时候,最外层的入口模块才会触发 “complete” 事件,use 方法中的回调函数才会被调用。