ESL内部实现
ESL (Enterprise Standard Loader)
ESL是一个浏览器端、符合AMD的标准加载器,适合用于现代Web浏览器端应用的入口与模块管理。
1 | require(['echarts', 'echarts/chart/line', 'echarts/chart/pie'], dosomething); |
上面代码的执行流程是:
- require创建三个 script 标签’echarts’, ‘echarts/chart/line’, ‘echarts/chart/pie’
- 在上面动态创建的 script 标签中, 注册 onload 事件
onload 方法的实现,则是判断这个三个标签,是否全部加载完毕,当然,必然存在一个文件是最后被加载的,所以这个最后被加载的文件将调用 dosomething 方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20function tryFinishRequire() {
if (typeof callback === 'function' && !isCallbackCalled) {
var isAllCompleted = 1;
each(ids, function (id) {
if (!BUILDIN_MODULE[id]) {
return (isAllCompleted = !!modIs(id, MODULE_DEFINED));
}
});
// 检测并调用callback
if (isAllCompleted) {
isCallbackCalled = 1;
callback.apply(
global,
modGetModulesExports(ids, BUILDIN_MODULE)
);
}
}
}
类型功能的库:RequireJS
require
使用 esl 的 require 可以实现动态加载 js ,例如:
1 | // 在这里可以定义多个 package |
why require?
将js引入到项目中的全局变量进行了屏蔽,js 引入的功能通过变量引入 showLineChart,而不会污染整个页面中的全局变量。
其实这里也存在一个问题,例如 jquery 将导出 $ 和 jQuery 这两个全局变量,如果使用这种方式,加载jquery,将 $ 的功能限制于,其回调函数,这是非常不方便的。
便于升级 require 所加载的库,因为具体的 js 都是由 require 的 packages 来描述的,如果需要升级则修改 location 即可。
对于一个项目来说,通常只需要一个 require.config 即可,所以可以将 require.config 的单独放置到一个 js 当中。每一个具体的页面只需要引用这个js即可,这样当需要升级js时可以直接修改那一个js文件即可。
内部实现
1 | // 2.1.4 |
异步下载
使用 document.createElement
创建一个 script 标签。然后前 src 设置成需要下载的script文件的路径。然后调用 appendChild
将 script 元素添加成 head 标签的子元素。由于设置了 script.async = true
, 所以浏览器将执行异步下载。
1 | // 这个方法被 loadModule 方法调用用来加载 script 文件。 |
模块缓存
1 | /** |
执行回调
require 对名字的解析
调用 toUrl
方法进行名称解析
1 | // toUrl(moduleId + '.js'); |
1 | require(['echarts', 'echarts/chart/line'], dosomething); |
require 对象的初始化
1 | /** |