返回归档

归档 2018

minipack 迷你打包器

以 minipack 迷你打包器理解 webpack 打包核心流程:AST 解析、依赖收集、代码转译与拼接;以及加入 loader 后资源转换如何接入打包链路。

Webpack模块打包必读系列
本文目录3
  1. 基础打包流程
  2. 带 loader 的版本
  3. 与 webpack 的对照

minipack 是 Ronen Amiel 的迷你打包器实现,用几百行代码还原 webpack 的核心打包流程。它不包含 webpack 的工程化外壳(dev server、HMR、代码分割等),只保留"入口 → 依赖图 → 输出 bundle"的主干,是理解模块打包的第一手材料。

基础打包流程

minipack 打包流程

  1. 读取入口文件:接收文件名并读取内容。
  2. 生成 AST:使用 babylon 将源码解析为 AST(abstract syntax tree),使代码可以被程序化分析。
  3. 收集依赖:遍历 AST 找到 import/require 语句,获取依赖文件列表;对每个文件生成 asset 对象,记录它的 id、code 和 dependencies,构建出整张依赖图。
  4. 转译代码:根据 code 使用 preset-env 处理并转义为新的兼容代码,把 import 等 ESM 语法转换成 CommonJS 形式,并将依赖路径替换为 asset id。
  5. 拼接输出:把所有 asset 的转译后代码拼接成新的 JS 代码,通过一个自定义模块加载函数(require + 模块缓存)组织成一个可执行的 bundle。

核心洞察:打包的本质是把"文件间的引用关系"重写为"运行时模块注册表"。所有模块的依赖在编译期收集完毕,运行时只需要按 id 查找和调用。

带 loader 的版本

minipack with loader

在基础流程上接入 loader 后,第 4 步之前多了一层资源转换:

  • 根据 filename 获取匹配到的 loader(webpack 通过 module.rules 的 test 正则匹配文件扩展名)。
  • babel-loader 排在 loader 列表最前面,保证源码先被 babel 转译(语法降级),再进入后续 loader。
  • 使用 loader-runner 包执行匹配到的 loaders,loader 的输出(转换后的 code)继续参与依赖收集与最终拼接。

loader 的本质是"对匹配文件的转换函数":输入文件内容(或上一个 loader 的输出),输出新的内容。这让 webpack 可以对任意资源(JS、CSS、图片、字体)统一做"解析 → 转换 → 打包"。

与 webpack 的对照

minipackwebpack
babylonacorn/parser 等
asset 对象Module + Chunk
自定义 requirewebpack runtime(__webpack_require__
preset-env 转译babel-loader 等
loader-runner 执行 loader同一 loader-runner(webpack 内部复用)

理解了 minipack,再看 webpack 官方文档的打包流程描述(entry → module resolution → loaders → plugin hooks → output)会清晰很多:webpack 只是在这个骨架上加了性能、缓存、代码分割和庞大的插件生态。

返回首页
上一篇loader-runner 执行机制下一篇面试问题示例

Discussion

留言与讨论

想法、补充和不同意见都欢迎。