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

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

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

打包工具就是负责把一些分散的小模块,按照一定的规则整合成一个大模块的工具。与此同时,打包工具也会处理好模块之间的依赖关系,最终这个大模块将可以被运行在合适的平台中。

打包工具会从一个入口文件开始,分析它里面的依赖,并且再进一步地分析依赖中的依赖,不断重复这个过程,直到把这些依赖关系理清挑明为止。

从上面的描述可以看到,打包工具最核心的部分,其实就是处理好模块之间的依赖关系。

为了简单起见,minipack项目直接使用ES modules规范,接下来我们新建三个文件,并且为它们之间建立依赖:

export <span style="color: #0000ff">const name = <span style="color: #800000">'<span style="color: #800000">World<span style="color: #800000">'

import { name } <span style="color: #0000ff">from <span style="color: #800000">'<span style="color: #800000">./name.js<span style="color: #800000">'<span style="color: #000000">

export <span style="color: #0000ff">default hello ${name}!

import message <span style="color: #0000ff">from <span style="color: #800000">'<span style="color: #800000">./message.js<span style="color: #800000">'<span style="color: #000000">

console.log(message)

它们的依赖关系非常简单:entry.js→message.js→name.js,其中entry.js将会成为打包工具的入口文件。

但是,这里面的依赖关系只是我们人类所理解的,如果要让机器也能够理解当中的依赖关系,就需要借助一定的手段了。

依赖关系解析

新建一个js文件,命名为minipack.js,首先引入必要的工具

<span style="color: #0000ff">const fs = require(<span style="color: #800000">'<span style="color: #800000">fs<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">const path = require(<span style="color: #800000">'<span style="color: #800000">path<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">const babylon = require(<span style="color: #800000">'<span style="color: #800000">babylon<span style="color: #800000">'<span style="color: #000000">)
<span style="color: #0000ff">const traverse = require(<span style="color: #800000">'<span style="color: #800000">babel-traverse<span style="color: #800000">').<span style="color: #0000ff">default
<span style="color: #0000ff">const { transformFromAst } = require(<span style="color: #800000">'<span style="color: #800000">babel-core<span style="color: #800000">')

接下来,我们会撰写一个函数,这个函数接收一个文件作为模块,然后读取它里面的内容,分析出其所有的依赖项。当然,我们可以通过正则匹配模块文件里面的import关键字,但这样做非常不优雅,所以我们可以使用babylon这个js解析器把文件内容转化成抽象语法树(AST),直接从AST里面获取我们需要的信息。

得到了AST之后,就可以使用babel-traverse去遍历这棵AST,获取当中关键的“依赖声明”,然后把这些依赖都保存在一个数组当中。

最后使用babel-coretransformFromAst方法搭配babel-preset-env插件,把ES6语法转化成浏览器可以识别的ES5语法,并且为该js模块分配一个ID。

let ID = function createAsset (filename) {
<span style="color: #008000">//<span style="color: #008000"> 读取文件内容
<span style="color: #0000ff">const content = fs.readFileSync(filename,<span style="color: #800000">'<span style="color: #800000">utf-8<span style="color: #800000">'<span style="color: #000000">)

<span style="color: #008000">//<span style="color: #008000"> 转化成AST
<span style="color: #0000ff">const ast =<span style="color: #000000"> babylon.parse(content,{
sourceType: <span style="color: #800000">'<span style="color: #800000">module<span style="color: #800000">'<span style="color: #000000">,});

<span style="color: #008000">//<span style="color: #008000"> 该文件的所有依赖
<span style="color: #0000ff">const dependencies =<span style="color: #000000"> []

<span style="color: #008000">//<span style="color: #008000"> 获取依赖声明
<span style="color: #000000"> traverse(ast,{
ImportDeclaration: ({ node }) =><span style="color: #000000"> {
dependencies.push(node.source.value);
}
})

<span style="color: #008000">//<span style="color: #008000"> 转化ES6语法到ES5
<span style="color: #0000ff">const {code} = transformFromAst(ast,<span style="color: #0000ff">null<span style="color: #000000">,{
presets: [<span style="color: #800000">'<span style="color: #800000">env<span style="color: #800000">'<span style="color: #000000">],})

<span style="color: #008000">//<span style="color: #008000"> 分配ID
<span style="color: #0000ff">const id = ID++

<span style="color: #008000">//<span style="color: #008000"> 返回这个模块
<span style="color: #0000ff">return<span style="color: #000000"> {
id,filename,dependencies,code,}
}

运行createAsset('./example/entry.js'),输出如下:

{ id:

(编辑:新余站长网)

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

推荐文章
    热点阅读