项目结构
VextJS 遵循 约定优于配置 的设计理念,通过固定的目录结构实现自动扫描、加载和注册,无需手动配置路由映射或服务注入。
标准目录结构
各目录详解
src/config/ — 配置目录
框架启动时,config-loader 按以下顺序加载配置文件并深度合并:
环境文件通过 NODE_ENV 环境变量自动匹配。例如 NODE_ENV=production 时加载 production.ts。
配置采用深度合并(deep merge),你只需在环境文件中声明需要覆盖的字段。middlewares 数组使用智能 patch 策略(按 name 匹配并覆盖),而非简单的数组替换。
src/routes/ — 路由目录
路由文件由 router-loader 自动扫描,文件路径直接映射为 URL 前缀。每个文件使用 defineRoutes() 导出路由定义。
路径映射规则
动态参数
使用 [paramName] 语法表示动态路由参数,加载时自动转换为 :paramName:
文件内的子路由
每个文件内部可以注册多个子路由。路径会自动拼接文件级前缀:
排除规则
以下文件会被自动跳过,不作为路由加载:
- 测试文件:
*.test.ts、*.spec.ts - 以
_或.开头的文件/目录 node_modules目录
src/services/ — 服务目录
服务文件由 service-loader 自动扫描,每个文件导出一个 class,构造函数接收 app 参数。实例化后自动挂载到 app.services。
命名映射规则
文件名自动从 kebab-case 转换为 camelCase。子目录会映射为嵌套对象。
服务类写法
service-loader 内置循环依赖检测机制。如果 ServiceA 在构造函数中直接访问 app.services.b,而 ServiceB 也访问 app.services.a,框架会在启动时检测到并报错。
推荐做法:在构造函数中只保存 app 引用,在方法中按需访问其他 service(延迟访问)。
src/middlewares/ — 中间件目录
中间件文件由 middleware-loader 自动扫描。每个文件导出一个通过 defineMiddleware 或 defineMiddlewareFactory 标记的中间件。
文件名即中间件名,在配置和路由中通过名称引用:
使用时,先在配置中声明白名单,然后在路由中引用:
详见 中间件 章节。
src/plugins/ — 插件目录
插件文件由 plugin-loader 自动扫描,按 dependencies 声明进行拓扑排序后依次执行 setup()。
详见 插件 章节。
src/locales/ — 国际化目录
语言包文件由 i18n-loader 自动扫描,文件名即语言代码。加载后注册到 schema-dsl 的 i18n 系统,与 app.throw() 联动。
详见 国际化 (i18n) 章节。
自动扫描加载顺序
框架启动时(bootstrap)按以下顺序加载各目录:
这个顺序确保:
- 配置在所有模块之前就绪
- 插件可以扩展
app对象(如注入数据库连接) - 中间件在路由注册前就绪
- 服务在路由之前注入,路由 handler 中可以安全访问
app.services
package.json 要求
VextJS 项目必须声明为 ESM 模块:
tsconfig.json 推荐配置
构建产物 dist/
执行 vext build 后,src/ 下的 TypeScript 文件会被编译到 dist/ 目录,保持相同的目录结构。生产模式下(vext start)直接从 dist/ 加载。
:::tip 开发 vs 生产
vext dev:直接从src/加载.ts文件(通过 esbuild 即时编译),支持热重载vext start:从dist/加载.js文件,需要先执行vext build:::