javascript - requireJS为何不会多次加载同一个文件?怎么理解内部机制?
本文介绍了javascript - requireJS为何不会多次加载同一个文件?怎么理解内部机制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
问 题
文件目录如下:
root-|index.html
|require.js
|main.js
|jquery.min.js
|math.js
index.html:
<head>
<script type="text/javascript" src="require.js" data-main="main" defer async="true"></script>
</head>
main.js:
require.config({
paths: {
"jquery": "jquery.min",
"math": "math"
}
});
require(['jquery','math'], function ($,math){
console.log('main');
});
math.js:
define(['jquery'],function($){
console.log('math');
var add = function(a,b){
return a+b;
};
return{
add: add
};
});
在浏览器的Network可以看到加载js的情况:
疑问:
main.js模块依赖了jquery模块和math模块,由于异步我视为开了两个线程;第二个math线程又依赖了jquery模块,为何没有再一次请求该资源?requireJS内部机制是怎样的?
解决方案
如果你有时间去看看 sea 或者 requirejs 的源码就能明白,其实原理并不复杂。
如果没有显式的指定名称,你的源文件路径(含目录和文件名)就是模块的名称。当然它内部会进行一些处理,使名称能唯一对应一个模块的定义。
那么模块的定义是一个 function
,这个 function
实际是一个 factory(工厂模式,不明白的话就去搜下),这个 factory 在需要使用的时候(require("xxxx") 的时候)才有可能会被调用。为什么是有可能?因为如果检查到已经调用过,已经生成了模块实例,就直接返回模块实例,而不再次调用工厂方法了。
这个过程大概是这样的(非常简化的,只是个示意,加载和依赖都忽略了,想了解详情自己去看源码)
class Module {
constructor(name, factory) {
this.name = name;
this.factory = factory;
this.instance = null;
}
}
// 非常简化的 define 方法(不要问我依赖的问题)
function define(factory) {
const name = ""; // 根据源码路径之类的来计算
// allModules 是框架维护的一个模块字典
allModules[name] = new Module(name, factory);
}
// 非常简化的 require 方法
function require(name) {
const module = allModules[name];
if (!module.instance) {
const moduleInst = { exports: {} };
// 如果 factory 有返回值就用返回值赋给 module.instance
// 否则就用 moduleInst 赋给它
module.instance = module.factory(moduleInst.exports, moduleInst) || moduleInst;
}
return module.instance;
}
对于加载的外部模块也说,也是一样的。尤其是像 jQuery 这些,在写源码的时候已经考虑了兼容 AMD 的问题,所以可以很好的用于 requirejs 依赖加载。
这篇关于javascript - requireJS为何不会多次加载同一个文件?怎么理解内部机制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文