前言
此文是require.js源码分析系列的文章,之所以会分析require.js,原因如下:
- 面试时会被问到相关知识点,但是在工作中没有使用require.js
- 想要加深对于AMD规范的理解
- require.js是异步加载js文件,对其内部的实现思想想要一窥究竟
本系列文章着重于require.js的如下两点:
- require.js中异步加载js文件的实现
- require.js是如何处理依赖列表以及循环依赖的问题
require.js流程分析
require.js源码的分析,打算从require.js的加载开始,逐渐分析整个过程。
require.js在html中引用方式如下:
<script src="require.js" data-main="config.js"></script>
src指向require.js文件路径
data-main指向require.config({})配置文件
data-main指向的config.js文件中代码如下:
require.config({
baseUrl: './'
});
当浏览器解析script标签之后,就开始加载require.js。
通过分析require.js源码,require.js加载流程如下图所示:
注:图中星号部分表示关键点
从上图中的流程中,可以知道如下信息:
- require.js通过定义三个全局变量requirejs、require、define,作为对外暴露的api,也就是使用require.js的功能:define定义AMD规范模块,require加载模块
- !require 等于 true,require、req、requirejs等价
- 在require.js加载过程中调用了两次require函数,分别是req({})以及req(cfg),第一次传入空对象{},第二次传入cfg对象,该对象便是配置对象,就是require.config中的参数对象
在require.js中主要的处理有:
req({}),data-main的处理、req(cfg)、req(config)
req({})以及req(cfg)就是require函数功能,此文是一系列分析讲解,此文只专注加载过程中处理,req以及define都会单独讲解,此处就不展开,主要讲解data-main的处理。
data-main的处理代码如下:
if (isBrowser && !cfg.skipDataMain) {
eachReverse(scripts(), function (script) {
// 相关处理代码
});
}
不会展示过多的代码,因为会影响主要点的阅读,这里是处理data-main属性的地方。
我在加载过程中打印cfg对象的内容,cfg对象的内容如下:
从上面可见我在config.js配置的对象就是cfg对象
data-main处理
data-main的处理是一段同步语句,阅读源码得到它的流程如下:
从上面的处理流程中可以得知 cfg对象deps至少会有一个值,那就是data-main的属性值。
require.j加载过程中的执行流程大概就是如此,下面总结下执行流程中主要几点:
- 定义require、requirejs、define对外API
- req({})
- data-main处理
- req(cfg)
- req(config)
接下来会分析req({})的过程,即require({})内部到底做了哪些处理。