AI Web 项目的文件到底应该怎么放?

专栏:AI 全栈开发|05

|-------------------------------------------------------------------------------------------------|
| 技术栈定下来以后,真正打开 IDE 时你面对的不是架构图,而是一个空文件夹。这一篇不追求"生产级目录看起来多专业",而是从 5 个文件开始:先让每个东西有明确归属,再随着项目变复杂逐步扩展。 |

一、目录结构解决的不是"好不好看",而是以后去哪找代码

刚建项目时,所有文件放根目录也能跑。真正的问题通常在几周后才出现:API 路由和模型调用混在一起,迁移脚本不知道放哪,Docker 配置散落,谁都不敢删"final2.py"。

所以目录结构最实用的目标只有两个:

• 看到一个文件名,大致知道它应该属于哪类职责。

• 想修改一类功能时,知道主要应该去哪个目录找。

只要这两点做到了,目录就已经在帮你,而不是在给项目增加仪式感。

二、第一天不要先建 6 个空目录

图 1 项目目录应该跟着真实职责生长,不需要第一天把"目标态"全部建出来

按照前面专栏的路线,第一版只有 Frontend 和 Backend,那么目录完全可以先这样:

复制代码
app/
├── README.md
├── .gitignore
├── .env.example
├── frontend/
└── backend/

这已经足够建立最重要的边界:浏览器侧代码进 frontend,可信服务端代码进 backend。

等真的有数据库迁移、部署配置、运维脚本和架构文档,再把 scripts、infra、docs 加进来。

三、为什么前端和后端建议分目录

因为它们本来就是两套运行环境:Frontend 依赖 Node / 浏览器生态,Backend 依赖 Python 和服务端库,构建、测试、环境变量也不一样。

分开以后,一个非常简单的规则就成立了:

frontend/ 不直接 import backend/ 的 Python 代码;backend/ 也不去读 frontend/src 里的业务实现。两边通过 HTTP / Streaming API 等契约通信。

如果以后想共享类型,也更推荐通过 OpenAPI 生成客户端、共享 Schema 包等明确机制,而不是相对路径跨目录乱 import。

四、Monorepo 是一种方便的选择,不是"唯一最优"

对一个中小团队、同一个产品、前后端经常一起改的项目,把 frontend 和 backend 放在同一个 Git 仓库里确实很方便:一个 PR 能同时改接口和页面,CI 也能一起跑。

但这不代表 Monorepo 对所有组织都是最优。大型组织、独立发布节奏、不同权限边界、已有多仓库平台,都可能有充分理由拆仓。

|---------------------------------------------------------------|
| 本专栏使用 Monorepo,是为了学习和项目演进更连贯。真正要记的是"职责边界",不是"所有 AI 项目必须一个仓库"。 |

五、项目长大以后,各目录分别应该管什么

图 2 好目录的核心是边界:不同职责各有归属,跨边界通过契约连接

frontend/:浏览器里运行的产品代码

页面路由、组件、Hooks、Streaming 客户端、上传 UI、前端状态都在这里。

复制代码
frontend/
├── src/
│   ├── app/          # Next.js 页面 / 路由
│   ├── components/   # 可复用 UI
│   ├── hooks/        # useChat 等
│   └── lib/          # API client、stream parser
├── public/
├── package.json
└── tsconfig.json

backend/:可信服务端的业务代码

路由只负责 HTTP 边界,真正的模型调用、RAG、文件服务等放到 services;数据库访问集中到 repositories;配置和安全公共代码放 core。

复制代码
backend/
├── app/
│   ├── main.py
│   ├── api/            # 路由层
│   ├── services/       # 业务 / AI 编排
│   ├── repositories/   # DB / Cache 数据访问
│   ├── schemas/        # 请求 / 响应模型
│   └── core/           # config / auth / logging
├── tests/
└── pyproject.toml

这里的分层也不是硬性教条。项目只有两三个接口时,services 和 repositories 可以很轻;不要为了目录完整,把一行函数拆成五层。

scripts/:有明确生命周期的"动作"

数据库初始化、一次性数据回填、导入测试数据、迁移辅助脚本等可以放在 scripts。

关键不是"脚本必须一次性",而是它们不是在线请求路径里的业务模块。能重复执行的运维脚本也完全可以放这里,只要命名清楚、行为可控。

infra/:部署与基础设施定义

Docker Compose、Terraform、Kubernetes manifests、反向代理配置等可以放 infra。

但 Dockerfile 放在哪里没有唯一答案。很多项目会把 frontend/Dockerfile、backend/Dockerfile 跟应用源码放在一起,因为构建上下文更直观;也有团队集中管理。选择一种规则并保持一致即可。

docs/:记录代码解释不了的"为什么"

README 解决"怎么跑";docs/ 更适合保存架构总览、复杂流程、API 约定和 ADR。

ADR 最有价值的不是记录"用了 PostgreSQL",而是记录"为什么当时选择 PostgreSQL、考虑过什么替代方案、什么时候重新评估"。

六、根目录应该放什么

根目录是整个仓库的入口,适合放跨前后端都需要知道的契约文件。

