复习webpack4之实现简易的webpack

以前学习过webpack3的知识,可是webpack4升级后仍是有不少变更的,因此此次从新整理一下webpack4的知识点,方便之后复习。node

此次学习webpack4不只仅要会配置,记住核心API,最好还要理解一下webpack更深层次的知识,好比打包原理等等,因此可能会省略一些比较基础的内容,可是但愿我能够经过这次学习掌握webpack,更好地应对之后的工做。webpack

这一节会深刻理解webpack原理git

1.模块分析

咱们这一次会实现一个相似webpack的工具,首先来写模块分析部分。github

代码地址:web

代码仓库npm

先把目录搭好,src下有三个js文件,每一个文件里面对应如下内容:数组

word.js浏览器

message.jsbash

index.jsbabel

如今这个代码在浏览器中是没有办法运行的,须要借助相似webpack这种工具才能够,因此咱们须要借助node.js实现一个打包工具。

和src同级,咱们新建一个bundler.js。

建立一个函数,用来分析打包入口文件,支持传入一个参数(文件路径),而后利用node读取文件内容。

而index中引用了message.js,咱们须要把引用的文件名提取出来,要借助@babel/parser分析咱们的源代码。

cnpm install @babel/parser --save
复制代码

@babel/parser提供了一个parse方法,第一个参数传入文件内容,第二个参数传一个对象。

方法返回的对象是一个抽象语法树(AST)。

对象里面有一个program.body,内容是这样的:

第一个Node的type是ImportDeclaration,意思是引入声明语句,咱们index.js中第一行确实是引入语句。第二个Node的type是ExpressionStatement,意思是表达式语句,咱们第二行写的console.log(),确实是表达式语句。因此借助这个工具,咱们就能够分析文件之间的依赖关系。

为了找出全部的依赖关系,咱们要遍历全部type是ImportDeclaration的语句,本身写会比较麻烦,还能够借助@babel/traverse

cnpm install --save @babel/traverse
复制代码

traverse是一个函数,第一个参数接受抽象语法树,第二个参数是一个对象。

抽象语法树中有元素的type是ImportDeclaration时,就会执行ImportDeclaration函数,它接受的参数能够解构出一个node,它就是全部type是ImportDeclaration的元素,就是咱们全部的依赖,里面哟一个source,value值就是文件名,因此咱们就能够把全部文件名都存起来

声明一个数组,把全部node中的soure.value都push到数组中。

这样入口分析就已经分析好了,可是这时候分析的依赖都是相对路径,咱们要把它改成绝对路径,或者是相对于根路径的相对路径,这样才不会有问题,因此要借助node中的path。

可是咱们为了方便之后开发,如今应该把绝对路径和相对路径都存好,因此把原先的数组变成对象,用如下方法存起来。

对象的key是相对路径,value是绝对路径。

而后就返回入口文件名,和文件全部依赖的内容。

可是咱们用的ES Module引入文件,浏览器没法识别这个语法,就要依赖@babel/core。

cnpm install --save @babel/core
复制代码

@babel/core提供了一个方法,transformFromAst,能够把抽象语法树转化成浏览器能够运行的代码。

传入的参数中还能够配置ES6转ES5的插件,因此要先安装一下@babel/preset-env。

cnpm install --save @babel/preset-env
复制代码

函数会返回一个对象,里面有一个code属性,code属性中就是咱们浏览器能够运行的代码。

最后返回咱们分析的结果。

返回的结果意思是:入口文件是index.js;引用的依赖是message.js,地址是src/message.js;浏览器中能够运行的代码是code中的内容。

2.依赖图谱

咱们如今只分析了入口文件的依赖,接下来咱们要开始分析其余依赖,从message开始,一层一层把全部依赖都分析完。

咱们再建立一个函数,用来制做依赖图谱,利用相似递归的方式,调用moduleAnalyser逐层分析依赖内容,并把它们都放到一个数组中。

最后生成的数组。

而后咱们把它整合成一个对象,用路径做为key,依赖和代码做为value,而且返回这个对象。

对象的内容。

3.生成代码

拿到依赖图谱,如今要开始生成浏览器能够运行的代码了。

先看生成的代码中,存在require和exports两个方法,可是浏览器中没有这两个方法,因此咱们要先定义这两个方法,而后把生成的代码片断利用闭包的形式执行。

require函数中,经过传入路径拿到对应的代码,利用eval()执行,若是require中有依赖,继续执行require时拿到的就是相对路径,须要转成绝对路径,直接去咱们以前建立的对象中取就能够。

exports是一个空对象便可,这样导出的内容会被存到exports中。

而后把生成的代码格式化一下,复制到浏览器中执行。

就打印出say hello了。

这样,咱们就已经实现了一个简易的webpack打包工具了,具体代码能够去个人github仓库里面看。

参考

从基础到实战 手把手带你掌握新版Webpack4.0 ----DellLee
相关文章
相关标签/搜索