实现最基本的webpack功能
- 打包
- 可配置
- Loader
- Plugin
src
├── config.js # 配置文件
├── example # 示例
│ ├── bar.js
│ ├── changeBundleName.js # 自定义plugin
│ ├── foo.js
│ ├── json-loader.js # 自定义loader
│ ├── main.js # 入口文件
│ ├── sub-dir
│ │ └── baz.js
│ └── test.json # 测试loader的json文件
├── index.js # webpack核心逻辑
└── template # ejs模板
└── index.ejs
在./src/example/
文件夹下是一个简单的示例,其中main.js
是入口文件
模块间的引用关系:
main.js
├── foo.js
│ └── baz.js
└── bar.js
./src/example/
还包含用于处理test.json
的自定义loaderjson-loader.js
# 在./dist/目录下生成打包后的文件bundle.js
yarn build
从入口文件开始,查找并收集依赖赖,放入一个队列,遍历队列中的每个依赖,直到队列为空,然后我们就能获取到所有的依赖内容、依赖之间的关系和相对路径,并根据路径生成依赖图
读取模块内容,使用@babel/parser
将模块内容解析成AST,然后使用@babel/traverse
遍历AST,找到import
语句就找到了每个模块的依赖
将很多模块打包到同一个js文件中,就会出现命名冲突的问题,所以我们需要将每个模块包裹在一个函数中
但这又出现了一个问题,原本模块是使用ESModule的方式引用的,ESModule规范中import
只能出现在模块顶层,不能出现在函数中,所以我们使用@babel/plugin-transform-modules-commonjs
将ESModule转换成CommonJS规范的语法:使用require()
进行导入,使用module.exports
进行导出,为此还要在模板中简单实现require()
和module.exports
的功能
bundle.js
文件中有动态写入的模块代码、依赖关系等,也有静态的require()
等方法,所以我们使用ejs
模板引擎动态生成bundle.js
文件
有了依赖关系、模块代码,我们就可以将每个模块的代码放在函数中,将这些模块合并写入bundle.js