配置项

本页详细列出 VextJS 的所有配置字段、类型、默认值及使用说明。

配置加载机制

VextJS 使用多层配置合并策略,按优先级从低到高:

DEFAULT_CONFIG(框架内置默认值)
  ↓ 深度合并
src/config/default.ts(项目默认配置)
  ↓ 深度合并
src/config/{profile}.ts(配置 profile,如 production.ts 或 sg-sit.ts)
  ↓ 深度合并
src/config/local.ts(本地覆盖,可选)
  ↓ provider patch
src/config/bootstrap.ts(启动期远程配置,可选)
  ↓ CLI override
vext start/dev --port --host ...

合并后的配置通过 deepFreeze() 深冻结,运行时不可修改。

配置文件清单

文件用途是否必须
src/config/default.ts所有 profile 的基础配置
src/config/development.ts开发默认 profile 覆盖可选
src/config/production.ts生产默认 profile 覆盖可选
src/config/test.ts测试默认 profile 覆盖可选
src/config/sg-sit.ts自定义 profile 覆盖可选
src/config/local.ts本地覆盖(通常不提交 Git)可选
src/config/bootstrap.ts启动期 provider 注册入口可选

src/config/bootstrap.ts

当数据库、密钥或配置中心 patch 需要在配置冻结前完成注入时,可新增:

import { defineBootstrapConfig } from "vextjs";

export default defineBootstrapConfig({
  providers: [
    {
      name: "remote-config",
      timeoutMs: 10_000,
      async load({ configProfile, signal, baseConfig }) {
        const response = await fetch(
          `https://config.example.com/${configProfile}.json`,
          { signal },
        );
        const remote = await response.json();
        return {
          database: remote.database,
          logger: {
            lifecycleLevel: baseConfig.logger?.lifecycleLevel ?? "concise",
          },
        };
      },
    },
  ],
});

约束:

  • provider 必须返回 plain object patch 或 null
  • patch 只支持 JSON-like 结构
  • required 未声明时:production 默认 fail-fast,development / test 默认 warning 后继续
  • Cluster 模式下,同一启动周期会复用同一份 provider patch,避免 Master / Worker 看到不同结果

配置文件示例

// src/config/default.ts
export default {
  port: 3000,
  adapter: "native",
  cors: {
    enabled: true,
    origins: ["http://localhost:3000"],
  },
  logger: {
    level: "debug",
  },
};
// src/config/production.ts
export default {
  port: 8080,
  cors: {
    origins: ["https://api.example.com"],
  },
  logger: {
    level: "warn",
  },
  response: {
    hideInternalErrors: true,
  },
};

完整配置参考

VextConfig

字段类型默认值说明
portnumber3000HTTP 监听端口
hoststring'0.0.0.0'HTTP 监听地址
adapterstring | Function | VextAdapter'native'底层适配器
trustProxybooleanfalse是否信任代理
middlewaresVextMiddlewareConfig[][]路由级中间件白名单
corsVextCorsConfig见下方CORS 配置
rateLimitVextRateLimitConfig见下方速率限制配置
requestIdVextRequestIdConfig见下方请求 ID 配置
loggerVextLoggerConfig见下方日志配置
shutdownVextShutdownConfig见下方优雅关闭配置
serverVextServerConfig{}Node.js HTTP server 配置
responseVextResponseConfig见下方响应配置
sessionVextSessionConfig见下方Session 自动注册、store 与 cookie 配置
csrfVextCsrfConfig见下方CSRF 中间件配置
securityHeadersVextSecurityHeadersConfig{ enabled: false }浏览器安全响应头配置
bodyParserVextBodyParserConfig见下方Body 解析配置
multipartVextMultipartConfigundefined文件上传配置
accessLogVextAccessLogConfig见下方访问日志配置
openapiVextOpenAPIConfig见下方OpenAPI 文档配置
requestContextVextRequestContextConfig见下方请求上下文配置
fetchVextFetchConfig见下方内置 HTTP 客户端与代理配置
frontendboolean | VextFrontendConfig{ enabled: false }内置前端构建与静态服务配置
clusterPartial<VextClusterConfig>undefinedCluster 多进程配置

