RsPack 采用 js + rust 来编写,期望在最大化兼容 webpack 配置的基础上对 rust 的高性能兼而有之,其实就目前前列的 vite 与 turbopack 而言,打包编译的速度其实不分伯仲,只有在特别大量的文件打包时才能显现出 rust 的优势,不过 RsPack 作为一次新的尝试,也有很多可以借鉴的,于是便有了这一系列文章。
rspack 源码结构如下:
图中主要的代码部分为以 js 编写的 packages 文件夹以及以 rust 编写的 crates 文件夹
- packages 文件夹主要负责 环境检测、整体流程控制等,以 tabaple 进行流程控制
- crates 文件夹主要进行 编译、打包 等大运算量操作
这么看为什么不全部使用 rust 进行编写,而要拆开进行,源码阅读、编写、调试的难度都增大了
主要在 rspack 与 rspack-cli 中
rspack-cli 作为 rspack-cli 工具的运行入口提供了 RspackCLI 类
构造函数中 使用了
- colorette 美化输出
- yargs 构建交互式命令行 (yargs不完全指南)
- semver 版本号识别(在运行时会检测 nodejs 的版本,需要最少在 14.0.0 以上)
运行时会注册 两个 命令
- BuildCommand
- ServerCommand
使用了
- @discoveryjs/json-ext 加强 JSON
调用 createCompiler 方法
- 默认
process.env.RSPACK_CONFIG_VALIDATE = "loose" - loadConfig
- buildConfig
- 调用 rspack 返回 compiler
- compiler.run
compiler
- rspackOptionsCheck -> revalidateWithStrategy
- createCompiler 创建 compiler
- 如果 option.watch 为 true 则开启 watchOptions 中文件的监控
- compiler.run
createCompiler
- getNormalizedRspackOptions
- applyRspackOptionsBaseDefaults
- Compiler 创建 compiler
- NodeEnvironmentPlugin 注册插件
- 批量注册用户插件
- applyRspackOptionsDefaults
- 调用 compiler.hooks.environment.call
- 调用 compiler.hooks.afterEnvironment.call
- RspackOptionsApply
- 调用 compiler.hooks.initialize.call
- compiler.run
Compiler 类中所有勾子
hooks: {
done: tapable.AsyncSeriesHook<Stats>;
afterDone: tapable.SyncHook<Stats>;
// TODO: CompilationParams
compilation: tapable.SyncHook<Compilation>;
// TODO: CompilationParams
thisCompilation: tapable.SyncHook<[Compilation, CompilationParams]>;
invalid: tapable.SyncHook<[string | null, number]>;
compile: tapable.SyncHook<[any]>;
initialize: tapable.SyncHook<[]>;
infrastructureLog: tapable.SyncBailHook<[string, string, any[]], true>;
beforeRun: tapable.AsyncSeriesHook<[Compiler]>;
run: tapable.AsyncSeriesHook<[Compiler]>;
emit: tapable.AsyncSeriesHook<[Compilation]>;
afterEmit: tapable.AsyncSeriesHook<[Compilation]>;
failed: tapable.SyncHook<[Error]>;
watchRun: tapable.AsyncSeriesHook<[Compiler]>;
watchClose: tapable.SyncHook<[]>;
environment: tapable.SyncHook<[]>;
afterEnvironment: tapable.SyncHook<[]>;
afterPlugins: tapable.SyncHook<[Compiler]>;
afterResolvers: tapable.SyncHook<[Compiler]>;
make: tapable.AsyncParallelHook<[Compilation]>;
};
run
- 开始编译计时
- 标记编译开始
this.running = true - 触发 beforeRun
- 触发 run
- 调用 build
- 记录结束时间
- 触发 done
- 标记编译结束
- 调用回掉函数
- 触发 afterdone
build
- 引入 unsafe 的 rust 代码,同时将上下文传递给 rust 函数,进行编译操作
以上是 js 侧的主要流程,主要是进行了插件的注册、配置的初始化、编译流的初始化、搭建 devServer 等