Configuration
VextJS uses a multi-layer configuration merging mechanism to support configuration overrides by environment, while providing a rich set of built-in configuration items to cover framework behaviors.
Configuration loading mechanism
When the framework starts, config-loader loads configuration files and merges them deeply in the following order:
Each layer can declare only the fields that need to be covered, and undeclared fields are inherited from the previous layer.
Configuration file
Select a config profile explicitly with --config <name> or VEXT_CONFIG=<name>. When omitted, vext start, vext build, and vext deploy assets default to the production profile, while vext dev defaults to the development profile.
Profile names can represent custom deployment environments, for example:
src/config/sg-sit.tssrc/config/us-uat.tssrc/config/us-prod.ts
Pass the profile name at startup:
Vext will be loaded according to the same set of merge links: default -> sg-sit -> local -> bootstrap provider patch -> CLI override.
vext build statically injects process.env.NODE_ENV in user source code as "production", and vext start runs with production runtime mode. Config profile selection is independent and is controlled by --config / VEXT_CONFIG.
Therefore, it is recommended to put the environmental differences into:
src/config/<env>.tssrc/config/bootstrap.ts- Other explicit business environment variables
Instead of relying on the process.env.NODE_ENV conditional branch in the source code after build.
Merge rules
- Object fields: deep merge, the environment file only needs to declare the fields that need to be covered
middlewaresarray: smart patch strategy - match and merge bynameinstead of simply replacing the entire array- Other Arrays: The back layer covers the front layer
bootstrap provider patch: Participate in the same merge / validate / freeze process afterlocal.tsand before CLI override- Final result: deep freeze (
deepFreeze), unmodifiable at runtime
Bootstrap Config Provider
If you need to pull the remote configuration (such as Nacos/Configuration Center/Startup Key Distribution) before finalizing the configuration, you can add src/config/bootstrap.ts:
provider context field:
Constraints:
- provider must return plain object patch or
null - patch only supports JSON-like structure; does not support functions, class instances, and adapter factory
- Default priority:
local < provider < CLI - When
requiredis not declared:productiondefaults to fail-fast,development/testdefaults to continue after warning - In Cluster mode, the Master will pass the current round of provider patches to the Worker for reuse to avoid configuration drift in the same startup cycle.
Configuration file format
Export one object per configuration file using export default:
Middlewares Patch Strategy
The middlewares array uses smart merging, matching by middleware name:
Merged result:
Use Adapter
Native Adapter (http.createServer + route-core) is used by default. To switch to another Adapter, specify the adapter field in the configuration:
When adapter is not specified, Native Adapter is used by default, which has the highest performance and zero framework dependency. Only switch when you need to use the ecology or features of a specific framework.
Frontend configuration (frontend)
frontend controls the built-in browser pipeline. It can be true, false, or an object:
By default spaFallback.scopes is empty, so unknown HTML paths are not swallowed into the SPA. For mixed SSR + client-router sub-apps, declare each basePath in scopes[]. spaFallback: true is kept only as a compatibility shorthand and is not recommended for enterprise mixed projects.
When frontend.deploy.upload is enabled, vext deploy assets reads dist/client/deploy-manifest.json and uploads changed assets by uploadKey and sha256. The built-in filesystem adapter writes files to targetDir, which is useful as a CDN sync staging directory. HTML is still rendered by Vext, and index.html plus **/*.map are excluded from the default deploy manifest.
For creating the app, changing pages, adding components, CSS/JSCSS, assets, API calls, HTML templates, and troubleshooting, see the Frontend guide.
Complete configuration item reference
Basic configuration
CORS configuration (cors)
Rate limiting configuration (rateLimit)
You can override the rate limiting configuration for a specific route in the route's options.override.rateLimit:
Request ID configuration (requestId)
When the request carries the X-Request-Id header, the framework will transparently transmit the ID instead of generating a new one. Suitable for microservice link tracking.
Log configuration (logger)
Supported log levels (from low to high): 'trace' → 'debug' → 'info' → 'warn' → 'error' → 'fatal' → 'silent'
VextJS has a built-in logger kernel with zero runtime dependency, and the pretty mode uses the built-in formatter to output readable logs. The default logger supports trace(), getLevel() / setLevel() and exact key/path redaction; see Log Document for complete description.
Graceful shutdown configuration (shutdown)
After receiving the SIGTERM / SIGINT signal, the framework executes all onClose hooks (such as closing the database connection) in the reverse order of registration, and forcefully exits after timeout.
HTTP Server Configuration (server)
config.server only affects inbound service requests; the timeout for outbound app.fetch / app.fetch.proxy is still controlled by config.fetch.timeout or options when calling.
Response configuration (response)
The response.hideInternalErrors here is aimed at the 500 path of "unknown exceptions", such as throw new Error("...") directly in the code. If you use app.throw(...) to actively throw 404, 409 and other structured HTTP errors, the framework will still return the status code and message you specify, regardless of this configuration.
Actual output of res.json(data) with wrap: true enabled:
Set wrap: false to turn off wrapping, and res.json(data) will output the original data directly.
Body Parser configuration (bodyParser)
maxBodySize supports string formats ('1mb'', '500kb'') and numeric formats (number of bytes).
Multipart / File upload configuration (multipart)
Access Log Configuration (accessLog)
When enabled, each request is automatically logged on completion:
OpenAPI configuration (openapi)
Request context configuration (requestContext)
Disabling requestContext can improve RPS by about 3-8%, but the following features will be disabled:
app.loggerautomatically carriesrequestIdapp.throw()automatically parses the request localeapp.fetchautomatically propagatesrequestId
Consider disabling it only in extreme performance scenarios.
Cluster configuration (cluster)
You can also turn on Cluster mode through the environment variable VEXT_CLUSTER=1 without modifying the configuration file.
Dev mode configuration (dev)
dev configuration items are only read in vext dev development mode, production mode (vext start) automatically ignores all fields.
The Dev error overlay is based on Accept content negotiation, not the HTTP method:
Accept: text/html(Browser address bar GET, HTML form POST) → Return to HTML error pageAccept: application/json(frontend fetch / axios / curl) -> always returns JSON.
Console logging is not affected by overlay - logging configured with logErrors behaves exactly the same whether the response returns HTML or JSON.
Middleware whitelist (middlewares)
Only middleware declared in the whitelist can be referenced in the route's options.middlewares.
Access configuration in code
Routing
In service
In plug-in
app.config is deep-frozen (deepFreeze) after startup and any attempt to modify it will throw a TypeError. This ensures that the configuration is not accidentally modified at runtime.
Custom configuration fields
The VextConfig interface allows extending custom fields. Plug-ins and business code can add arbitrary fields in the configuration:
Use with declare module to get type hints:
Environment variables
In addition to configuration files, some settings can also be controlled through environment variables:
:::warning Security Tips Do not hardcode sensitive information (such as database passwords, API Keys) in configuration files. Recommended:
- Use environment variable:
process.env.DB_PASSWORD - Use
local.ts(added.gitignore) to store sensitive configurations for local development :::
Configuration verification
config-loader will perform Fail Fast verification after the merge is completed, checking the following:- port must be a positive integer in the range 1-65535
adaptermust be a known built-in identifier or a valid adapter object/function- Each element in the
middlewaresarray must be a string or a{ name: string }object rateLimit.maxmust be a positive integerrateLimit.windowmust be a positive integerlogger.levelmust be a legal log levellogger.redactKeys/logger.redactPathsmust be a string array,logger.redactValuemust be a stringshutdown.timeoutmust be a non-negative number (unit: seconds)server.requestTimeout,server.headersTimeout,server.keepAliveTimeout,server.socketTimeoutmust be non-negative finite numbers (unit: milliseconds)server.maxHeaderSize,server.connectionsCheckingIntervalmust be positive integers,server.maxRequestsPerSocketmust be non-negative integerscluster.workersmust be a positive integer or'auto'/'auto-1'
If the verification fails, the framework will report an error immediately at startup and give a clear error message to avoid configuration errors being exposed at runtime.
Complete example
Next step
- Understand the detailed configuration and switching methods of Adapter Architecture
- Learn how to configure whitelist in Middleware
- See OpenAPI Documentation for advanced configuration
- Explore configuration options for Cluster Multiprocess