Preload
VextJS provides the Preload mechanism, allowing the following two types of sources to execute scripts before the Node.js module is loaded:
- Dependency package declaration: npm package declares
vext.preloadinpackage.json - Project-level directory:
preload/in the root directory of the application project
vext start / vext dev will automatically discover these declarations and inject them into the child process via the --import parameter.
Why do we need to preload?
Some tools, such as the OpenTelemetry SDK, must be initialized before the application code is loaded in order to correctly patch Node.js built-in modules (http, net, dns) and third-party libraries (MongoDB, pg, Redis, etc.).
Node.js's --import parameter is designed for exactly this: it ensures that the specified script is run before any user code is executed.
Manually adding --import requires modifying the startup script, which increases the configuration burden. VextJS’s preload mechanism automates this step:
- The plug-in package only needs to declare
vext.preloadinpackage.json - The application project only needs to create the
preload/directory in the project root
The CLI will automatically complete the injection.
Starting from
v0.3.6, application projects no longer need to package a local npm package for preload. Just create thepreload/directory in the project root.
Working principle
Timing diagram
Statement preload
Method A: Project-level preload/ directory
Create in the application project root directory:
First term rules:
Supported file types
It is recommended to use
.mjs/.mtsfirst, which has the clearest semantics.
How TypeScript preload works
If the project-level preload/ directory contains .ts / .mts files, the CLI will use esbuild to compile them to:
For example:
The purpose of this is to ensure that: without modifying the vext build main compilation chain:
vext devvext start-Cluster worker
The preload behavior of the three links is consistent.
Behavior under vext dev
Project-level preload belongs to execution logic before startup. Therefore, when files in preload/ are added/modified/deleted:
vext devwill listen to this directory- and trigger cold restart uniformly
This ensures that the results are consistent with manual restarts and avoids "the preload has changed but the development server still uses the old injection results".
Method B: Dependency package vext.preload
Add the vext.preload field in the package.json of the npm package:
Field format
Paths are relative to the package root (node_modules/<package>/) and are automatically resolved to absolute paths by the CLI.
Real example
vextjs-opentelemetry has this declaration built in:
After installation, vext start / vext dev automatically injects --import, OpenTelemetry SDK completes initialization before the application starts, and automatic patches such as MongoDB / pg / Redis take effect.
Applicable scenarios
The boundary between preload and bootstrap config providerpreload and src/config/bootstrap.ts both occur before the application is fully started, but have different responsibilities:
Recommended practices:
- APM/OpenTelemetry/monkey patch → use
preload - Bridge environment variables to bootstrap provider before starting → You can also use
preload - Remote configuration center / database configuration main chain during startup → Use
bootstrap config provider - The two can cooperate: preload first prepares the SDK, token cache or environment variables, and the provider then reads these statuses and outputs the patch.
Three startup modes
It is recommended to use
vext start/vext devto enjoy the convenience of automatic injection.
Cluster mode
In Cluster mode, the preload script also takes effect. The CLI passes the --import argument to all Worker processes via cluster.setupPrimary({ execArgv }):
Notes
Safe Behavior
- The project-level directory is a controlled single directory: Only the project root
preload/is recognized, and any directory is not scanned recursively. - Only scan direct dependencies: CLI only reads the
dependencies+devDependenciesof the projectpackage.json, and does not recursively scan sub-dependencies - Skip when the file does not exist: When the file pointed to by
vext.preloaddoes not exist, the CLI will output a warning and skip it, without blocking startup. - Downgrade when parsing fails: The dependent package
package.jsonis silently skipped when parsing fails. - fail-fast when project-level TS preload compilation fails: avoid bringing obviously unexecutable TS preload into the running phase
- No impact when there is no preload declaration: When there is no project-level directory or package-level preload declaration, the CLI behavior is exactly the same as before.
Coexists with manual --import
CLI-injected --import does not conflict with --import manually added by the user. If the same script is injected twice, there is usually global registration protection inside the SDK and it will not be initialized repeatedly.
Suggestions for developing preload scripts
- Scripts should be executed quickly to avoid blocking application startup
- If it is
.js/.ts, please make sure the project adopts ESM semantics ("type": "module") - Errors should be handled by yourself; in the case of TS preload, syntax compilation errors will directly interrupt the startup
Deployment boundaries
If you are using project-level preload/:
vext buildwill compile the project rootpreload/todist/preload/.ts/.mts/.js/.mjswill all be uniformly output into.mjsfiles that can be directly--import- Therefore, when deploying in production, you usually only need to carry:
- Project root
package.json dist/(which already containsdist/preload/, if used)
- Project root
vext start will give priority to reading the project root preload/; if the directory does not exist in the root directory, it will automatically fall back to reading dist/preload/.
Write custom preload
Write project-level preload
Write package-level preload
If you are developing a vext plugin package that requires preload:
Declare in package.json:
After building, any project using vext start / vext dev will have the preload script automatically executed after installing this package.
Next step
- See OpenTelemetry Observability for typical applications of preload
- Understand the full capabilities of the plugins system
- Explore preload behavior in Cluster multi-process mode