配置
VextJS 采用 多层配置合并 机制,支持按环境覆盖配置,同时提供丰富的内置配置项覆盖框架行为。
配置加载机制
框架启动时,config-loader 按以下顺序加载配置文件并深度合并:
运行时合并允许后层只声明需要覆盖的字段。TypeScript 则有意区分项目基础配置与后层 patch:default.ts 使用 VextUserConfig,环境 profile 与 local 配置文件使用 VextConfigOverride,createTestApp() 采用同一覆盖合同。bootstrap provider 继续使用 JSON-like Record<string, unknown> patch,并由现有运行时校验。
配置文件
配置 profile 通过 --config <name> 或 VEXT_CONFIG=<name> 显式选择。未指定时,vext start、vext build、vext deploy assets 默认使用 production profile,vext dev 默认使用 development profile。
profile 名可以是自定义部署环境名,例如:
src/config/sg-sit.tssrc/config/us-uat.tssrc/config/us-prod.ts
启动时传入 profile 名:
Vext 就会按同一套合并链路加载:default -> sg-sit -> local -> bootstrap provider patch -> CLI override。
vext build 会将用户源码中的 process.env.NODE_ENV 静态注入为 "production",vext start 运行时也会使用 production runtime mode。配置 profile 是独立概念,由 --config / VEXT_CONFIG 决定。
因此,推荐把环境差异放进:
src/config/<env>.tssrc/config/bootstrap.ts- 其他显式业务环境变量
而不是依赖 build 后源码中的 process.env.NODE_ENV 条件分支。
合并规则
- 对象字段:深度合并(deep merge),环境文件只需声明需要覆盖的字段
middlewares数组:智能 patch 策略——按name匹配并合并,而非简单替换整个数组- 其他数组:后层覆盖前层
bootstrap provider patch:在local.ts之后、CLI override 之前参与同一套 merge / validate / freeze 流程- 最终结果:深冻结(
deepFreeze),运行时不可修改
TypeScript 基础配置与覆盖层
- 基础配置(
default.ts):使用VextUserConfig。它的顶层字段可选,但一旦写出某个嵌套对象,该对象不会自动变成深度可选。例如default.ts中的database必须满足完整MonSQLizeDatabaseConfig,包括必填的连接config。 - 覆盖层:
development.ts、production.ts、自定义 profile 与local.ts使用VextConfigOverride。它与运行时深度合并一致,后层可以只 patchdatabase.findLimit或logger.level,其余字段从完整 base 继承。 - 原子能力:adapter、store、callback、数组以及注册为 runtime capability 的路径仍要求完整值,不会被递归放宽。
不要把一个必填的基础对象拆到多个文件,并期待 TypeScript 等后续合并再补齐。即使 development.ts 会提供 uri,default.ts 中的半截 database 仍然无效;应先在 base 提供完整连接,再由后层只覆盖环境差异。参见数据库配置。
Bootstrap Config Provider
如果你需要在 配置定稿前 拉取远程配置(例如 Nacos / 配置中心 / 启动期密钥派发),可以新增 src/config/bootstrap.ts:
provider 上下文字段:
约束:
- provider 必须返回 plain object patch 或
null - patch 只支持 JSON-like 结构;不支持函数、类实例、adapter factory
- 默认优先级:
local < provider < CLI - 未声明
required时:production默认 fail-fast,development / test默认 warning 后继续 - Cluster 模式下,Master 会将本轮 provider patch 传递给 Worker 复用,避免同一启动周期出现配置漂移
配置文件格式
每个配置文件使用 export default 导出一个对象:
config.session.enabled: true 会在生产、开发、测试和软重载链路中自动注册 Session,应用配置默认值为 false。内置 memory store 适合单进程部署;共享部署应把 createCacheSessionStore(cacheLike) 或自定义 VextSessionStore 设置到 config.session.store。路由可通过 session: false 跳过,也可在全局关闭时通过 session: true 单独启用。显式 session() 中间件仍保留给作用域化或手动注册场景。
config.csrf.enabled: true 会在 body parsing 与插件全局中间件之后自动注册内置 CSRF 中间件。若只想保护指定路径,请保持禁用并手动注册 csrf()。
config.securityHeaders.enabled: true 会自动注册低破坏浏览器安全响应头。默认建议使用 preset: "basic";启用 strict 或显式 CSP/COEP 前,请先检查前端资源、CDN、iframe 嵌入和 OAuth popup 流程。
Middlewares Patch 策略
middlewares 数组使用智能合并,按中间件 name 匹配:
同一个配置层中,每个中间件名称只能声明一次;同文件重名会在启动时失败。后续 profile/local 层可以声明一次同名项来 patch 前一层;{ name, enabled: false } 不会进入运行时 registry。
合并后结果:
使用 Adapter
默认使用 Native Adapter(http.createServer + route-core)。要切换其他 Adapter,在配置中指定 adapter 字段:
不指定 adapter 时默认使用 Native Adapter,它不依赖第三方 HTTP 框架。需要特定框架的能力或迁移路径时再切换;吞吐表现会随场景变化,请结合当前性能基准和你的业务负载判断。
前端配置 (frontend)
frontend 控制内置浏览器流水线。它可以是 true、false 或对象:
默认 spaFallback.scopes 为空,因此未知 HTML 路径不会被自动吞成 SPA 页面。需要混合 SSR + client-router 子应用时,在 scopes[] 中声明具体 basePath。spaFallback: true 仅作为兼容 shorthand,不推荐在企业级混合项目中使用。
frontend.deploy.upload 启用后,vext deploy assets 会读取 dist/client/deploy-manifest.json,按 uploadKey 和 sha256 增量上传。内置 filesystem adapter 会把文件写入 targetDir,适合作为 CDN 同步前的 staging 目录;真实云厂商上传可通过自定义 adapter 扩展。
默认上传排除 index.html 和 **/*.map:HTML 仍由 Vext 服务端渲染,source map 可保留在服务器调试链路中,不随 CDN 静态资源发布。
本表只是通用配置总览。需要精确嵌套字段、resolved default、构建输出拓扑或 CDN/upload 决策时,请阅读前端配置与权威的 VextFrontendConfig API 参考。创建项目、修改页面、添加组件、CSS/JSCSS、静态资源、API 调用、HTML 模板和常见排错见 前端指南。
完整配置项参考
基础配置
生产或容器环境可使用 host: "0.0.0.0" 监听 IPv4 all interfaces,也可使用 host: "::" 监听 IPv6 all interfaces。host: "::" 的 ready 日志会额外显示 http://[::1]:PORT 和 bracketed IPv6 Network URL;具体 IPv6 host 也会按 http://[IPv6]:PORT 输出。
CORS 配置 (cors)
限流配置 (rateLimit)
关闭或省略时,Vext 不安装限流中间件,也不会产生限流响应头或 HTTP 429。
app.setRateLimiter() 只替换实现,不会改变这个显式启用开关。
可以在路由的 options.override.rateLimit 中为特定路由覆盖限流配置:
Security Headers 配置 (securityHeaders)
basic 发送 X-Content-Type-Options、Referrer-Policy 与 X-Frame-Options。strict 额外启用 HTTPS-only HSTS、最小 Permissions-Policy、COOP 和 CORP;CSP 与 COEP 仍需显式配置。路由可通过 { securityHeaders: false } 跳过。
请求 ID 配置 (requestId)
当请求中携带 X-Request-Id 头时,框架会透传该 ID 而不是生成新的。适合微服务链路追踪。
日志配置 (logger)
支持的日志级别(从低到高):'trace' → 'debug' → 'info' → 'warn' → 'error' → 'fatal' → 'silent'
VextJS 内置零 runtime dependency 的 logger kernel,pretty 模式使用内置 formatter 输出可读日志。默认 logger 支持 trace()、getLevel() / setLevel() 和 exact key/path redaction;完整说明见 日志文档。
优雅关闭配置 (shutdown)
收到 SIGTERM / SIGINT 信号后,框架按注册的逆序执行所有 onClose 钩子(如关闭数据库连接),超时后强制退出。
HTTP Server 配置 (server)
server 控制入站 Node.js HTTP server 层行为,适用于内置 Native / Hono / Fastify / Express / Koa adapter,也适用于 vext dev 创建的开发 server。未配置的字段保持当前 Node.js 默认值。
config.server 只影响入站服务请求;出站 app.fetch / app.fetch.proxy 的超时仍由 config.fetch.timeout 或调用时 options 控制。
响应配置 (response)
这里的 response.hideInternalErrors 针对的是“未知异常”的 500 路径,例如代码中直接 throw new Error("...")。如果你使用 app.throw(...) 主动抛出 404、409 等结构化 HTTP 错误,框架仍会按你指定的状态码和消息返回,不受该配置影响。
启用 wrap: true 后,res.json(data) 的实际输出:
设置 wrap: false 可关闭包装,res.json(data) 直接输出原始数据。
Body Parser 配置 (bodyParser)
maxBodySize 支持字符串格式('1mb'、'500kb')和数字格式(字节数)。
Multipart / 文件上传配置 (multipart)
Access Log 配置 (accessLog)
启用后,每个请求完成时自动记录:
OpenAPI 配置 (openapi)
openapi.docs.access.cacheKey 当前版本不支持,并会被配置校验拒绝。请直接配置 resolver;后续若引入文档缓存层,应由独立缓存契约重新定义。
固定本地或部署 API 目标时,openapi.servers[].url 建议直接写带端口的完整 base URL,例如 http://127.0.0.1:3000。只有环境名、区域、租户或 API 版本这类真正会变化的 URL 片段,才建议使用 openapi.servers[].variables。openapi.docs.tryItOut.defaultServer 用于控制 Try it out 初始选中的 server,openapi.docs.tryItOut.customServer 用于允许用户在浏览器里临时输入其他目标地址,不需要修改项目配置。
数据库配置 (database)
添加 database 会启用 Vext 内置的 monsqlize@3.3.0 生命周期:连接归一化、
日志桥接、Model 加载、挂载原始 app.db 以及关闭清理。这些由
Vext 管理的能力继续使用一等字段配置。database.monsqlizeOptions 是带类型且
经过运行时校验的高级 allowlist 入口;受保护或未知字段会在上游构造函数运行前失败。
完整 allowlist、所有权边界、原始实例 API、Vector Search 与关系保护删除前提见 数据库 (MonSQLize)。
请求上下文配置 (requestContext)
禁用 requestContext 会移除基于请求上下文的生命周期能力,也可能减少相应开销,但收益取决于负载,必须用实际应用验证。以下功能将失效:
app.logger自动携带requestIdapp.throw()自动解析请求 localeapp.fetch自动传播requestId
仅在确认这些能力不需要、且实际压测证明收益成立时考虑禁用。
Cluster 配置 (cluster)
也可以通过环境变量 VEXT_CLUSTER=1 开启 Cluster 模式,无需修改配置文件。
Dev 模式配置 (dev)
dev 配置项仅在 vext dev 开发模式下读取,生产模式(vext start)自动忽略所有字段。
Dev 错误覆盖层基于 Accept 内容协商,而非 HTTP 方法:
Accept: text/html(浏览器地址栏 GET、HTML 表单 POST)→ 返回 HTML 错误页Accept: application/json(前端 fetch / axios / curl)→ 始终返回 JSON
控制台日志不受 overlay 影响——无论响应返回 HTML 还是 JSON,logErrors 配置的日志行为完全相同。
中间件白名单 (middlewares)
只有在白名单中声明的中间件才能在路由的 options.middlewares 中被引用。
在代码中访问配置
路由中
服务中
插件中
app.config 在启动后被深冻结(deepFreeze),任何修改尝试都会抛出 TypeError。这确保配置在运行时不被意外修改。
自定义配置字段
VextConfig 接口允许扩展自定义字段。插件和业务代码可以在配置中添加任意字段:
配合 declare module 获得类型提示:
环境变量
除了配置文件,部分设置也可以通过环境变量控制:
VextJS 不会自动解析 .env 文件。process.env 中可见的值,必须已由操作系统、
shell、进程管理器、容器/CI 平台、密钥系统或应用显式拥有的 loader 注入。Vext
配置 profile 由 --config 或 VEXT_CONFIG 选择;.env 文件不是另一个内建的
Vext profile 层。
:::warning 安全提示 敏感信息(如数据库密码、API Key)不要硬编码在配置文件中。推荐:
- 使用环境变量:
process.env.DB_PASSWORD - 使用
local.ts(已加入.gitignore)存放本地开发的敏感配置 :::
配置校验
config-loader 在合并完成后会执行 Fail Fast 校验,检查以下内容:
port必须是 1-65535 范围内的正整数adapter必须是已知的内置标识或合法的 adapter 对象/函数middlewares数组中每个元素必须是字符串或{ name: string }对象rateLimit.max必须是正整数rateLimit.window必须是正整数logger.level必须是合法的日志级别logger.redactKeys/logger.redactPaths必须是字符串数组,logger.redactValue必须是字符串shutdown.timeout必须是非负数(单位:秒)server.requestTimeout、server.headersTimeout、server.keepAliveTimeout、server.socketTimeout必须是非负有限数(单位:毫秒)server.maxHeaderSize、server.connectionsCheckingInterval必须是正整数,server.maxRequestsPerSocket必须是非负整数cluster.workers必须是正整数或'auto'/'auto-1'
如果校验失败,框架会在启动时立即报错并给出清晰的错误信息,避免配置错误在运行时才暴露。
完整示例
下一步
- 了解 Adapter 架构 的详细配置和切换方法
- 学习 中间件 白名单的配置方式
- 查看 OpenAPI 文档 的高级配置
- 探索 Cluster 多进程 的配置选项