预加载(Preload)
VextJS 提供了 预加载(Preload) 机制,允许 npm 包声明需要在 Node.js 模块加载之前执行的脚本。vext start / vext dev 会自动发现这些声明,并通过 --import 参数注入到子进程中。
为什么需要预加载?
某些工具(如 OpenTelemetry SDK)必须在应用代码加载之前完成初始化,才能正确 patch Node.js 内置模块(http、net、dns)和第三方库(MongoDB、pg、Redis 等)。
Node.js 的 --import 参数正是为此设计:它确保指定脚本在任何用户代码执行前运行。
手动添加 --import 需要修改启动脚本,增加了配置负担。VextJS 的 preload 机制将这一步自动化——npm 包只需在 package.json 中声明,CLI 自动完成注入。
工作原理
时序图
声明 preload
在 npm 包的 package.json 中添加 vext.preload 字段:
字段格式
路径相对于包根目录(node_modules/<package>/),由 CLI 自动解析为绝对路径。
真实示例
vextjs-opentelemetry 已内置此声明:
安装后,vext start / vext dev 自动注入 --import,OpenTelemetry SDK 在应用启动前完成初始化,MongoDB / pg / Redis 等自动 patch 生效。
适用场景
preload 与 bootstrap config provider 的边界
preload 和 src/config/bootstrap.ts 都发生在应用完全启动前,但职责不同:
推荐做法:
- APM / OpenTelemetry / monkey patch → 用
preload - 远程配置中心 / 启动期数据库配置 → 用
bootstrap config provider - 两者可以配合:preload 先准备 SDK 或 token cache,provider 再读取共享状态产出 patch
三种启动模式
推荐使用
vext start/vext dev,享受自动注入的便利。
Cluster 模式
在 Cluster 模式下,preload 脚本同样生效。CLI 通过 cluster.setupPrimary({ execArgv }) 将 --import 参数传递给所有 Worker 进程:
注意事项
安全行为
- 仅扫描直接依赖:CLI 只读取项目
package.json的dependencies+devDependencies,不递归扫描子依赖 - 文件不存在时跳过:
vext.preload指向的文件不存在时,CLI 输出 warning 并跳过,不阻断启动 - 解析失败时降级:依赖包
package.json解析失败时静默跳过 - 无 preload 包时无影响:没有任何包声明
vext.preload时,CLI 行为与之前完全一致
与手动 --import 共存
CLI 注入的 --import 与用户手动添加的 --import 不冲突。如果同一脚本被注入两次,SDK 内部通常有全局注册保护,不会重复初始化。
开发 preload 脚本的要求
- 脚本必须是 ESM 格式(
--import要求) - 脚本应快速执行,避免阻塞应用启动
- 错误应自行处理(try/catch),不应抛出未捕获异常导致进程退出
编写自定义 preload
如果你正在开发一个需要 preload 的 vext 插件包:
在 package.json 中声明:
构建后,任何使用 vext start / vext dev 的项目安装此包后,preload 脚本会自动执行。
下一步
- 查看 OpenTelemetry 可观测性 了解 preload 的典型应用
- 了解 插件 系统的完整能力
- 探索 Cluster 多进程 模式下的 preload 行为