乘着周日有点时间,阅读一下玉伯大神的源码。
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。