配置
本页说明配置从哪里加载、各层如何合并,以及如何验证实际生效值。首次建项目见快速开始。先完成下方不依赖外部服务的完整示例,再按需要阅读加载机制与分项配置;字段的精确签名和完整嵌套项见配置 API。各分项代码是独立片段,需合并到已有配置中,不能反复覆盖整个文件。
完整示例
先在已完成快速开始的 TypeScript 项目中验证。项目需已有 dev、build(含 --typecheck)、start 三个 npm scripts;把以下配置合并到对应文件,新增诊断路由。为得到下述结果,请使用独立的练习项目,保留脚手架的空 bootstrap.ts,避免已有 provider 或其他 profile 改写示例值。
示例只显式设置本次验证需要的字段,其余使用框架默认值;不连接外部服务。完整字段说明见后续各节及配置 API。
- 清除本终端先前设置的PORT、VEXT_PORT/VEXT_HOST、VEXT_CONFIG等覆盖(或在干净终端执行),运行
npm run dev。请求http://127.0.0.1:8080/config-info,应为200,data中port=8080、logLevel=info、docsEnabled=true,证明local在开发模式生效。 - 停止dev,运行
npm run build,成功后npm start。请求http://127.0.0.1:3000/config-info,应为200,port=3000、logLevel=warn、docsEnabled=false,证明production覆盖生效且未读取local。 - 停止服务后运行
npm start -- --port 3100,请求3100端口应显示port=3100,验证CLI覆盖优先级。验证结束停止该服务。
只输出本例的三个非敏感诊断字段,不要把整个app.config作为业务接口返回。监听host可能是0.0.0.0或::,它不是对外服务的公开base URL;代理/CDN后的公开地址由部署合同决定,不能仅由host/port推断。
VextJS 采用 多层配置合并 机制,支持按环境覆盖配置,同时提供丰富的内置配置项覆盖框架行为。
配置加载机制
框架启动时,config-loader 按以下顺序加载配置文件并深度合并:
运行时合并允许后层只声明需要覆盖的字段。TypeScript 则有意区分项目基础配置与后层 patch:default.ts 使用 VextUserConfig,环境 profile 与 local 配置文件使用 VextConfigOverride,createTestApp() 采用同一覆盖合同。bootstrap provider 继续使用 JSON-like Record<string, unknown> patch,并由现有运行时校验。
直接加载 TypeScript 配置源码时,框架负责编译,不要求额外安装 TS loader。模块在当前应用进程中执行,支持顶层 await,模块导出的 provider 函数仍可使用当前进程状态;同一进程对同一个 TS 配置模块复用求值结果。import.meta.url / filename / dirname 指向该模块的源码位置。临时执行文件由框架管理,正常加载和加载失败都会清理;发现外部改动时会保留冲突文件并报告错误。compiled 生产模式继续加载选定构建目录中的配置产物。
配置文件
配置 profile 的显式选择优先级为 --config <name> → VEXT_CONFIG=<name> → 非标准 NODE_ENV 的兼容选择(会警告)。无显式选择时,vext build 默认使用 production,vext dev 默认使用 development;vext start 与 vext deploy assets 优先沿用所选成功构建产物记录的 profile,没有记录时才回退 production。
例如在干净终端执行 npm run build -- --config sg-sit 后,直接 npm start 会沿用 sg-sit,运行模式仍为 production。需要改用其他 profile 时显式选择,并确认对应配置文件已进入产物;完整命令与构建身份检查见 CLI。
显式CLI profile优先于VEXT_CONFIG。非标准NODE_ENV名称仍有带警告的旧兼容入口,推荐改用显式profile;标准NODE_ENV不能取代命令自己的默认模式。profile名称只允许字母、数字、下划线和连字符,default/local/bootstrap是保留名;不要传文件路径。
profile 名可以是自定义部署环境名,例如:
src/config/sg-sit.tssrc/config/us-uat.tssrc/config/us-prod.ts
启动时传入 profile 名:
第二行是POSIX shell写法;PowerShell可用 $env:VEXT_CONFIG = "sg-sit" 后再执行命令,或直接使用跨shell的 --config。配置文件示例使用.ts;Loader也支持.js/.mjs/.cjs。
上述生产启动使用 default -> sg-sit -> bootstrap provider patch -> CLI override。local.ts 只在 development/test 运行模式加载;生产 build 与 start(JS 源码或编译后的 TS)均不隐式执行它。部署覆盖使用显式 profile 或 bootstrap provider;选择自定义 profile 不改变运行模式。
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 条件分支。
合并规则
- 普通对象字段:深度合并,后层只声明覆盖字段;类实例和运行能力对象有原子边界,不能据此递归patch任意实例
middlewares数组:智能 patch 策略——按name匹配并合并,而非简单替换整个数组- 其他数组:后层覆盖前层
bootstrap provider patch:在local.ts之后、CLI override 之前参与同一套 merge / validate / freeze 流程- 最终结果:普通配置对象和数组深冻结,运行时不应修改;客户端等非普通类实例保留内部可变状态,不会被递归冻结
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 上下文字段:
dev 和 build 在后端编译前从 src/config 求值一次完整配置,先确定自定义前端等目录;这两个入口的 provider 上下文中 configDir 指向源码配置目录,isBuilt=false。后端编译、前端构建和开发监视复用本次配置,不为获取目录再次执行 provider。start 消费编译产物时仍使用产物配置目录与 isBuilt=true;不要把 isBuilt 当成“是否正在执行 build 命令”。
约束:
- 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 复用,避免同一启动周期出现配置漂移
超时会触发 signal,但不会强制终止任意用户异步工作;provider 中的网络操作应接收该 signal。占位远端地址需要替换为实际服务,不属于开篇完整示例的必需文件。
配置文件格式
每个配置文件使用 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 } 会保留名称并注册为空操作,不查找或执行原中间件文件。禁用后可按名称引用,但不能在路由引用中继续传 options:空操作按普通中间件处理,不再是工厂。
同名声明是浅合并:options被后层整个替换,不递归合并内部属性。空数组不表示删除继承的白名单,禁用已有项应使用enabled:false;片段中的auth/check-role/rate-limit-api须有对应实现,白名单名称不会自动生成中间件。
合并后结果:
使用 Adapter
默认使用 Native Adapter(http.createServer + route-core)。要切换其他 Adapter,先按 Adapter 指南安装对应的可选依赖,再从以下四种配置中选择一种合并到 default.ts:
不指定 adapter 时默认使用 Native Adapter,它不依赖第三方 HTTP 框架。切换其他Adapter前需安装对应包;吞吐表现会随场景变化,请结合当前性能基准和你的业务负载判断。
前端配置 (frontend)
frontend 控制内置浏览器流水线。它可以是 true、false 或对象。以下展示多个可选能力的组合,假定项目已按前端指南建立页面、样式及语言资源;其中 admin/app/shell 必须是实际存在的页面。仅启用默认集成可以使用 frontend: true,不必照搬整个片段。
默认 spaFallback.scopes 为空,因此未知 HTML 路径不会被自动吞成 SPA 页面。需要混合 SSR + client-router 子应用时,在 scopes[] 中声明具体 basePath。spaFallback: true 仅作为兼容 shorthand,不推荐在企业级混合项目中使用。
frontend.deploy.upload 启用后,vext deploy assets 会读取实际所选前端输出中的deploy-manifest,默认是 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 模板和常见排错见 前端指南。
常用配置项总览
本节保留常用字段及默认值;未列出的缓存、fetch、locale、Session/CSRF细项等,以配置 API为完整参考。单独设置某个参数不代表对应功能已启用。
基础配置
生产或容器环境可使用 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() 只替换实现,不会改变这个显式启用开关。
keyBy: "user"读取req.user.id,未取得时回退IP;全局限流早于普通认证中间件,不会自动用req.auth隔离额度。Redis、路由覆盖和自定义实现见请求限流。
全局已启用限流时,可以在路由的 options.override.rateLimit 中为特定路由覆盖限流配置。下面是 defineRoutes 回调内的片段,handler 代表你已有的处理函数:
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,缺失或为空时调用生成器,并写入响应头。读取到的 ID 和生成器返回值都必须是长度 1–512 的字符串,且不含控制字符,否则会抛错;数组形式的请求头只取首项。它用于请求关联,不自动等同于分布式追踪的 traceId。
日志配置 (logger)
支持的日志级别(从低到高):'trace' → 'debug' → 'info' → 'warn' → 'error' → 'fatal' → 'silent'
VextJS使用内置logger kernel与pretty formatter。默认logger支持trace、getLevel/setLevel和exact key/path redaction;完整说明见日志文档。
优雅关闭配置 (shutdown)
正常HTTP进程收到SIGTERM/SIGINT后进入有界关闭:停止接收、处理在途请求,再按注册逆序调用onClose。整个流水线共享期限,到期仍调用剩余清理但不再等待;测试helper关闭不会调用process.exit,也不能把某个未结束异步清理当成已完成。
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.maxFileSize增大而自动放宽;Adapter/反向代理还可能有更严格限额。
Multipart / 文件上传配置 (multipart)
内置multipart是纯内存解析,不自动写盘;普通multipart文本字段不会自动进入req.body,路由覆盖也不能挽回全局提前拒绝的文件。完整示例与错误复验见文件上传。
Access Log 配置 (accessLog)
启用后,请求完成时会按日志级别和路径过滤设置记录访问日志;以下是 pretty 模式下的示意:
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 生命周期;当前没有database.enabled关闭开关,未配置、null或空对象才会跳过。生命周期包括连接归一化、
日志桥接、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 模式,无需修改配置文件。
CPU 检测规则、源 IP 亲和性的代理/NAT 限制及滚动重启行为,见Cluster 指南。修改 sticky 或 workers 后需要完整重启 Master;vext reload 不用于切换这两项策略。
Jobs 配置
config.jobs 配置随应用启动的 cron / interval 定时任务。默认启用,插件、服务及 ready 阶段完成后才调度未来触发点;内置 Cluster 中有启用任务时必须配置 Redis。测试 helper 使用显式传入的定义,不自动扫描和运行任务。Docs 的 Job source 有独立目录配置,自定义 jobs.dir 时也应核对该文档源。
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的普通对象与数组在加载后被深冻结;ESM严格模式下改写冻结属性会抛TypeError。显式传入的非普通类实例不被递归冻结,因此不能把这个机制理解成会冻结Redis客户端内部状态。
自定义配置字段
VextConfig 接口允许扩展自定义字段。插件和业务代码可以在配置中添加任意字段:
配合 declare module 获得类型提示:
环境变量
除了配置文件,部分设置也可以通过环境变量控制:
VextJS 不会自动解析 .env 文件。process.env 中可见的值,必须已由操作系统、
shell、进程管理器、容器/CI 平台、密钥系统或应用显式拥有的 loader 注入。Vext
配置 profile 由 --config 或 VEXT_CONFIG 选择;.env 文件不是另一个内建的
Vext profile 层。
部署值可以由项目选定的配置文件、平台注入或provider提供;框架不要求统一使用某一种来源。例如:
- 使用环境变量:
process.env.DB_PASSWORD - 使用
local.ts(已加入.gitignore)存放本地开发的敏感配置
生产模式不会加载local.ts,生产值应通过实际加载的profile/provider或显式环境输入提供。
配置校验
config-loader 在合并完成后执行启动校验。下面是常见检查摘要;各配置域还有专用校验,不能把这份清单理解为所有字段和业务值均已被验证:
port必须是 1-65535 范围内的正整数adapter必须是已知的内置标识或合法的 adapter 对象/函数middlewares数组中每个元素必须是字符串或{ name: string }对象rateLimit.max、rateLimit.window当前检查类型为 number 且不小于 1,并未完整检查有限性与整数性。应用应使用有限的正数,次数max使用整数;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 多进程 的配置选项