目录结构
当你创建一个新的 AdonisJS 应用时,它会带有一套精心设计的默认目录结构,旨在让项目保持整洁、可预期且易于重构。
这套结构反映了适用于大多数项目的约定,但 AdonisJS 并不会将你锁死在其中。你可以自由地重新组织文件与目录,以契合团队的协作方式。
根据你选择的入门套件,某些文件或目录可能有所不同。例如,Inertia 入门套件包含一个顶层的 inertia 目录,而 Hypermedia 入门套件则不含此目录。
概述
下面是一个新建的 AdonisJS 项目大致的样子。
├── app
├── bin
├── config
├── database
├── resources
├── start
├── tests
├── ace.js
├── adonisrc.ts
├── eslint.config.js
├── package-lock.json
├── package.json
├── tsconfig.json
└── vite.config.ts
API 入门套件是一个由 Turborepo 管理的 monorepo,包含两个 workspace:
├── apps
│ ├── backend # AdonisJS 应用
│ │ ├── app
│ │ ├── bin
│ │ ├── config
│ │ ├── database
│ │ ├── start
│ │ ├── tests
│ │ ├── ace.js
│ │ ├── adonisrc.ts
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── frontend # 你的前端应用
│ ├── package.json
│ └── ...
├── package.json # 根 package.json,定义 workspaces
├── package-lock.json
└── turbo.json # Turborepo 流水线配置
apps/backend 目录包含标准的 AdonisJS 应用——下面所有小节(app/、config/、start/ 等)都适用于该目录。apps/frontend 目录则是你搭建前端框架(TanStack Start、Next.js、Nuxt 等)的地方。
根目录的 package.json 定义了 workspaces:
{
"workspaces": ["apps/*"]
}
而 turbo.json 配置了 dev、build 等脚本以跨两个应用运行。当你从项目根目录运行 npm run dev 时,Turborepo 会并行启动后端与前端开发服务器。
每个目录和文件都有特定用途。下面各小节将解释每一项的作用,以及你通常会在其中找到什么。
app/
app 目录用于组织应用领域逻辑相关的代码。例如控制器、模型、邮件、中间件等都位于 app 目录下。
你可以自由地在 app 目录下创建额外的文件夹,以更好地组织代码库。
├── app
│ ├── controllers
│ ├── exceptions
│ ├── mails
│ ├── middleware
│ ├── models
│ ├── transformers
│ └── validators
bin/
bin 目录包含用于在不同环境中启动 AdonisJS 应用的入口文件。
console.ts文件使用 Ace 命令行框架来执行 CLI 命令。server.ts文件在 Web 环境中启动应用以监听 HTTP 请求。test.ts文件用于为测试环境引导启动应用。
除非你想定制应用在特定上下文中的启动方式,否则通常无需修改这些文件。
├── bin
│ ├── console.ts
│ ├── server.ts
│ └── test.ts
config/
所有应用级与第三方配置文件都存放在 config 目录下。你也可以将仅限本应用使用的配置存放在该目录中。
├── config
│ ├── app.ts
│ ├── auth.ts
│ ├── bodyparser.ts
│ ├── database.ts
│ ├── hash.ts
│ ├── limiter.ts
│ ├── logger.ts
│ ├── mail.ts
│ ├── session.ts
│ ├── shield.ts
│ ├── static.ts
│ └── vite.ts
database/
database 目录存放与数据库层相关的产物。默认情况下,AdonisJS 随附已为 SQLite 配置好的 Lucid ORM;切换数据库无需重新组织此文件夹。
migrations/- 带版本的 schema 变更seeders/- 用于插入初始或测试数据的脚本factories/- 在测试或种子文件中生成模型实例的蓝图schema.ts- 模型所使用的自动生成数据库 schemaschema_rules.ts- 验证器所使用的自动生成 schema 规则
另请参阅: Lucid 文档
database/
├── migrations/
├── seeders/
├── factories/
├── schema.ts
└── schema_rules.ts
providers/
providers 目录用于存放应用所使用的
服务提供者
。你可以使用 node ace make:provider 命令创建新的提供者。
├── providers
│ └── app_provider.ts
public/
public 目录包含原始的静态资源,这些资源无需任何编译步骤即可直接提供给浏览器。该目录中的文件可通过 http://localhost:3333/public/<file-name> 这样的 URL 经 HTTP 公开访问。
API 入门套件不包含 public 目录,因为后端只返回 JSON 响应,不提供静态资源。
存放于该目录中的典型文件包括:
- 网站图标
(favicon.ico) - 爬虫规则文件
(robots.txt) - 静态图片
(logo.png, social-banner.jpg) - 可下载资源
(manual.pdf)
resources/
resources 目录存放 Edge 模板,以及尚未编译的前端资源(如 CSS 与 JavaScript 文件)。
API 入门套件不包含 resources 目录,因为后端只返回 JSON 响应,不渲染 HTML 模板。
对于使用 Inertia(配合 Vue 或 React)的应用,前端代码保存在 inertia 目录中,而 resources 目录仅包含根 Edge 模板。你可以把这个根模板理解为包含了前端应用 HTML 外壳的 index.html 文件。
├── resources
│ ├── css
│ ├── js
│ └── views
│ ├── home.edge
├── resources
│ └── views
│ └── inertia_layout.edge
inertia/
inertia 目录仅存在于使用 Inertia 入门套件的项目中。它代表一个包含前端源代码的子应用,包括 React 或 Vue 组件、页面以及配套的工具函数。
pages/- 存放用 React 或 Vue 编写的 Inertia 页面。app.(tsx|vue)- 客户端应用的主入口。ssr.(tsx|vue)- 服务端渲染(SSR)的入口。tsconfig.json- 前端代码库的 TypeScript 配置文件。其默认值针对浏览器环境、JSX/TSX 语法以及基于 Vite 的构建进行了优化。
你可以自由创建 components/、layouts/、utils/ 等额外的子文件夹来组织前端代码。
├── inertia
│ ├── css
│ ├── layouts
│ ├── pages
│ │ └── home.tsx
│ ├── app.tsx
│ ├── ssr.tsx
│ ├── tsconfig.json
│ └── types.ts
前端与后端的清晰分离
AdonisJS 在后端与前端之间保持着清晰的边界。你绝不应该将后端代码(如模型、服务或转换器)导入到前端应用中。
在实践中,你的前端通过 HTTP 请求与后端通信,并接收纯 JSON 数据。AdonisJS 鼓励你显式地建模这一现实:数据通过 API 响应来获取和转换,而不是被隐藏在共享抽象的背后。
共享类型
前端仍然可以依赖 AdonisJS 自动生成的共享 TypeScript 类型。这些类型存放在 .adonisjs/client 目录中,包含路由、props 以及其他共享契约的类型定义。
这种方式让前端代码在保持强类型的同时,又不破坏客户端与服务端之间的分离。
你应该将 .adonisjs 目录提交到版本控制中。框架依赖这些生成的文件来进行导入解析(例如 #generated/controllers)和 TypeScript 类型检查。缺少它们,生产构建和 CI 流水线都会失败。
我们建议阅读 类型生成文档 ,了解 AdonisJS 是如何创建共享类型的。
start/
start 目录包含你希望在应用启动生命周期中导入的文件。例如,用于注册路由和定义事件监听器的文件应放在此目录中。
├── start
│ ├── env.ts
│ ├── kernel.ts
│ └── routes.ts
AdonisJS 不会自动导入 start 目录中的文件。它只是作为一个约定来归类相似的文件。我们建议阅读
预加载文件
与
应用启动生命周期
,以便更好地理解哪些文件应当保留在 start 目录下。
tests/
tests 目录包含自动化测试。AdonisJS 使用
Japa
测试运行器。
测试组织在特定的子文件夹中。运行 unit(单元)测试时,AdonisJS 会引导启动应用,但不会启动 HTTP 服务器;而在 functional(功能)测试中,我们会启动 HTTP 服务器与 Vite 开发服务器。
另请参阅: 测试文档
├── tests
│ ├── unit
│ ├── functional
│ └── bootstrap.ts
tmp/
应用生成的临时文件存放在 tmp 目录中。例如,这些可能是用户上传的文件(开发期间生成),或写入磁盘的日志。
tmp 目录必须被 .gitignore 规则忽略,你也不应将其复制到生产服务器上。
ace.js
ace.js 文件是执行 Ace 命令的入口。该文件配置了一个 JIT TypeScript 编译器,然后导入 bin/console.ts 文件。
adonisrc.ts
adonisrc.ts 是项目的清单文件。它告诉 AdonisJS 如何发现并加载应用的各个部分,并包含以下配置:
- 目录别名(对应
app、start等) - 预加载文件
- 已注册的提供者与服务命令
- Assembler 钩子
另请参阅: AdonisRC 文件参考
eslint.config.js
该文件为项目配置 ESLint。其默认规则针对 TypeScript 与 AdonisJS 约定进行了调优。你可以修改或扩展此配置以契合团队的风格。
package.json 与 package-lock.json
package.json- 项目元数据、脚本与依赖声明。package-lock.json- 锁定确切的依赖版本,以保证安装的一致性。
tsconfig.json
tsconfig.json 控制 TypeScript 编译器选项、模块解析与路径别名。所提供的配置同时适用于开发与生产构建。不过,你可以调整编译器设置以匹配特定的工作流。
AdonisJS 依赖 experimentalDecorators 来支持依赖注入、Ace 命令以及 Lucid ORM。
以下配置选项是 AdonisJS 内部正常运作所必需的。
{
"compilerOptions": {
"module": "NodeNext",
"isolatedModules": true,
"declaration": false,
"outDir": "./build",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true
},
"include": ["**/*", ".adonisjs/server/**/*"]
}
{
"compilerOptions": {
"module": "NodeNext",
"isolatedModules": true,
"declaration": false,
"outDir": "./build",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"skipLibCheck": true
},
"references": [
{
"path": "./tsconfig.inertia.json"
}
],
"include": ["**/*", ".adonisjs/server/**/*"]
}
vite.config.ts
当项目使用 Vite(Edge 或 Inertia 入门套件)时,vite.config.ts 定义了前端资源如何编译与提供。如果你需要特殊的打包行为,可在此自定义入口、别名与插件设置。