加入收藏 | 设为首页 | 会员中心 | 我要投稿 新余站长网 (https://www.0790zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 资源网站 > 资源 > 正文

打包工具的核心原理(转自:https://juejin.im/entry/5b223ebd51

发布时间:2020-12-24 13:54:44 所属栏目:资源 来源:网络整理
导读:打包工具就是负责把一些分散的小模块,按照一定的规则整合成一个大模块的工具。与此同时,打包工具也会处理好模块之间的依赖关系,最终这个大模块将可以被运行在合适的平台中。 打包工具会从一个入口文件开始,分析它里面的依赖,并且再进一步地分析依赖中的

可见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 () {})(),手动定义moduleexportsrequire变量,最后实现代码在浏览器运行的目的。

接下来就是依据这个规范,通过字符串拼接去构建代码块。

= 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"&gt;return</span><span style="color: #000000"&gt; require(mapping[name]);
    }

    </span><span style="color: #0000ff"&gt;const</span> module =<span style="color: #000000"&gt; { exports : {} };

    fn(localRequire,module.exports);

    </span><span style="color: #0000ff"&gt;return</span><span style="color: #000000"&gt; module.exports;
  }

  require(</span><span style="color: #800080"&gt;0</span><span style="color: #000000"&gt;);
})({${modules}})

`
<span style="color: #0000ff">return<span style="color: #000000"> result
}

(编辑:新余站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

推荐文章
    热点阅读