|----------------------------|-----------------------|-------------------|
| 文件 | 作用 | 注意 |
| README.md | 启动、测试、目录导航 | 新同事先看这里 |
| .gitignore | 忽略构建产物、虚拟环境、本地 Secret | 不要把 .env 提交 |
| .env.example | 示例配置 Key 与说明 | 只放占位值,不放真实 Secret |
| compose.yaml(按需) | 本地统一启动多个依赖服务 | 项目不需要容器时可暂时没有 |
| Makefile / task runner(按需) | 统一常用开发命令 | 不是必需品 |

`.env.example` 不是生产配置的"唯一真相"。它更像开发者能看到的配置说明和模板;真正的 staging / prod Secret 应由部署平台或 Secret Manager 管理。

七、dev / staging / prod:不要追求"环境长得一模一样"

图 3 环境应该共享代码和契约,但基础设施规模与实现可以不同

原稿要求三套环境从第一天都用同一套 docker-compose,这个说法太死。更实际的原则是:

• 应用代码尽量同源,不通过改源码切换环境。

• 配置 Key 和接口契约尽量一致,Value 由环境注入。

• 数据库迁移流程、安全规则、关键依赖版本要可重复。

• dev 可以用本地依赖,prod 可以用托管数据库或 Kubernetes;基础设施不必逐字相同。

Staging 的目标是尽可能验证生产关键行为,但是否值得维护完整 staging,也取决于产品规模和团队成本。小项目未必第一天就需要三套完整环境。

八、一个更适合本专栏继续扩展的目录

到真正加入数据库、文件、Worker 和部署后,可以长成下面这样:

复制代码
app/
├── README.md
├── .gitignore
├── .env.example
├── frontend/
│   ├── src/
│   │   ├── app/
│   │   ├── components/
│   │   ├── hooks/
│   │   └── lib/
│   └── package.json
├── backend/
│   ├── app/
│   │   ├── api/
│   │   ├── services/
│   │   ├── repositories/
│   │   ├── schemas/
│   │   └── core/
│   ├── tests/
│   └── pyproject.toml
├── worker/             # 出现独立长任务进程后再加
├── scripts/
├── infra/
└── docs/

这里特意没有单独建 docker/。Dockerfile 是否跟应用放一起、是否集中到 infra,属于团队约定,不值得在第 05 篇把它说成"正确答案"。

九、几个最容易把目录越设计越复杂的误区

• 误区 1:目录越多越专业。空目录只会增加认知负担,职责真的出现再建。

• 误区 2:所有后端代码都拆 Router / Service / Repository。分层是为了隔离复杂度,不是为了给三行 CRUD 增加模板。

• 误区 3:Monorepo 是所有团队的最优解。它适合本专栏和很多中小团队,但不是组织架构定律。

• 误区 4:dev、staging、prod 必须用完全相同的部署方案。应该一致的是行为和契约,不是机器数量或云产品。

• 误区 5:.env.example 管理全部环境变量值。它只能进仓库做模板;真实 Secret 不应该进入 Git。

• 误区 6:为了共享代码让前端直接 import 后端目录。跨运行时边界最好走 API / Schema 等明确契约。

十、目录什么时候应该重构

目录结构不需要追求"三年不动"。当下面情况开始频繁出现,就说明边界需要调整:

• 一个目录里出现几十个职责完全不同的文件,找代码越来越慢。

• 同一类逻辑在多个目录重复出现。

• 每次改一个模块都必须同时修改很多不相关目录。

• 部署、测试或权限边界已经跟当前目录划分不一致。

好的目录不是永远不变,而是变化有原因、有迁移路径,不是每周凭感觉换一次。

十一、这一篇只需要记住一个原则

目录结构的价值不是提前预测三年后的所有文件,而是让"现在已经存在的职责"有稳定边界,并且给下一阶段的复杂度留出自然生长的位置。

十二、下一篇

下一篇 06《Browser 到 Server,一次请求到底发生了什么?》会从文件结构进入运行时:用户点下发送以后,请求怎样从浏览器到 FastAPI,再怎样把响应送回来。到那时,frontend 和 backend 之间那条"HTTP 线"会真正变得透明。

相关推荐
AIyy8661 小时前
PPT找不到合适配图?输入文字描述直接AI生成,2026AI绘图工具怎么选
人工智能
愚公搬代码1 小时前
【愚公系列】《Web应用安全》003-测试环境的搭建
前端·安全
_codemonster1 小时前
主流前端技术分层选型
前端
xiongmaogeo1 小时前
外贸企业如何利用GEO优化,抢占海外AI平台的搜索流量
人工智能·chatgpt·facebook
大模型搬砖师1 小时前
高校科研管理上 AI:科研处、课题组、信息中心的三方分歧怎么调和
人工智能·安全
小沈同学呀1 小时前
【Agent开发第五期】Tool Use 工具调用,给 Agent 装上“手“
人工智能·工具调用·functioncalling·agent开发·tooluse·从零开发ai助手
tianxuanjg1 小时前
机器人精密零件:为何样品合格,批量却频频超差?
人工智能·经验分享·机器人·无人机·制造·材质
隔窗听雨眠1 小时前
OceanBase接入DeepSeek:数据库与AI的深度融合如何改写企业数据规则
数据库·人工智能·oceanbase