Rolldown 插件钩子深度解析:augmentChunkHash 的用法与底层哈希原理

发布时间:2026/9/15 17:57:02
Rolldown 插件钩子深度解析:augmentChunkHash 的用法与底层哈希原理 Rolldown 插件钩子深度解析augmentChunkHash 的用法与底层哈希原理【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown本篇技术指南聚焦 Rolldown基于 Rust 实现、提供 Rollup 兼容 API 的 JavaScript/TypeScript bundler的输出生成钩子augmentChunkHash它能够在生成阶段为单个 chunk注入额外的哈希来源从而精确控制输出文件名的内容哈希。读完本文你将掌握该钩子的完整签名与返回值语义、它在多个插件间如何合并执行以及它如何进入 Rolldown 的最终文件名哈希计算链路含源码级证据可直接用于构建缓存失效、版本号注入等实战场景。钩子定位输出生成阶段Output Generation Hooks的同步顺序钩子augmentChunkHash是 Rolldown 在生成generate阶段提供的输出类钩子。其 TypeScript 定义位于 packages/rolldown/src/plugin/index.ts文档注释给出了三条核心契约/** * Can be used to augment the hash of individual chunks. Called for each Rolldown output chunk. * * Returning a falsy value will not modify the hash. * Truthy values will be used as an additional source for hash calculation. * * kind sync sequential * group Output Generation Hooks */ [DEFINED_HOOK_NAMES.augmentChunkHash]: ( this: PluginContext, chunk: RenderedChunk, ) string | void;对每个输出 chunk 调用一次只要最终产物中存在 chunk该钩子就会被依次触发返回值语义明确返回 falsy 值如undefined/null/表示不修改哈希返回 truthy 字符串则作为哈希计算的附加来源additional source同步顺序执行sync sequential钩子不是并行调用多个插件按注册顺序逐个执行返回值会按序参与后续拼接下文详述。在底层绑定层N-API/WASI 绑定类型 packages/rolldown/src/binding.d.cts中它的签名被声明为(ctx, chunk) MaybePromisevoid | string与上层定义保持一致。最小可运行示例让指定 chunk 的文件名哈希随构建失效关联文档 plugin-hooks-augmentchunkhash.md 给出了该钩子的典型用法——通过注入当前时间戳让名为foo的 chunk 每次构建的文件哈希都发生变化适用于不希望浏览器缓存复用旧产物的场景function augmentWithDatePlugin() { return { name: augment-with-date, augmentChunkHash(chunkInfo) { if (chunkInfo.name foo) { return Date.now().toString(); } }, }; }逐行拆解这个示例augmentChunkHash(chunkInfo)接收一个与 Rollup 兼容的RenderedChunk对象其中chunkInfo.name即该 chunk 的名称对应output.entryFileNames/output.chunkFileNames中通过name约定的命名if (chunkInfo.name foo)是常见的定向失效写法——只对特定 chunk 生效其余 chunk 保持原有哈希不变return Date.now().toString()返回一个随时间变化的字符串由于它是 truthy 值Rolldown 会将其纳入该 chunk 的哈希计算。当函数没有显式返回即返回undefined时该 chunk 的哈希不受影响。该插件通常与文件名模板中的[hash]占位符配合使用例如entryFileNames: [name]-[hash].js因为augmentChunkHash改变的是哈希计算来源最终会反映到[hash]替换结果上。返回值语义falsy 不生效truthy 即附加哈希源根据 packages/rolldown/src/plugin/index.ts 的定义返回值分为两类返回值行为undefined/null/等 falsy 值不修改该 chunk 的哈希非空字符串truthy作为哈希计算的附加来源参与最终哈希计算实践中常见的 truthy 返回物包括时间戳 / 构建序号Date.now().toString()、自增计数器强制每次构建变更哈希如文档示例环境变量或版本号从process.env.BUILD_ID、process.env.npm_package_version等读取使同一版本号下哈希稳定、版本变更时哈希失效外部文件内容摘要读取独立配置文件如package.json版本字段作为哈希来源实现配置变更才失效的精确缓存控制。需要注意augmentChunkHash与renderChunk的职责不同renderChunk可以改写 chunk 的代码与 sourcemap而augmentChunkHash只影响哈希计算来源不修改产物内容因此适合在不改动代码的前提下人为调整文件名哈希。执行流程从 JS 插件到 Rust 驱动的完整调用链augmentChunkHash属于典型的JS 定义、Rust 驱动插件钩子其执行链路贯穿两层1. JS 侧钩子绑定与参数转换在 packages/rolldown/src/plugin/bindingify-output-hooks.ts 中JS 插件对象被转换为底层绑定可调用的形式export function bindingifyAugmentChunkHash( args: BindingifyPluginArgs, ): PluginHookWithBindingExtBindingPluginOptions[augmentChunkHash] { return bindingifyHook(args.plugin.augmentChunkHash, ({ handler }) ({ plugin: async (ctx, chunk) { return handler.call(createPluginContext(args, ctx), transformRenderedChunk(chunk)); }, })); }其中transformRenderedChunk负责把底层的 chunk 表示转换为上层 JS 可见的RenderedChunk结构包含name、fileName等字段createPluginContext则构造钩子执行时的this插件上下文。此外packages/rolldown/src/plugin/generated/hook-usage.ts 显示只要插件定义了augmentChunkHash就会在钩子用量位标记HookUsageKind.augmentChunkHash 1 10中置位供底层做钩子使用情况的快速判定。2. Rust 侧顺序遍历与返回值拼接核心驱动逻辑位于 crates/rolldown_plugin/src/plugin_driver/output_hooks.rspub async fn augment_chunk_hash( self, chunk: ArcRollupRenderedChunk, ) - HookAugmentChunkHashReturn { let mut hash None; for (_, plugin, ctx) in self.iter_plugin_with_context_by_order(self.order_by_augment_chunk_hash_meta) { let result plugin.call_augment_chunk_hash(ctx, Arc::clone(chunk)).await; if let Some(plugin_hash) result.with_context(|| CausedPlugin::new(plugin.call_name()))? { hash.get_or_insert_with(String::default).push_str(plugin_hash); } } Ok(hash) }按order_by_augment_chunk_hash_meta定义的顺序遍历所有插件多个插件返回值按执行顺序直接拼接push_str而不是取第一个非空值最终返回ResultOptionString即所有插件贡献的哈希串拼接结果若所有插件都未返回则为None。插件基类的默认实现位于 crates/rolldown_plugin/src/plugin.rs直接返回Ok(None)因此未定义该钩子的插件不影响结果。3. 聚合调度仅对 ECMAScript chunk 生效在生成阶段crates/rolldown/src/utils/augment_chunk_hash.rs 负责把插件结果写入每个待定稿的 chunkif let InstantiationKind::Ecma(ecma_meta) asset.kind { let augment_chunk_hash plugin_driver.augment_chunk_hash(Arc::clone(ecma_meta.rendered_chunk)).await?; if let Some(augment_chunk_hash) augment_chunk_hash { asset.augment_chunk_hash Some(augment_chunk_hash); } }它通过try_join_all并行处理所有已实例化的 chunk但只对InstantiationKind::EcmaECMAScript 输出类型的 chunk 调用该钩子其他类型如纯二进制/资源类输出不会触发。4. 调用时机该聚合函数在 crates/rolldown/src/stages/generate_stage/render_chunk_to_assets.rs 中被调用位于 chunk 渲染完成之后、文件名哈希定稿finalize之前从而保证钩子返回值能赶在最终哈希计算前生效。源码视角augmentChunkHash 如何进入最终文件名哈希augmentChunkHash的返回值最终沉淀在 crates/rolldown_common/src/types/instantiated_chunk.rs 的InstantiatedChunk.augment_chunk_hash: OptionString字段上。真正的哈希计算发生在 crates/rolldown/src/utils/chunk/finalize_chunks.rslet mut hash match chunk.content { /* ... 先基于 chunk 内容计算 standalone content hash ... */ }; if let Some(augment_chunk_hash) chunk.augment_chunk_hash { hash.push_str(augment_chunk_hash); hash xxhash_base64_url(hash.as_bytes()); } hash关键结论均由源码确认先内容、后增强首先基于 chunk 渲染后的代码内容计算出一个独立内容哈希index_standalone_content_hashes再把augmentChunkHash的返回值追加到该哈希串末尾并重新进行一次xxhash_base64_url摘要影响最终文件名该哈希随后参与传递依赖闭包计算finalize_chunks.rs最终用于替换文件名模板中的[hash]占位符finalize_chunks.rs因此augmentChunkHash的变化会直接改变对应产物文件的输出文件名对依赖 chunk 的传导由于最终哈希会哈希整个传递依赖闭包中每个 chunk 的独立内容哈希改变某个 chunk 的 augment 哈希也会传导到依赖它的 chunk这一点与内容哈希的传播行为一致。实战注意事项与最佳实践基于上述实现在使用augmentChunkHash时建议注意配合[hash]占位符才有意义该钩子影响的是哈希计算来源产物文件名模板entryFileNames/chunkFileNames中必须包含[hash]改动才会体现在输出文件名上保持钩子轻量它是sync sequential的同步顺序钩子虽然底层经MaybePromise桥接仍应避免在其中执行重计算或异步 IO以免拖慢生成阶段善用条件判断定向失效像文档示例那样通过chunkInfo.name等字段过滤只对目标 chunk 注入哈希来源避免全局哈希频繁变动导致缓存全部失效理解多插件拼接规则多个插件都返回 truthy 时返回值按插件顺序拼接后再参与哈希因此插件顺序会影响最终哈希结果排查哈希意外变动时可先检查是否多个插件同时注入了值返回值应具备确定性或明确的失效意图若返回时间戳则每次构建哈希必然变化强制刷新缓存若返回版本号/配置摘要则仅在相关内容变更时失效。请根据缓存策略选择合适的注入内容。如果你需要控制产物的缓存失效粒度或者希望在不改动 chunk 内容的前提下调整其文件名哈希augmentChunkHash就是 Rolldown 提供的标准入口——从本文的调用链与哈希算法可以看到它已被完整地纳入 Rolldown 生成阶段的哈希定稿流程中。【免费下载链接】rolldownFast Rust bundler for JavaScript/TypeScript with Rollup-compatible API.项目地址: https://gitcode.com/GitHub_Trending/ro/rolldown创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询