host 支持 "0.0.0.0""::"、具体 IPv4、具体 IPv6 和主机名。配置为 "::" 时,ready 日志会同时展示 IPv4 local URL 与 bracketed IPv6 local/network URL(例如 http://[::1]:3000);具体 IPv6 host 也会以方括号 URL 格式输出。


adapter

底层 HTTP 适配器,支持三种传参方式:

// 方式一:字符串标识(内置 adapter)
export default {
  adapter: "native", // 'native' | 'hono' | 'fastify' | 'express' | 'koa'
};

// 方式二:工厂函数(传入自定义选项)
import { fastifyAdapter } from "vextjs/adapters/fastify";

export default {
  adapter: fastifyAdapter({ bodyLimit: 5 * 1024 * 1024 }),
};

// 方式三:自定义 adapter 实例(实现 VextAdapter 接口)
export default {
  adapter: myCustomAdapter,
};

trustProxy

当设置为 true 时:

  • req.ipX-Forwarded-For 请求头读取第一个 IP
  • req.protocolX-Forwarded-Proto 请求头读取

部署在 Nginx / 云负载均衡器之后时需开启此选项。

middlewares

路由级中间件白名单声明。只有在此处声明的中间件才能在路由 options.middlewares 中引用。

export default {
  middlewares: [
    { name: "auth" },
    { name: "framework-auth" },
    { name: "admin", options: { role: "admin" } },
    { name: "client-cache", options: { maxAge: 60 } },
  ],
};
Tip

全局中间件(如 CORS、body-parser)由框架自动注册,无需在此声明。此处只声明路由级可选中间件

Vext 内置 auth() helper 仍然以路由级中间件文件注册,路由再通过 RouteOptions.auth 选择是否保护:

// src/middlewares/framework-auth.ts
import { auth, defineMiddleware } from "vextjs";

export default defineMiddleware(
  auth({
    async verify(token) {
      return token === "demo-token" ? { userId: "1" } : false;
    },
  }),
);

VextCorsConfig

跨域资源共享配置。

字段类型默认值说明
enabledbooleantrue是否启用 CORS
originsstring[]['*']允许的来源域名
methodsstring[]['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']允许的 HTTP 方法
headersstring[]['Content-Type', 'Authorization', 'X-Request-Id']允许的请求头
credentialsbooleanfalse是否允许携带凭证
maxAgenumberundefinedCORS 预检结果缓存时间(秒)
export default {
  cors: {
    enabled: true,
    origins: ["https://app.example.com", "https://admin.example.com"],
    credentials: true,
    maxAge: 86400,
  },
};
Warning

origins: ['*']credentials: true 不能同时使用。需要携带凭证时必须指定具体域名。


VextRateLimitConfig

全局速率限制配置,基于 flex-rate-limit 实现。

字段类型默认值说明
enabledbooleantrue是否启用速率限制
maxnumber100时间窗口内最大请求数
windownumber60时间窗口(秒)
messagestring'Too Many Requests'超限错误消息
keyBystring | Function'ip'请求来源标识
export default {
  rateLimit: {
    max: 200,
    window: 120,
    // 按用户 ID 限流(需要 auth 中间件先解析用户)
    keyBy: (req) => req.user?.id ?? req.ip,
  },
};

keyBy 选项

说明
'ip'按客户端 IP 限流(默认)
'user'req.user?.id 限流
(req) => string自定义函数,返回唯一标识
Tip

路由级可通过 options.override.rateLimit 覆盖全局配置,或设为 false 禁用限流。


VextRequestIdConfig

请求 ID 追踪配置,用于日志关联和分布式链路追踪。

字段类型默认值说明
enabledbooleantrue是否启用请求 ID
headerstring'x-request-id'从哪个请求头读取(网关透传)
responseHeaderstring'x-request-id'写入响应头的名称
generate() => stringcrypto.randomUUID()自定义 ID 生成函数

requestId vs traceId

requestId 是 vext 内置的请求唯一标识,traceId 通常指 APM 链路追踪系统(如 OpenTelemetry / Jaeger)生成的追踪 ID。两者有不同的使用场景:

模式一:requestId 充当 traceId(简单场景)

requestId 的请求头名改为 x-trace-id,使其与链路追踪头统一,适合不依赖外部 APM 的系统:

import { nanoid } from "nanoid";

export default {
  requestId: {
    header: "x-trace-id", // 从 x-trace-id 读取(网关注入)
    responseHeader: "x-trace-id", // 写回响应头
    generate: () => nanoid(), // 可替换为更短的 ID 生成器
  },
};

模式二:requestId + APM traceId 并存(企业级场景)

保留 requestId(日志关联),同时通过 config.fetch.propagateHeaders 透传 APM 的 traceparent 头,适合接入 OpenTelemetry / Jaeger 等系统:

export default {
  // requestId 保留默认配置(用于日志关联)
  requestId: {
    header: "x-request-id",
    responseHeader: "x-request-id",
  },
  // APM 追踪头通过 propagateHeaders 自动透传到下游服务
  fetch: {
    propagateHeaders: ["traceparent", "tracestate"],
  },
};
选择建议
  • 内部系统、简单追踪 → 模式一(改 header 名为 x-trace-id
  • 接入 OpenTelemetry / Jaeger / Datadog → 模式二(保留 requestId,配置 propagateHeaders)
  • 详见 请求上下文 → 与分布式追踪的关系 :::

也可通过插件动态替换生成器:

app.setRequestIdGenerator(() => myCustomId());

VextFetchConfig

内置 HTTP 客户端与请求代理配置。

字段类型默认值说明
timeoutnumber10000app.fetchapp.fetch.proxy 默认超时
retrynumber0默认重试次数,表示额外尝试次数
retryDelaynumber | (attempt: number) => number1000默认重试间隔,支持函数形式
propagateHeadersstring[][]普通 app.fetch 自动透传的请求头白名单
proxyVextFetchProxyTargetConfig[][]app.fetch.proxy.<name>() 的上游目标列表

timeout 必须是大于 0 且不超过 2147483647 毫秒的有限数字;retryDelay 必须是 0 或正数且不超过 2147483647 毫秒,函数形式的返回值也会在运行时校验。

export default {
  fetch: {
    timeout: 10_000,
    retry: 1,
    retryDelay: 500,
    propagateHeaders: ["traceparent", "x-tenant-id"],
    proxy: [
      {
        name: "userService",
        baseURL: "http://user-service:3001/api",
        forwardHeaders: ["x-tenant-id"],
        headers: { "x-source": "gateway" },
        timeout: 5000,
        retry: 1,
      },
    ],
  },
};

VextFetchProxyTargetConfig

字段类型必填说明
namestring目标名称,对应 app.fetch.proxy.<name>();不能使用保留名 then
baseURLstring上游基础 URL
headersRecord<string, string>目标级固定请求头
forwardHeadersstring[]从当前 req.headers 透传的请求头白名单
defaultInjectHeadersRecord<string, string> | Function目标级动态注入 headers
allowAuthorizationForwardboolean是否允许透传原始 Authorization
timeoutnumber目标级超时
retrynumber目标级重试次数
retryDelaynumber | (attempt: number) => number目标级重试间隔

代理请求头优先级:target.headers < forwardHeaders < target.defaultInjectHeaders < options.headers < options.injectHeadersAuthorization 默认不透传,必须同时配置白名单和 allowAuthorizationForward: true

代理 retry 优先级:options.retry > target.retry > config.fetch.retry > 0。仅 GET / HEAD / OPTIONS / PUT / DELETE 会在上游 5xx 或网络错误时自动重试;POST / PATCH 默认不重试,超时不重试并返回本地 504。


VextLoggerConfig

结构化日志配置,基于 Vext 内置 logger kernel 实现。

字段类型默认值说明
level'fatal' | 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'silent''info'日志级别
lifecycleLevel'concise' | 'verbose''concise'框架生命周期日志详细程度,控制启动、loader、hot reload、cluster 等系统日志输出
prettyboolean开发环境 true是否使用内置 pretty formatter 输出可读格式
prettyIgnorestring'pid,hostname,requestId'pretty 模式下忽略的字段(逗号分隔)。默认隐藏 requestId 避免 mixin 注入的字段被展开为多行噪音,生产环境 JSON 输出不受影响
prettySingleLinebooleantruepretty 模式下是否将额外字段以 JSON 内联形式压缩到消息同一行。设为 false 使用多行展开格式。仅影响 pretty 模式,生产环境 JSON 输出不受影响
redactKeysstring[][]按任意层级 exact key 脱敏结构化日志字段。顶层 level 为日志协议字段,不会被改写
redactPathsstring[][]按 dot notation exact path 脱敏结构化日志字段,支持数组数字下标;不支持 wildcard、bracket notation、remove 或 function censor
redactValuestring'[Redacted]'脱敏替换值
mixin() => Record<string, unknown>undefined自定义日志 mixin 函数,返回值会与框架内置字段合并注入每条日志。requestId 是框架保护字段,不可被用户 mixin 覆盖;trace_id / span_id 等其他字段按用户 mixin 优先。典型用途:注入 OpenTelemetry trace_id / span_id,实现日志与链路追踪关联。未配置时不会执行用户 mixin 调用。
export default {
  logger: {
    level: "debug",
    pretty: true, // 开发环境美化输出
    // prettySingleLine: true,                   // 默认值,额外字段压缩到消息同一行
    // prettySingleLine: false,                  // 恢复多行展开格式
    // prettyIgnore: 'pid,hostname,requestId',   // 默认值,隐藏 requestId
    // prettyIgnore: 'pid,hostname',             // 如需在 pretty 模式下显示 requestId
    // redactKeys: ['password', 'token'],
    // redactPaths: ['user.email', 'headers.authorization'],
    // redactValue: '[Redacted]',
  },
};

日志级别优先级(从高到低):

fatal > error > warn > info > debug > trace

设置某个级别后,只输出该级别及更高级别的日志。设为 'silent' 完全静默。

默认 logger 还支持运行时 app.logger.getLevel() / app.logger.setLevel(level) 调整后续日志阈值;配置对象本身仍会在启动后冻结,不应通过修改 app.config.logger.level 动态变更。


VextShutdownConfig

优雅关闭配置。

字段类型默认值说明
timeoutnumber10关闭超时(秒)

收到 SIGTERM / SIGINT 信号后,框架会:

  1. 停止接受新请求
  2. 等待飞行中请求完成(不超过 timeout 秒)
  3. 按 LIFO 顺序执行所有 onClose 钩子
  4. 退出进程
export default {
  shutdown: {
    timeout: 30, // 容器环境建议 30 秒
  },
};

VextServerConfig

入站 Node.js HTTP server 层配置。适用于内置 Native / Hono / Fastify / Express / Koa adapter,也适用于 vext dev 创建的开发 server。未设置字段保持当前 Node.js 默认值。

字段类型默认值说明
requestTimeoutnumberNode.js 默认值接收完整请求的最大时间(毫秒),0 表示禁用
headersTimeoutnumberNode.js 默认值接收完整 HTTP headers 的最大时间(毫秒)
keepAliveTimeoutnumberNode.js 默认值响应完成后 keep-alive 空闲等待时间(毫秒)
socketTimeoutnumberNode.js 默认值socket inactivity timeout(毫秒),0 表示禁用
maxHeaderSizenumberNode.js 默认值最大请求头大小(bytes)
maxRequestsPerSocketnumberNode.js 默认值单 socket 最大请求数,0 表示不限
connectionsCheckingIntervalnumberNode.js 默认值未完成请求超时检查间隔(毫秒)
export default {
  server: {
    requestTimeout: 120_000,
    headersTimeout: 60_000,
    keepAliveTimeout: 5_000,
    socketTimeout: 0,
    maxHeaderSize: 16 * 1024,
    maxRequestsPerSocket: 0,
    connectionsCheckingInterval: 30_000,
  },
};

config.server 只控制入站服务请求。出站 app.fetch / app.fetch.proxy 的超时由 config.fetch.timeout、代理目标 timeout 或调用时 options 控制。


VextResponseConfig

响应格式配置。

字段类型默认值说明
hideInternalErrorsbooleantrue是否隐藏 500 错误详情
wrapbooleantrue是否启用出口包装

出口包装

启用 wrap: true 时,res.json(data) 自动包装:

{
  "code": 0,
  "data": { "id": 1, "name": "Alice" },
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

错误响应格式:

{
  "code": 10001,
  "message": "用户不存在",
  "requestId": "550e8400-e29b-41d4-a716-446655440000"
}

禁用 wrap: false 时,res.json(data) 直接发送原始 data

隐藏内部错误

hideInternalErrors 只影响“未知异常”这条 500 错误路径,例如路由、service、middleware 中直接 throw new Error("...") 的场景。它不会改变 app.throw(...)VextValidationError 这类结构化错误的状态码与响应格式。

hideInternalErrors: true 时,500 错误不暴露 stack trace:

// hideInternalErrors: true
{ "code": 500, "message": "Internal Server Error" }

// hideInternalErrors: false(仅开发环境使用)
{ "code": 500, "message": "Internal Server Error", "stack": "..." }

VextBodyParserConfig

请求体解析配置。

字段类型默认值说明
enabledbooleantrue是否启用 body 解析
maxBodySizestring | number'1mb'最大请求体大小
export default {
  bodyParser: {
    maxBodySize: "5mb", // 支持 'kb', 'mb', 'gb' 单位
  },
};

禁用后 req.body 始终为 undefined,适用于纯 GET 服务或自定义 body 解析场景。

maxBodySize 支持的格式:

格式示例说明
字符串'1mb', '512kb', '10mb'支持 kb/mb/gb 单位
数字1048576直接指定字节数

VextMultipartConfig

Multipart / 文件上传全局配置。

字段类型默认值说明
enabledbooleanfalse是否启用内置 multipart 解析。设为 true 后 body-parser 自动填充 req.files,无需插件
maxFileSizenumber10485760单个文件最大大小(字节,默认 10MB)
maxFilesnumber10单次请求最多文件数
allowedMimeTypesstring[]undefined允许的 MIME 类型白名单(不设置则不限制)
export default {
  multipart: {
    enabled: true, // 开启内置解析
    maxFileSize: 10 * 1024 * 1024, // 10MB
    maxFiles: 5,
    allowedMimeTypes: [
      "image/jpeg",
      "image/png",
      "image/gif",
      "application/pdf",
    ],
  },
};

:::tip Fastify 联动 multipart.maxFileSize 只限制单个文件大小;总请求体读取上限由 bodyParser.maxBodySize 控制。使用 Fastify 时,如额外传入 fastifyAdapter({ bodyLimit }),实际读取边界会取 adapter bodyLimit 与 body-parser 总体上限中的较小值。


VextAccessLogConfig

访问日志配置,基于洋葱模型 after-middleware 实现。

字段类型默认值说明
enabledbooleantrue是否启用访问日志
levelstring'info'基础日志级别,仅支持 'info''debug'
skipPathsstring[][]精确匹配跳过的路径列表
skipPathPrefixesstring[][]前缀匹配跳过的路径列表
slowThresholdnumber0慢请求阈值,0 表示不启用
warnOn4xxbooleanfalse是否将 4xx 响应提升为 warn
logResponseSizebooleanfalse是否在消息末尾追加响应体大小
export default {
  accessLog: {
    enabled: true,
    level: "info",
    skipPaths: ["/health", "/readiness", "/metrics"],
    skipPathPrefixes: ["/internal"],
    slowThreshold: 1000,
    warnOn4xx: false,
    logResponseSize: false,
  },
};

访问日志输出示例:

POST /api/users 201 12ms | 192.168.1.1

消息字段包括 HTTP 方法、路径、状态码、响应时间(ms)和客户端 IP;requestId 由 logger 的 AsyncLocalStorage mixin 自动注入到 JSON 记录字段。


VextOpenAPIConfig

OpenAPI 文档自动生成配置。

字段类型默认值说明
enabledbooleandev 启用,prod 关闭是否启用
titlestringundefined文档标题
versionstringundefined文档版本号
descriptionstringundefined文档描述
docs.pathstring'/docs'Vext Docs 文档路径
docs.assetsPathstring'/_vext/docs'Vext Docs 内置资产与数据端点前缀,包含 app.js / style.css / favicon.svg 和 source-aware JSON 数据
docs.assetsPublicPathstringdocs.assetsPath浏览器可见的 docs 资产/数据前缀,用于反向代理剥离公开前缀的场景;HTML 中的 app.js / style.css / favicon.svg 使用该公开前缀
docs.renderer'vext''vext'内置 Vext Docs renderer;不再支持第三方 renderer object,外部工具请直接消费 /openapi.json
docs.ui.theme'system' | 'light' | 'dark''system'内置 Vext Docs 颜色主题;访问者也可在 UI 中本地覆盖
docs.ui.density'comfortable' | 'compact''comfortable'内置 Vext Docs 间距密度;访问者也可在 UI 中本地覆盖
docs.code.enabledboolean | 'auto''auto'是否从 services / utils / models / components / plugins / middlewares 及显式开启的可选静态来源生成代码文档
docs.code.scan'lazy' | 'background''lazy'Code Docs 扫描生命周期;lazy 每次请求 docs data 时扫描,background 在文档注册时预热一次进程内快照并复用
docs.code.componentsboolean | objecttrueComponents JSDoc 文档源;默认扫描 src/frontend/components/**,仅发现条目时在 UI 中展示
docs.code.pluginsboolean | objecttruePlugins JSDoc/runtime 文档源;默认扫描 src/plugins/**,仅发现条目时在 UI 中展示
docs.code.middlewaresboolean | objecttrueMiddlewares JSDoc/runtime 文档源;默认扫描 src/middlewares/**,仅发现条目时在 UI 中展示
docs.code.localesboolean | objectfalse可选 Locales 文档源;开启后扫描 src/locales/**src/frontend/locales/**;配置 dir 时只扫描该自定义 locale 根目录
docs.code.configboolean | objectfalse可选 Config 文档源;开启后扫描 src/config/**
docs.code.stylesboolean | objectfalse可选 Styles 文档源;开启后扫描 src/frontend/styles/**
docs.code.preloadboolean | objectfalse可选 Preload 文档源;开启后扫描项目根 preload/**
docs.access.mode'off' | 'visibility-only' | 'enforce''off'文档 UI 数据、菜单和 operation 权限模式
docs.access.openapiJson'filtered' | 'public''filtered'canonical /openapi.json 是否跟随 docs 权限过滤,或保持公开
docs.sourcesArray[]可选的多 API / 多版本文档面配置。每个 source 都需要 match;非 All code docs 需要显式 code.include / code.exclude
docs.tryItOut.hookScriptstringundefinedTry it out 请求/响应 hook 的可选浏览器脚本路径
docs.tryItOut.hookGlobalstring'VextDocsHooks'Try it out beforeRequest / afterResponse hook 的浏览器全局变量名
docs.tryItOut.defaultServerstringundefinedTry it out 初始 server,支持 "first""same-origin""custom" 或精确 OpenAPI server URL
docs.tryItOut.sameOriginboolean | 'auto''auto'是否显示 Same origin server 选项;auto 仅在没有配置 OpenAPI servers 时显示
docs.tryItOut.customServerbooleantrue是否允许访问者在浏览器中临时填写 Try it out base URL
docs.tryItOut.customServerUrlstringundefinedCustom server 输入框的可选默认值
docsPathstring'/docs'兼容字段;新项目推荐使用 docs.path
jsonPathstring'/openapi.json'OpenAPI JSON 路径
jsonPublicPathstringjsonPath外部工具和链接使用的公开 OpenAPI 规范地址。内置 source-aware docs 数据使用 docs.assetsPublicPath / docs.assetsPath详见指南
contactobjectundefined联系信息
licenseobjectundefined许可证信息
serversarrayundefined服务器地址列表
tagsarrayundefined全局标签定义
tagGroupsArray<{ name: string; tags: string[] }>undefined显式输出 OpenAPI x-tagGroups vendor extension;内置 Vext Docs 默认导航不依赖它
guardSecurityMapRecord<string, string>undefinedGuard → Security Scheme 映射
securitySchemesobjectundefined安全方案定义
scalarobjectundefined已废弃兼容字段;仅显式配置时触发 warning,不影响内置 Vext Docs 页面
tryItOutEnabledbooleantrue已废弃 保留兼容,不影响 Vext Docs 默认实现
docExpansion'none' | 'list' | 'full''list'已废弃 保留兼容,不影响 Vext Docs 默认实现

docs.access.cacheKey 不是当前版本支持的配置字段。Vext 会拒绝该字段,避免让用户误以为文档访问链路已经提供 response cache 或 access result cache。

固定本地或部署 API 目标时,servers[].url 建议直接写带端口的完整 base URL,例如 http://127.0.0.1:3000。只有环境名、区域、租户或 API 版本这类真正会变化的 URL 片段,才建议使用 servers[].variablesdocs.tryItOut.defaultServer 用于控制 Try it out 初始选中的 server,docs.tryItOut.customServer 用于允许用户在浏览器里临时输入其他目标地址,不需要修改项目配置。

tagGroups 只有在显式配置时才会透传为 x-tagGroups。默认 Vext Docs renderer 使用 OpenAPI path segment 构建递归导航;tagGroups 主要用于下游 OpenAPI 工具明确消费该 vendor extension 的场景。

默认 Vext Docs renderer 会从 code docs 数据生成 Services / Utils / Models / Components / Plugins / Middlewares。Model 条目可展示静态 schema fields、enums、options、indexes、methods、hooks 和 usage;Plugins 与 Middlewares 可展示可推断的 lifecycle/bootstrap、app extension、middleware 类型、route usage 和源码链接;Locales / Config / Styles / Preload 属于可选高级静态来源,可在 docs.code 下显式开启,但不进入默认顶层文档入口;本地 loopback 文档页还可为 code docs 条目展示 Open source 链接,不需要新增单独配置项。

export default {
  openapi: {
    enabled: true,
    title: "My API",
    version: "1.0.0",
    description: "我的 API 文档",
    docs: {
      path: "/docs",
      renderer: "vext",
      code: {
        enabled: "auto",
      },
    },
    servers: [
      { url: "http://localhost:3000", description: "开发环境" },
      { url: "https://api.example.com", description: "生产环境" },
    ],
    tags: [
      { name: "用户", description: "用户管理接口" },
      { name: "订单", description: "订单管理接口" },
    ],
    securitySchemes: {
      bearerAuth: {
        type: "http",
        scheme: "bearer",
        bearerFormat: "JWT",
      },
    },
    guardSecurityMap: {
      auth: "bearerAuth",
    },
  },
};

guardSecurityMap 历史回退

用于把只声明 middleware 的历史路由映射到 OpenAPI Security Scheme。新的 Auth 示例应优先通过本地 route guard helper 使用 RouteOptions.auth,让运行时保护和 OpenAPI security 共用同一个真相源:

// 仅用于历史兼容:没有 RouteOptions.auth 的 middleware 名称推断
app.get("/profile", { middlewares: ["auth"] }, handler);
// ↑ OpenAPI 自动推断该路由需要 bearerAuth 认证

securitySchemes

支持的安全方案类型:

type说明必填字段
httpHTTP 认证schemebearer / basic
apiKeyAPI Keyname, inheader / query / cookie
oauth2OAuth 2.0
openIdConnectOpenID Connect

对于 in: "cookie"apiKey 安全方案和 validate.cookie 参数,内置文档可以展示字段,但浏览器 Try it out 不能直接设置受限的 Cookie header。如需手动 cookie 值,请使用同源浏览器 cookie 或 HTTP 客户端。


VextRequestContextConfig

AsyncLocalStorage 请求上下文配置。

字段类型默认值说明
enabledbooleantrue是否启用请求上下文
export default {
  requestContext: {
    enabled: false, // 禁用后可提升 3-8% RPS
  },
};

:::warning 禁用后以下功能失效:

  • Logger 自动注入 requestId
  • app.throw() 自动解析请求级 locale
  • app.fetch() 自动传播 requestId :::

VextFrontendConfig

内置前端构建与静态服务配置。

字段类型默认值说明
enabledbooleanfalse是否启用前端集成
frameworkstring'react'前端框架标签
rootstring'src/frontend'前端源码目录
pages.dirstring'pages'页面目录,相对 root 解析
pages.extensionsstring[]['.tsx', '.jsx', '.ts', '.js']页面、layout、错误页和 locale 模块扫描扩展名
pages.documentstring'pages/_document.html'document 模板路径,相对 root 解析
pages.errorDirstring'pages/error'错误页面目录,相对 root 解析
componentsDirstring'components'公共组件目录,相对 root 解析
styles.entrystring'styles/index.css'全局 CSS 入口,相对 root 解析
styles.jscssboolean | object{ enabled: true }Vext JSCSS 构建期 CSS 抽取与动态 CSS variables
styles.jscss.filesstring[]['**/*.style.ts', '**/*.style.js', '**/*.css.ts']JSCSS 源文件扫描 glob
styles.jscss.runtimeAdapter'css-variables' | 'none' | false'css-variables'通过 CSS custom properties 输出动态变量,或回退为静态 fallback 值
styles.jscss.dynamicVarsbooleantrue是否输出 JSCSS custom property 声明与 var(...) 引用
styles.jscss.recipesbooleantruerecipe variants 是否生成额外 class 与 CSS rules
assetsDirstring'assets'前端打包资产目录,相对 root 解析
entrystring'.vext/generated/frontend/browser-entry.tsx'自动生成的浏览器入口;通常不需要手写
indexHtmlstring'src/frontend/pages/_document.html'HTML document 模板
outDirstring开发期 .vext/client,生产期 dist/client前端输出目录
publicDirstring'public'会复制到前端输出目录的静态资源
publicPathstring'/'公开资源路径前缀
aliasobject内置 @frontend/@pages/@components/@styles/@assets前端安全 alias,不默认指向整个 src
spaFallbackboolean | object{ scopes: [] }只对显式声明的 client-router 子应用范围服务 fallback
spaFallback.enabledbooleantrue是否允许 scoped fallback 仲裁;无 scope 时不会接管路径
spaFallback.excludestring[]['/api/**', '/openapi.json', '/docs/**', '/_vext/docs/**']fallback 全局排除路径
spaFallback.scopes[]object[][]明确声明的 client-router 子应用范围
apiClientboolean | objecttrue生成 client contract 产物
apiClient.enabledbooleantrue是否输出 client-contract.jsonapi.generated.ts
render.ssrbooleantrue是否启用 SSR 渲染
render.fallback'client' | 'error''client'SSR 失败时回退客户端壳还是错误响应
render.timeoutMsnumber3000单次 SSR 超时时间
render.layoutbooleantrue是否启用嵌套 layout chain
errorPages.defaultstring'error/default'默认错误页 page id
errorPages.statusobject{ 404: 'error/404', 500: 'error/500' }状态码到错误页 page id 的映射
i18nobject{ enabled: false }前端页面文案层、SSR messages 与 {vext.lang}
i18n.sourcestring'locales'前端文案目录,相对 root 解析
i18n.defaultLocale'inherit' | string'inherit'默认 locale;inherit 表示跟随请求级 locale
i18n.detectstring[]['accept-language']SSR locale 探测来源
i18n.inject'used' | 'all''used'注入已使用 messages 还是全部 messages
i18n.clientSwitch'reload''reload'客户端切换 locale 的首期策略
i18n.clientLoad'current' | 'all''current'浏览器端只加载当前 SSR locale,或加载全部 locale
i18n.htmlLangbooleantrue是否写入 {vext.lang} / <html lang>
i18n.varybooleantrue是否按 locale 影响响应 vary/cache
dev.hotbooleantrue开发期前端热更新通道
dev.fastRefreshbooleantrueReact Fast Refresh
dev.transport'sse''sse'Vext dev event bus 传输方式
dev.overlaybooleantrue是否显示前端 dev browser rebuild 错误与 render refresh 提示 UI
dev.debounceMsnumber50文件变更事件防抖时间
dev.renderRefresh'prompt' | 'auto' | 'off''prompt'route/service 等 render 相关后端变更后的浏览器动作
build.targetstring | string[]'es2022'浏览器构建目标
build.minifyboolean生产期 true压缩前端产物
build.sourcemapboolean开发期 true生成前端 source map
build.clientobject继承共享 build 默认值浏览器 bundle 输出、hash 命名、splitting 与 external
build.client.assetsDirstring"assets"frontend.outDir 下的浏览器 bundle 资源子目录
build.client.splittingbooleantrue浏览器代码拆分
build.client.externalstring[][]浏览器 bundle 外置模块列表
build.client.externalRuntimeobject{}外置模块 import map URL 映射;React external 缺映射会构建失败
build.serverobjectserver/renderer.cjsSSR renderer bundle 输出
build.server.outFilestringserver/renderer.cjsfrontend.outDir 下的 SSR renderer 文件
build.vendorChunksboolean | object{ enabled: true }Vext-managed vendor entry 与共享 chunk 管理
build.budgetsobject全部 0前端资源大小预算;0 表示不限制
build.budgets.maxInitialJsGzipBytesnumber0首屏入口 JS gzip 预算
build.budgets.maxInitialJsBrotliBytesnumber0首屏入口 JS brotli 预算
build.budgets.maxRouteInitialJsBrotliBytesnumber0单 route 首屏 JS brotli 预算
build.budgets.maxAppOwnedInitialJsBrotliBytesnumber0排除 external runtime 后的应用自有首屏 JS brotli 预算
build.assets.inlineLimitnumber0import 型资源内联阈值;默认输出 hash 文件
build.css.modulesbooleantrue是否支持 CSS Modules 约定
build.diagnostics.metafilebooleantrue是否保留内部 esbuild metafile 诊断,供 size report / leak scan 使用
build.diagnostics.sizeReportbooleantrue是否生成体积报告
build.diagnostics.performanceReportbooleantrue是否在构建报告中保留路由级 initial JS 指标
build.diagnostics.leakScanbooleantrue阻断浏览器 bundle 误引入服务端模块
deploy.assetBaseUrlstringCDN 静态资源绝对前缀
deploy.crossOrigin'anonymous' | 'use-credentials'注入 script/link 时的 crossorigin 值
deploy.integritybooleanfalse是否把构建期 SRI 注入 JS/CSS 标签
deploy.uploadboolean | object{ enabled: false, exclude: ["**/*.map"] }静态资源上传配置;vext deploy assets 按 sha256 增量上传
export default {
  frontend: {
    enabled: true,
    framework: "react",
    publicDir: "public",
    publicPath: "/",
    spaFallback: {
      scopes: [
        {
          basePath: "/admin/app",
          page: "admin/app/shell",
          exclude: ["/admin/api/**"],
        },
      ],
    },
  },
};

默认 spaFallback.scopes 为空,因此未知 HTML 路径不会被自动吞成 SPA 页面。需要混合 SSR + client-router 子应用时,在 scopes[] 中声明具体 basePathspaFallback: true 仅作为兼容 shorthand,不推荐在企业级混合项目中使用。


VextClusterConfig

Cluster 多进程配置。完整接口定义见 src/types/app.ts VextClusterConfig

基础字段

字段类型默认值说明
enabledbooleanfalse是否启用 Cluster 模式(也可通过 VEXT_CLUSTER=1 开启)
workers'auto' | 'auto-1' | number'auto'Worker 数量('auto' = 检测到的可用 CPU 数;'auto-1' = 可用 CPU 数 - 1;number = 固定数量,clamp 到 [1, 64])
autoRestartbooleantrueWorker 崩溃后自动重启
maxRestartsnumber5快速重启检测窗口内允许的最大重启次数
restartWindownumber60000快速重启检测窗口(毫秒)
restartBaseDelaynumber1000重启间隔退避基数(毫秒)
restartMaxDelaynumber30000重启间隔上限(毫秒)
pidFilestring'.vext.pid'PID 文件路径(供 vext stop / vext reload 定位进程)
titlePrefixstring'vext'Worker 进程标题前缀
sticky'none' | 'ip''none'粘性会话模式('ip' 基于客户端 IP 分配固定 Worker,适用于 WebSocket / SSE)

healthCheck — 心跳检测

字段类型默认值说明
healthCheck.enabledbooleantrue是否启用 Worker 心跳检测
healthCheck.intervalnumber15000Master 发送心跳探测的间隔(毫秒)
healthCheck.timeoutnumber30000Worker 心跳超时阈值(毫秒),超时则强制重启

reload — 零停机滚动重启

cluster.reload 只配置 vext reload / SIGHUP 触发滚动重启时的时间参数。省略 cluster.reload 不会禁用滚动重启,框架会使用默认值。

字段类型默认值说明
reload.workerDelaynumber2000替换下一个 Worker 前的等待时间(毫秒)
reload.readyTimeoutnumber30000新 Worker 就绪超时(毫秒)
reload.shutdownTimeoutnumber10000旧 Worker 关闭超时(毫秒)
export default {
  cluster: {
    enabled: true,
    workers: "auto", // 使用 availableParallelism / cgroup v1 / os.cpus 检测可用 CPU
    autoRestart: true,
    maxRestarts: 5,
    healthCheck: {
      enabled: true,
      interval: 15000,
      timeout: 30000,
    },
    reload: {
      workerDelay: 2000,
      readyTimeout: 30000,
      shutdownTimeout: 10000,
    },
  },
};

也可通过环境变量启用(无需修改配置文件):

VEXT_CLUSTER=1 vext start

VextCacheConfig

路由级响应缓存全局配置。

字段类型默认值说明
enabledbooleantrue是否启用路由级响应缓存。设为 false 后不安装缓存中间件,也不会打开 Redis/MultiLevel 连接
defaultTtlnumber60000路由未指定 TTL 时的默认值,单位毫秒
maxEntriesnumber1000Memory 模式快捷配置:最大缓存条目数
maxMemorynumberMemory 模式快捷配置:最大内存占用 bytes
cleanupIntervalnumber0Memory 模式快捷配置:周期清理间隔,0 表示只做惰性清理
cacheHubobjectMemory底层响应缓存运行时配置
export default {
  cache: {
    enabled: true,
    defaultTtl: 120_000,
    maxEntries: 2000,
  },
};

Memory 完整配置:

export default {
  cache: {
    defaultTtl: 60_000,
    cacheHub: {
      mode: "memory",
      maxEntries: 1000,
      maxMemory: 50 * 1024 * 1024,
      cleanupInterval: 30_000,
      enableStats: true,
    },
  },
};

Redis 配置:

export default {
  cache: {
    defaultTtl: 2_000,
    cacheHub: {
      mode: "redis",
      url: "redis://localhost:6379",
      deleteCommand: "unlink",
      lease: {
        waitForOwner: 1_000,
        onTimeout: "fetch",
      },
      distributed: {
        channel: "vext:response-cache",
      },
    },
  },
};

MultiLevel 配置:

export default {
  cache: {
    defaultTtl: 60_000,
    cacheHub: {
      mode: "multi-level",
      memory: { maxEntries: 1000 },
      redis: { url: "redis://localhost:6379" },
      writePolicy: "both",
      backfillOnRemoteHit: true,
      remoteTimeout: 50,
      lease: true,
    },
  },
};

cacheHub 只接受 response-cache-kit/cache-hub 配置,不接受自定义 Store。路由级响应缓存通过 RouteOptions.cache 配置。公开配置单位使用毫秒;响应头中的 Cache-Control: max-age 会按 HTTP 标准输出秒。详见 响应缓存指南


DEFAULT_CONFIG

框架内置默认配置的完整值:

import { DEFAULT_CONFIG } from 'vextjs';

// DEFAULT_CONFIG 的完整内容:
{
  port: 3000,
  host: '0.0.0.0',
  adapter: 'native',
  trustProxy: false,
  middlewares: [],
  cors: {
    enabled: true,
    origins: ['*'],
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],
    headers: ['Content-Type', 'Authorization', 'X-Request-Id'],
    credentials: false,
  },
  rateLimit: {
    enabled: true,
    max: 100,
    window: 60,
    message: 'Too Many Requests',
    keyBy: 'ip',
  },
  requestId: {
    enabled: true,
    header: 'x-request-id',
    responseHeader: 'x-request-id',
  },
  logger: {
    level: 'info',
  },
  shutdown: {
    timeout: 10,
  },
  server: {},
  response: {
    hideInternalErrors: true,
    wrap: true,
  },
  session: {
    enabled: false,
    name: 'vext.sid',
    ttl: 86400,
    rolling: false,
    autoCommit: true,
    idLength: 32,
    cookie: {
      httpOnly: true,
      sameSite: 'lax',
      path: '/',
      secure: 'auto',
    },
  },
  csrf: {
    enabled: false,
    mode: 'auto',
    methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
    headerNames: ['x-csrf-token', 'x-xsrf-token'],
    bodyField: '_csrf',
    cookie: {
      name: 'vext.csrf',
      httpOnly: false,
      sameSite: 'lax',
      path: '/',
      secure: 'auto',
    },
    fetchMetadata: true,
    origin: false,
  },
  securityHeaders: {
    enabled: false,
    preset: 'basic',
  },
  bodyParser: {
    enabled: true,
    maxBodySize: '1mb',
  },
  accessLog: {
    enabled: true,
    level: 'info',
    skipPaths: [],
  },
  openapi: {
    enabled: false,
  },
  requestContext: {
    enabled: true,
  },
  frontend: {
    enabled: false,
  },
}

VextUserConfig

用户配置的输入类型,所有字段均为可选。由 loadConfig() 合并默认值后生成完整的 VextConfig

import type { VextUserConfig } from "vextjs";

const config: VextUserConfig = {
  port: 8080,
  logger: { level: "debug" },
};

export default config;

VextSessionConfig

config.session.enabled: true 会在生产、开发、测试和软重载链路中自动注册 Session。显式 session() 中间件仅用于作用域化或手动注册场景。

字段类型默认值说明
enabledbooleanfalse是否自动全局注册 Session
namestring'vext.sid'session cookie 名称
ttlnumber86400store TTL,单位秒
rollingbooleanfalse每次请求刷新 store TTL 与 cookie
autoCommitbooleantrue响应发送前自动持久化 dirty session
idLengthnumber32CSPRNG session id 的随机字节长度,范围 16-128
cookieVextSessionCookieOptions见下方session cookie 属性
storeVextSessionStorememory store面向共享部署的自定义异步 store

VextSessionCookieOptions 基于 CookieSerializeOptions,并额外支持 secure: boolean | "auto"。Cookie 选项包含 domainpathexpiresmaxAgehttpOnlysecuresameSiteprioritypartitionedencode

VextSessionStore 必须实现 get(id)set(id, data, ttlSeconds)delete(id)。可选方法包括 touch(id, ttlSeconds)clearExpired()close()。配置 Store 和已启用的手动 Session 运行时会在应用关闭时调用 close()

生产 cache-backed session 推荐使用 vextjs 根入口导出的 createCacheSessionStore(cacheLike, options?)。它接收具备 getsetdel 的结构型 VextCacheLike,把 session TTL 秒转换为 cache 毫秒,默认写入 JSON string,且只有传入 options.close 时才暴露 close()config.cache.cacheHub 仍然只是路由响应缓存配置,不会注入 Session Store。

RouteOptions.session 接受 falsetrue{ enabled?, rolling?, autoCommit? },可为单个路由关闭 Session,也可在全局运行时关闭时单独启用。


VextCsrfConfig

config.csrf 用于配置内置 CSRF 中间件。enabled: true 会在 body parsing 与插件全局中间件之后自动全局注册 CSRF;也可以保持禁用,并手动注册 csrf() 保护指定路径。

字段类型默认值说明
enabledboolean应用配置默认 false;手动 csrf() 默认 true是否启用全局自动注册
mode"auto" | "session" | "signed-cookie""auto"token 存储模式
secretstringundefinedsigned-cookie 模式必填
methodsstring[]["POST", "PUT", "PATCH", "DELETE"]需要 CSRF 校验的 unsafe methods
headerNamesstring[]["x-csrf-token", "x-xsrf-token"]接收 token 的请求头名称
bodyFieldstring | false"_csrf"接收 token 的 body 字段;false 表示禁用 body token
cookieCookieSerializeOptions{ name: "vext.csrf", sameSite: "lax", path: "/" }签名 double-submit cookie 属性
fetchMetadatabooleantrue拒绝 Sec-Fetch-Site: cross-site unsafe 请求
originfalse | { trustedOrigins?: string[] }false可选 Origin/Referer 同源校验

路由可通过 route options { csrf: false } 跳过 CSRF。


VextSecurityHeadersConfig

config.securityHeaders 用于启用 Vext 内置浏览器安全响应头。默认关闭。preset: "basic" 是多数应用的低破坏主路径;strictcustom 都是显式 opt-in。

字段类型默认值说明
enabledbooleanfalse自动注册内置 Security Headers 中间件
preset"basic" | "strict" | "custom""basic"响应头预设
contentTypeOptions"nosniff" | false由 preset 决定控制 X-Content-Type-Options
referrerPolicystring | false由 preset 决定控制 Referrer-Policy
frameOptions"DENY" | "SAMEORIGIN" | false由 preset 决定控制 X-Frame-Options
hstsfalse | { enabled?: boolean; maxAge?: number; includeSubDomains?: boolean; preload?: boolean; force?: boolean }basic 中为 false控制 Strict-Transport-Security;默认仅 HTTPS 请求发送,除非 force: true
contentSecurityPolicyfalse | string | objectfalse控制 CSP 或 CSP report-only
permissionsPolicyfalse | string | Record<string, boolean | string[]>basic 中为 false控制 Permissions-Policy
crossOriginOpenerPolicyfalse | "same-origin" | "same-origin-allow-popups" | "unsafe-none"basic 中为 false控制 COOP
crossOriginEmbedderPolicyfalse | "require-corp" | "credentialless" | "unsafe-none"false控制 COEP;strict 也不会默认开启
crossOriginResourcePolicyfalse | "same-origin" | "same-site" | "cross-origin"basic 中为 false控制 CORP
headersRecord<string, string>{}最后合并的自定义响应头
skipPathsstring[][]精确路径或尾部 * 前缀跳过
export default {
  securityHeaders: {
    enabled: true,
    preset: "basic",
    contentSecurityPolicy: {
      reportOnly: true,
      directives: {
        "default-src": ["'self'"],
        "upgrade-insecure-requests": true,
      },
    },
  },
};

basic 发送 X-Content-Type-Options: nosniffReferrer-Policy: strict-origin-when-cross-originX-Frame-Options: SAMEORIGINstrict 额外开启 HTTPS-only HSTS、最小 Permissions-Policy、COOP 和 CORP,但 CSP 与 COEP 仍需显式配置。custom 只发送你配置的字段。路由可通过 { securityHeaders: false } 跳过。


loadConfig

配置加载函数,接收配置目录路径并执行完整配置链合并。

import { loadConfig } from "vextjs";
import { join } from "node:path";

const config = await loadConfig(join(process.cwd(), "src/config"), {
  rootDir: process.cwd(),
  command: "start",
  isBuilt: false,
});
// config: VextConfig(已合并、已冻结)

通常不需要手动调用,bootstrap() 内部会自动调用 loadConfig()。合并顺序为:DEFAULT_CONFIG < default < config profile < local < bootstrap provider patch < CLI override


环境变量覆盖

部分配置支持通过环境变量覆盖:

环境变量对应配置说明
VEXT_PORTportCLI/运行时传递的严格整值端口覆盖
VEXT_HOSThostCLI/运行时传递的监听地址覆盖
VEXT_CONFIG选择要加载的配置 profile
NODE_ENV运行时模式;vext start 固定为 production
VEXT_CLUSTERcluster.enabled设为 1 启用集群
VEXT_PORT=8080 VEXT_CONFIG=sg-sit vext start

类型声明扩展

插件可通过 declare moduleVextConfig 添加自定义字段:

// types/vext.d.ts
declare module "vextjs" {
  interface VextConfig {
    redis?: {
      host: string;
      port: number;
      password?: string;
    };
  }
}

之后在配置文件中使用将获得完整的类型提示:

// src/config/default.ts
export default {
  redis: {
    host: "localhost",
    port: 6379,
  },
};