加载流程与缓存策略
语言: English | 中文
本文梳理 bundleRequire 在内部如何打包、落盘与加载,并介绍缓存相关的实用配置。
整体流程
- 解析入口:根据
filepath与cwd生成绝对路径,并用后缀/package.json.type推断format(可手动覆盖)。 - rolldown 打包:
- 固定
platform: 'node'、inlineDynamicImports: true、treeshake: false,保证生成单入口产物并完整收集依赖。 - 注入
__dirname/__filename/import.meta.url,让运行时代码感知源文件真实路径。 - 通过
externalize-deps插件外部化大部分node_modules依赖,同时保留 JSON 内联;尊重module-sync条件导出。
- 固定
- 执行临时产物:
- ESM:写入临时
.mjs/.cjs或 data URL,再用import()加载。 - CJS:通过
_require.extensions临时钩子编译源文件。
- ESM:写入临时
- 结果返回:提供
mod与dependencies(包含入口以外的打包依赖)便于监听或调试。
外部化与解析
- 解析行为与 Vite/rolldown 对齐:使用相同的主字段优先级与
tsconfig路径解析(若未禁用)。 - Node 内置与
node:/npm:命名空间依赖会被直接标记为 external。 - 若依赖处于入口目录下的嵌套
node_modules中,为保证临时产物可执行,会自动内联而非 external。 - JSON 资源暂不外部化,始终交给 rolldown 处理。
临时产物控制
- 默认写入最近的
node_modules/.rolldown-require,找不到时退回系统临时目录;文件名会包含随机哈希,避免并发冲突。 - 通过
getOutputFile可自定义写入路径;preserveTemporaryFile设为true时不会自动清理,便于直接查看产物。 - 若所有落盘尝试失败且目标为 ESM,会回退到
data:URL 写入。
缓存策略
缓存默认关闭。cache: true 或传入对象即可开启,包含持久化与进程内缓存:
- 缓存位置:默认选择最近的
node_modules/.rolldown-require-cache,否则使用os.tmpdir()/rolldown-require-cache。可通过cache.dir指定。 - 缓存键:入口路径、
mtime/size、format、tsconfig路径、Node 版本以及rolldownOptions摘要共同决定。 - 有效性校验:在命中缓存后,会逐个比对入口与依赖的
mtime/size;任意文件变化即视为失效。 - 内存缓存:默认开启(
cache.memory !== false),命中后直接返回已加载模块,避免额外的文件系统读写。 - 重置与事件:
cache.reset: true会在写入前清理旧的 code/meta 文件。cache.onEvent可获取hit/miss/store/skip-invalid事件,skip-invalid的reason可能是missing-entry、format-mismatch、stale-deps等。
示例:记录缓存事件并自定义目录
ts
await bundleRequire({
filepath: './config/vite.config.ts',
cache: {
enabled: true,
dir: './.cache/rolldown-require',
onEvent: (e) => {
console.log(`[cache] ${e.type}`, e)
},
},
})调试建议
- 监听
dependencies,在文件变更后决定是否重新调用bundleRequire。 - 配合
preserveTemporaryFile: true检查生成的临时代码,或在缓存目录里直接比对*.code.mjs/cjs。 - 若需要排查缓存误命中,可临时设置
cache.reset: true或直接关闭缓存。 - 当入口后缀与
package.json.type不匹配时,手动传入format可以避免 Node/rolldown 解析差异。