可见entry.js 文件已经变成了一个典型的模块,且依赖已经被分析出来了。接下来我们就要递归这个过程,把“依赖中的依赖”也都分析出来,也就是下一节要讨论的建立依赖关系图集。
建立依赖关系图集
新建一个名为createGragh() 的函数,传入一个入口文件的路径作为参数,然后通过createAsset() 解析这个文件使之定义成一个模块。
接下来,为了能够挨个挨个地对模块进行依赖分析,所以我们维护一个数组,首先把第一个模块传进去并进行分析。当这个模块被分析出还有其他依赖模块的时候,就把这些依赖模块也放进数组中,然后继续分析这些新加进去的模块,直到把所有的依赖以及“依赖中的依赖”都完全分析出来。
与此同时,我们有必要为模块新建一个mapping 属性,用来储存模块、依赖、依赖ID之间的依赖关系,例如“ID为0的A模块依赖于ID为2的B模块和ID为3的C模块”就可以表示成下面这个样子:
: [function A () {},{ : ,:
搞清楚了个中道理,就可以开始编写函数了。
mainAsset =<span style="color: #008000">//<span style="color: #008000"> 维护一个数组,传入第一个模块
<span style="color: #0000ff">const queue =<span style="color: #000000"> [mainAsset]
<span style="color: #008000">//<span style="color: #008000"> 遍历数组,分析每一个模块是否还有其它依赖,若有则把依赖模块推进数组
<span style="color: #0000ff">for (<span style="color: #0000ff">const<span style="color: #000000"> asset of queue) {
asset.mapping =<span style="color: #000000"> {}
<span style="color: #008000">//<span style="color: #008000"> 由于依赖的路径是相对于当前模块,所以要把相对路径都处理为绝对路径
<span style="color: #0000ff">const dirname =<span style="color: #000000"> path.dirname(asset.filename)
<span style="color: #008000">//<span style="color: #008000"> 遍历当前模块的依赖项并继续分析
asset.dependencies.forEach(relativePath =><span style="color: #000000"> {
<span style="color: #008000">//<span style="color: #008000"> 构造绝对路径
<span style="color: #0000ff">const absolutePath =<span style="color: #000000"> path.join(dirname,relativePath)
<span style="color: #008000">//<span style="color: #008000"> 生成依赖模块
<span style="color: #0000ff">const child =<span style="color: #000000"> createAsset(absolutePath)
<span style="color: #008000">//<span style="color: #008000"> 把依赖关系写入模块的mapping当中
asset.mapping[relativePath] =<span style="color: #000000"> child.id
<span style="color: #008000">//<span style="color: #008000"> 把这个依赖模块也推入到queue数组中,以便继续对其进行以来分析
<span style="color: #000000"> queue.push(child)
})
}
<span style="color: #008000">//<span style="color: #008000"> 最后返回这个queue,也就是依赖关系图集
<span style="color: #0000ff">return<span style="color: #000000"> queue
}
尝试运行一下createGraph('./example/entry.js') ,就能够看到如下的输出:
[ { id: : :
现在依赖关系图集已经构建完成了,接下来就是把它们打包成一个单独的,可直接运行的文件啦!
进行打包
上一步生成的依赖关系图集,接下来将通过CommomJS 规范来实现加载。由于篇幅关系,本文不对CommomJS 规范进行扩展,有兴趣的读者可以参考@阮一峰 老师的一篇文章,说得非常清晰。简单来说,就是通过构造一个立即执行函数(function () {})() ,手动定义module ,exports 和require 变量,最后实现代码在浏览器运行的目的。
接下来就是依据这个规范,通过字符串拼接去构建代码块。
= graph.forEach(mod =><span style="color: #000000"> {
modules +=<span style="color: #000000"> ${mod.id}: [ function (require,module,exports) { ${mod.code} },${JSON.stringify(mod.mapping)},],
})
<span style="color: #0000ff">const result =<span style="color: #000000"> `
(function(modules) {
function require(id) {
<span style="color: #0000ff">const [fn,mapping] =<span style="color: #000000"> modules[id];
function localRequire(name) {
</span><span style="color: #0000ff">return</span><span style="color: #000000"> require(mapping[name]);
}
</span><span style="color: #0000ff">const</span> module =<span style="color: #000000"> { exports : {} };
fn(localRequire,module.exports);
</span><span style="color: #0000ff">return</span><span style="color: #000000"> module.exports;
}
require(</span><span style="color: #800080">0</span><span style="color: #000000">);
})({${modules}})
`
<span style="color: #0000ff">return<span style="color: #000000"> result
} (编辑:衡阳站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|