你知道webpack是如何分析模块各个依赖关系的?是如何将ES6代码编译成浏览器可执行代码的吗?
项目初始化
- 创建文件夹
1 | mkdir bundler |
- 创建相关文件
在bundler中创建src文件夹,在src文件夹新建index.js,message.js,word.js。文件内容如下:
1 | // word.js |
如果想直接在浏览器中运行index.js的话,当然是不能的,浏览器无法识别es6的语法,以前我们都是通过类似webpack的打包工具将es6代码转换成es5的代码,然后直接在浏览器中运行。
入口文件依赖分析
在项目根目录下新建一个bundler文件,实现打包过程。其实所谓的webpack编译打包就是通过一些特定的方法函数将源代码转换成浏览器可识别的代码
定义一个模块分析函数
1
2
3
4const moduleAnalyser=(filename)=>{
}
moduleAnalyser("./src/index.js");// 入口函数读取文件内容
这里使用了node中的一个核心模块fs。
1 | const fs=require("fs"); |
在终端中执行node命令
1 | node bundler.js |
就会输出index.js的文件内容
- 解析文件依赖
(1)执行npm init -y初始化
(2)安装一个babel模块
1 | npm install @babel/parser --save |
(3)使用parser
1 | const fs=require("fs"); |
再次执行node命令,node bundler.js,查看文件内容,输出的就是常说的AST,描述了文件的相关依赖关系。
修改一下bundler
1 | ... |
执行node bundler.js命令就会得到如下输出内容
输出的就是文件相关依赖,type为ImportDeclaration表示是引入声明,type为ExpressionStatement表示是表达式。接下来要做的就是遍历body的内容得到依赖关系。
(4)安装模块
1 | npm install @babel/traverse --save |
(5)使用traverse
1 | ... |
继续改写bundler.js
1 | const dependencies=[]; |
继续改写bundler.js
1 | const dependencies={};// 变成对象,key是依赖路径,value是相对依赖路径。便于之后使用 |
(6)安装babel/core转换代码
1 | npm install @babel/core @babel/preset-env --save |
(7)转换代码
1 | const { code }=babel.transformFromAst(ast,null,{ |
执行node bundler.js命令就会得到如下输出内容
入口文件的依赖分析就完成了。完整代码如下:
1 | const fs=require("fs"); |
构建依赖图谱
一个项目不可能只有一个文件,这就需要我们分析整个项目的依赖关系,即生成得到依赖图谱。
- 定义生成依赖图谱方法
1 | const makeDependenciesGraph=(entry)=>{ |
- 从入口开始,循环递归分析依赖关系
1 | const makeDependenciesGraph=(entry)=>{ |
执行node bundler.js命令就会得到如下输出内容
- 生成依赖图谱graph对象,完整代码如下:
1 | const makeDependenciesGraph=(entry)=>{ |
生成浏览器可识别代码
1 | const generateCode=(entry)=>{ |
执行node bundler.js命令就会得到如下输出内容
将输入内容拷贝后到浏览器console中执行,便会得到代码的正常输出
bundler文件完整代码:
1 | const fs=require("fs"); |
以上就是一个webpack代码转换编译的整个过程。继续学习中!