seajs源码阅读

乘着周日有点时间,阅读一下玉伯大神的源码。

seajs的源码写得真的很好,很是佩服,工整美观不愧是大神,造福百姓。

说起seajs不得不说,AMD和CMD的区别。

 CMD 推崇依赖就近,AMD 推崇依赖前置。
 
事实上我对他们的区别没啥兴趣。关键是requirejs没明显的BUG,seajs明显没BUG。
 
两者最大区别请看这里:http://www.cnblogs.com/gyjWEB/p/4543945.html
 
好了,扯正题。
 
可以先看看别人写的源码解析:https://segmentfault.com/a/1190000000471722
 
我只补上模块的加载过程.首先,弄个简单的DEMO。
 
<!DOCTYPE html>
<html>
<head>
    <title>seajs源码阅读</title>
</head>
<body>
    <script src="seajs-2.2.3/dist/sea-debug.js"></script>
    <script>
        seajs.use("./application",function(){
        })
    </script>
</body>
</html>

很简单的代码,使用application.js做主文件.下面是application.js源码.

define(function(require,exports,module){
    var test = require('ModuleTest');
});

application.js只依赖了ModuleTest.

seajs.use为入口.会先预加载,然后再调用Module.use.

seajs.use = function(ids, callback) {
  //预加载,预加载的模块可以通过seajs.config设置
  Module.preload(function() {
    //开始了
    Module.use(ids, callback, data.cwd + "_use_" + cid())
  })
  return seajs
}

Module.use的代码很关键.一开始会创建一个模块就叫做入口模块吧,这个模块是没有id的,而且这个模块会依赖主模块,更关键的是,这个入口模块有callback,其他模块是没有callback。

Module.use = function (ids, callback, uri) {
  var mod = Module.get(uri, isArray(ids) ? ids : [ids])
  //模块回调,加载完了之后就执行
  mod.callback = function() {
    //......
  }
  //加载模块
  mod.load()
}

入口模块的callback,最终会在Module.prototype.onload调用

Module.prototype.onload,不得不扯Module.prototype.load.下面是load的流程.

大体流程:

demo中:

会创建入口模块,设置入口模块的callback,加载入口模块。

由于入口模块依赖了"application模块",就会fetch "application模块",fetch成功就会调用"application模块"中的define。

define会算出"application模块"的依赖,也就是"ModuleTest模块",然后回到load,继续fetch "ModuleTest模块"。

继续回到"ModuleTest模块"的load,这时候“ModuleTest模块”的remain为0,就会调用"ModuleTest模块"的onload,然后根据waittings调用"application模块"的onload。

最后就是入口模块的onload.最后的最后,所有的模块exec。KO。

吃完饭,再弄张图,千言万语不如一张图。

原文地址:https://www.cnblogs.com/geilishu/p/5248321.html