30分钟 带你浅入requirejs源码
因为最近项目想现实一个单页功能,用的是react ,然后看了一下react route,挖槽 gzip后16k? 然后我简单写了一个纯单页(不支持多页的单页,所有入口都经过rewrite跑到index.html) 才200多行(后续放github)。
然后项目是用webpack打包的, 发现webpack的 require.ensure不支持变量加载的(至少暂时没发现), 就是意味着我有多小页面,就得在main(入口里配多小页面的关系) 这样挫,领导会喷我的。
然后我今天早上起来,想看看requirejs是如何现实的
好前戏完毕 直入主题,大家都知道requrejs 有一个data-main 配置 , 顾名思义就是 入口 类似c,java的main函数
main.js
require.config({ paths: { 'xm': 'xm', 'adb': 'db' }, waitSeconds: 50 }) requirejs(['xm', 'adb'], function(xm, db) { console.log(xm, 'main'); db.db(); });
然后定义了2个文件 ,分别是xm.js 和db.js
//xm.js define([], function() { return { name: 'xm', age: 22 } });
//db.js define(['xm'], function(xm){ return { db: function(){ var who = xm.name; console.log(who, ' play'); } } })
首先,我们把代码叠起来, 一览众山小
可以看到,其实requirejs 很简单, 只有3个api(按我的理解, 有错请指正)
1、requirejs, 引入定义的模块,并执行callback的代码
2、require,只引入,不执行
3、define,定义一个模块
然后具体看实现的地方
前面1000多行都是 内部调用的 function的实现,例如判断函数啊, 是否数组啊,遍历,反向遍历 etc.. ,太细节 就不多说了

着重看看后面的req变量的实现, 本来想加些标注的, 但是发现 每行都是重点, 正如小时候老师让我们画重点,经常半页书都画上, 不如不画了 囧。
1、这里requirejs 就是上面说到的1的实现
2、config其实就是一系列的配置,例如base路径,path(配短名字), urlArgs(问号后加时间戳之类的),shim(没有用define声明的模块,全局注入) etc..
3、nextTick 其实就是一个定时器, 按你代码 加入的模块,逐个依次 创建script标签 引入到页面
4、然后 引入require的时候,他会默认加了一个版本,默认初始化(注意这行 req({}) ), 默认错误提示等等
5、define函数的实现
好,有了上面已经知道require大概有些什么了, 然后来一起看看某几个重要的细节点。
首先代码里先看看data-main这个关键词 ,其实就是遍历所有的TagName为script的,找到data-main, 然后处理了一下路径
然后最后一行,其实才是真正的main入口初始化

然后第一次require会根据配了的data-main 以下列处理后,通过req.load 自动引入main.js

第一次自动调用requirejs 内容基本都是默认值,没啥好看的, 来 一起看看我们main.js 里主动调用的requrejs、
然后 继续跟下去 发现最后调用了Module的有个each,然后是会调用自己的fetch,load进行一个一个按顺序像main加载步骤一样 加载
因为时间原因,有些太细的点就不深入一一步析 希望此文对初了解requirejs的同学有所帮助,谢谢观看完毕。
</div>