回顾一下之前的调用流程
现在进入到 rolldown(rust)中的代码后可以看到,Buldler对外主要暴露了write、generate和scan三个方法
impl Bundler {
pub async fn write(&mut self) -> Result<BundleOutput> {}
pub async fn generate(&mut self) -> Result<BundleOutput> {}
pub async fn scan(&mut self) -> Result<ScanStageOutput> {}
}
这里我们主要讲write方法,因为在write的流程中基本都包括了scan和generate的实现。
因为整体流程过于复杂,我曾想一条线走到底,需要描述的内容实在是太多了,接下来我们会采用“大胆假设,小心求证”的方式,先给出全流程,然后根据hooks分段来解释流程。
接下来我们先看看rolldown一直设置了哪些hooks,
- 从plugin的配置里看(packages/rolldown/src/plugin/index.ts)
export interface Plugin {
// --- Build hooks ---
buildStart?: Hook<
(
this: PluginContext,
options: NormalizedInputOptions,
) => MaybePromise<NullValue>
>
resolveId?: Hook<
(
this: PluginContext,
source: string,
importer: string | undefined,
extraOptions: BindingHookResolveIdExtraOptions,
) => MaybePromise<ResolveIdResult>
>
/**
* @deprecated
* This hook is only for rollup plugin compatibility. Please use `resolveId` instead.
*/
resolveDynamicImport?: Hook<
(
this: PluginContext,
source: string,
importer: string | undefined,
) => MaybePromise<ResolveIdResult>
>
load?: Hook<
(
this: PluginContext,
id: string,
) => MaybePromise<
NullValue | string | { code: string; map?: SourceMapInput }
>
>
transform?: Hook<
(
this: TransformPluginContext,
code: string,
id: string,
) => MaybePromise<
| NullValue
| string
| {
code: string
map?: string | null | SourceMapInput
}
>
>
moduleParsed?: Hook<
(this: PluginContext, moduleInfo: ModuleInfo) => MaybePromise<NullValue>
>
buildEnd?: Hook<(this: PluginContext, err?: Error) => MaybePromise<NullValue>>
// --- Generate hooks ---
renderStart?: Hook<
(
this: PluginContext,
outputOptions: NormalizedOutputOptions,
inputOptions: NormalizedInputOptions,
) => MaybePromise<NullValue>
>
renderChunk?: Hook<
(
this: PluginContext,
code: string,
chunk: RenderedChunk,
outputOptions: NormalizedOutputOptions,
) => MaybePromise<
| NullValue
| string
| {
code: string
map?: string | null | SourceMapInput
}
>
>
renderError?: Hook<
(this: PluginContext, error: Error) => MaybePromise<NullValue>
>
generateBundle?: Hook<
(
this: PluginContext,
outputOptions: NormalizedOutputOptions,
bundle: OutputBundle,
isWrite: boolean,
) => MaybePromise<NullValue>
>
writeBundle?: Hook<
(
this: PluginContext,
outputOptions: NormalizedOutputOptions,
bundle: OutputBundle,
) => MaybePromise<NullValue>
>
}
- 从rolldown(rust)中结构体PluginDriver里面看,分成build_hooks和output_hooks
// build_hooks.rs
impl PluginDriver {
pub async fn build_start(&self) -> HookNoopReturn {}
pub async fn resolve_id(&self, args: &HookResolveIdArgs<'_>) -> HookResolveIdReturn {}
// Only for rollup compatibility
pub async fn resolve_dynamic_import(
&self,
args: &HookResolveDynamicImportArgs<'_>,
) -> HookResolveIdReturn {}
pub async fn load(&self, args: &HookLoadArgs<'_>) -> HookLoadReturn {}
pub async fn transform(
&self,
args: &HookTransformArgs<'_>,
sourcemap_chain: &mut Vec<SourceMap>,
original_code: &str,
) -> Result<String> {}
pub async fn module_parsed(&self, module_info: Arc<ModuleInfo>) -> HookNoopReturn {}
pub async fn build_end(&self, args: Option<&HookBuildEndArgs>) -> HookNoopReturn {}
// output_hooks.rs
impl PluginDriver {
pub async fn render_start(&self) -> HookNoopReturn {}
pub async fn render_chunk(
&self,
mut args: HookRenderChunkArgs<'_>,
) -> Result<(String, Vec<SourceMap>)> {}
pub async fn render_error(&self, args: &HookRenderErrorArgs) -> HookNoopReturn {}
pub async fn generate_bundle(&self, bundle: &mut Vec<Output>, is_write: bool) -> HookNoopReturn {}
pub async fn write_bundle(&self, bundle: &mut Vec<Output>) -> HookNoopReturn {}
}
每个hooks都对的上,对比一下rollup的[hooks](Plugin Development | Rollup (rollupjs.org)),也能覆盖大部分的核心hooks了,这边就先抛开rollup,开始看看build hook和generate hooks在rolldown中大概是在什么位置(hook具体的含义可以看rollup的文档)
- Build hooks
- Generate hooks
从方法来看,hooks的分布大致如下:
如果从方法来讲的话模块还是太大了,以后我会从hooks的阶段来讲解整个流程,但是在调试的时候发现hooks并不是按照上图中的顺序执行的,所以我会先假设是按照这个流程来运行的,其中到特殊的例子的时候会再标注出来,然后根据内容的大小看看是否需要对这个特殊例子再来一篇文章。