从零搭建 Web 项目的工程化规范全指南¶
一句话说明:以 Python/FastAPI + SQLite + Nginx + Linux 为例,覆盖一个真实 SaaS 项目从开发到上线的 13 项工程化规范,每项给出"为什么、怎么做、用什么工具"。
核心知识点速查表¶
| 知识点 | 说明 |
|---|---|
| 阅读前说明 | 见对应章节 |
| 一、版本控制(Git) | 见对应章节 |
| 二、分支管理策略 | 见对应章节 |
| 三、远程仓库 | 见对应章节 |
| 四、环境隔离 | 见对应章节 |
阅读前说明¶
本文面向已经会写代码、但没有完整上线过项目的开发者。每个章节分三档标注:
| 标记 | 含义 |
|---|---|
| [必须] | 不做就是埋雷,上线必出事 |
| [推荐] | 做了省心省力,团队协作必备 |
| [进阶] | 锦上添花,中大型项目再考虑 |
全文以一个假设项目为例:
项目名:t2d-api(2型糖尿病肠道菌群分析平台)
技术栈:FastAPI 0.115+ + SQLite + Nginx
运行环境:Python 3.12(FastAPI 0.130+ 最低要求 Python 3.10)
服务器:Ubuntu 24.04 LTS
包管理:uv(2025-2026 年 Python 生态首选工具)
一、版本控制(Git)¶
为什么需要¶
不用 Git 的后果: - 你的代码只有一份,硬盘坏了就全没了 - "上次改了什么来着?"——没有历史记录 - 多人协作靠微信传文件,覆盖别人代码
1.1 初始化仓库 [必须]¶
# 创建项目目录并初始化
mkdir t2d-api && cd t2d-api
git init # 初始化 Git 仓库
# 设置用户信息(首次使用 Git 必须配置)
git config user.name "你的名字" # 提交记录里显示的名字
git config user.email "your@email.com" # 和 GitHub 账号邮箱一致
1.2 .gitignore 最佳实践 [必须]¶
白话:告诉 Git "这些文件不要管"。不配 .gitignore,密码、临时文件、几百MB的模型文件全传上去。
# ===== Python =====
__pycache__/ # Python 编译缓存,每次运行自动生成
*.py[cod] # .pyc .pyo .pyd 编译文件
*.egg-info/ # 包安装信息
dist/ # 打包产物
build/ # 构建临时文件
.venv/ # 虚拟环境目录(不要提交几百MB的依赖)
venv/
# ===== 环境与密钥 =====
.env # 【关键】数据库密码、API Key 都在这里
.env.local # 本地覆盖配置
*.pem # SSL 私钥
*.key # 密钥文件
# ===== IDE =====
.vscode/ # VS Code 个人配置
.idea/ # PyCharm 配置
*.swp # vim 临时文件
# ===== 系统 =====
.DS_Store # macOS 文件夹元数据
Thumbs.db # Windows 缩略图缓存
# ===== 数据库 =====
*.db # SQLite 数据库文件(生产数据不入库)
*.sqlite3
# ===== 日志 =====
logs/ # 日志目录
*.log # 日志文件
# ===== 测试 =====
htmlcov/ # 测试覆盖率 HTML 报告
.coverage # 覆盖率数据文件
.pytest_cache/ # pytest 缓存
关键提醒:
.env文件里存密码、密钥,绝对不能提交到 Git。一旦提交,即使之后删除,Git 历史里仍然有。
1.3 提交规范(Conventional Commits)[推荐]¶
白话:给每次提交写个标准格式的"日记标题",让人一眼看懂改了什么。
格式:<类型>: <描述>
# 常用类型
feat: 新增物种丰度查询接口 # 新功能
fix: 修复样本上传时文件名乱码 # 修 bug
docs: 更新 API 文档说明 # 文档
refactor: 重构数据库查询逻辑 # 重构(不改功能)
test: 添加用户认证单元测试 # 测试
chore: 升级 FastAPI 到 0.115 # 杂务(依赖、配置等)
perf: 优化大表分页查询性能 # 性能优化
ci: 添加 GitHub Actions 测试流程 # CI/CD 相关
用工具强制执行(Python 项目推荐 commitizen + pre-commit):
# 安装 commitizen(交互式提交工具)
pip install commitizen # 安装提交辅助工具
# 安装 pre-commit(Git 钩子框架)
pip install pre-commit # 安装 Git 钩子管理器
创建 .pre-commit-config.yaml:
# .pre-commit-config.yaml —— 定义 Git 提交前自动执行的检查
repos:
# Ruff:一个工具替代 Black + Flake8 + isort(Rust 写的,超快)
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.6 # 指定 Ruff 版本
hooks:
- id: ruff # 代码检查(lint)
args: [--fix] # 自动修复简单问题
- id: ruff-format # 代码格式化(替代 Black)
# commitizen:检查提交信息是否符合规范
- repo: https://github.com/commitizen-tools/commitizen
rev: v4.1.0 # 指定版本
hooks:
- id: commitizen # 在 commit-msg 阶段检查格式
pre-commit install # 安装 pre-commit 钩子
pre-commit install --hook-type commit-msg # 安装提交信息检查钩子
# 以后每次 git commit 都会自动检查代码格式和提交信息
# 用交互式提交(不用自己记格式):
cz commit # 会弹出交互菜单让你选类型、填描述
1.4 Tag 版本标记 [推荐]¶
# 语义化版本号:主版本.次版本.修订号
# 主版本:不兼容的改动(1.0.0 → 2.0.0)
# 次版本:新增功能但兼容(1.0.0 → 1.1.0)
# 修订号:修 bug(1.0.0 → 1.0.1)
git tag -a v1.0.0 -m "首个正式发布版本" # 创建带注释的标签
git push origin v1.0.0 # 推送标签到远程
# 用 commitizen 自动打版本标签(根据提交记录自动判断版本号)
cz bump # 自动分析 feat/fix 提交,决定版本号
二、分支管理策略¶
为什么需要¶
不管分支的后果: - 直接在 main 上开发,一个 bug 把线上搞崩 - 多人同时改同一个文件,合并冲突到崩溃 - 想回滚到上个版本?找不到那个"干净"的节点
2.1 三种主流策略对比¶
| 策略 | 复杂度 | 适合谁 | 核心思想 |
|---|---|---|---|
| Git Flow | 高 | 大团队、定期发版 | main + develop + feature + release + hotfix 五种分支 |
| GitHub Flow | 低 | 小团队、持续部署 | 只有 main + 短命 feature 分支,PR 合并即部署 |
| Trunk-Based | 最低 | 个人/小团队、CI/CD 成熟 | 所有人直接往 main 提交,用 feature flag 隐藏未完成功能 |
2.2 推荐:小团队/个人用 GitHub Flow [推荐]¶
# 1. 从 main 创建功能分支
git checkout -b feat/species-query # 新建分支:物种查询功能
# 2. 在分支上开发、提交
git add .
git commit -m "feat: 添加物种丰度查询接口"
# 3. 推送分支到远程
git push -u origin feat/species-query # -u 设置上游追踪
# 4. 在 GitHub/Gitee 上创建 Pull Request
# 5. 代码审查通过后合并到 main
# 6. 删除已合并的分支
git branch -d feat/species-query # 删除本地分支
git push origin --delete feat/species-query # 删除远程分支
2.3 保护主分支 [必须]¶
在 GitHub 仓库设置中: - Settings → Branches → Add branch protection rule - Branch name pattern: main - 勾选 "Require a pull request before merging"(合并前必须 PR) - 勾选 "Require status checks to pass"(CI 必须通过)
这样就没人能直接 git push 到 main,所有改动必须经过 PR 审查。
三、远程仓库¶
为什么需要¶
代码只在本地 = 一场硬盘故障就能让你从零开始。
3.1 GitHub vs Gitee 对比¶
| 对比项 | GitHub | Gitee(码云) |
|---|---|---|
| 国内访问速度 | 偶尔慢/被墙 | 快 |
| 国际影响力 | 全球最大 | 国内为主 |
| 私有仓库 | 免费无限 | 免费有限制 |
| CI/CD | GitHub Actions(强大) | Gitee Go(功能少) |
| 社区生态 | 绝对领先 | 中文友好 |
| 推荐 | 首选(面试加分) | 备份/国内协作用 |
3.2 SSH Key 配置 [必须]¶
# 生成 SSH 密钥对(如果已有可跳过)
ssh-keygen -t ed25519 -C "your@email.com" # ed25519 比 RSA 更安全更短
# 一路回车用默认路径,可以设置密码也可以留空
# 查看公钥
cat ~/.ssh/id_ed25519.pub # 复制这段内容
# 去 GitHub → Settings → SSH and GPG keys → New SSH key,粘贴公钥
# 测试连接
ssh -T git@github.com # 成功会显示 "Hi xxx!"
# 添加远程仓库
git remote add origin git@github.com:你的用户名/t2d-api.git # SSH 地址
git push -u origin main # 首次推送
3.3 同时推送到 GitHub 和 Gitee(双保险)[进阶]¶
# 添加 Gitee 作为第二个远程
git remote set-url --add --push origin git@gitee.com:你的用户名/t2d-api.git
git remote set-url --add --push origin git@github.com:你的用户名/t2d-api.git
# 现在 git push 会同时推送到两个平台
git push origin main # 一次推两个
四、环境隔离¶
为什么需要¶
不隔离环境的后果: - 开发时用的 SQLite,上线用 PostgreSQL——代码跑不了 - 本地装了 debug=True,上线忘关——被人看到完整报错信息 - 开发环境装了 100 个测试包,部署到服务器全装一遍——浪费 2 小时
4.1 三套环境分离 [必须]¶
| 环境 | 用途 | 特点 |
|---|---|---|
| development | 本地开发 | 开调试、热重载、用测试数据 |
| testing/staging | 测试 | 模拟生产环境、跑自动化测试 |
| production | 线上 | 关调试、开性能优化、真实数据 |
4.2 .env 文件管理 [必须]¶
# .env.example —— 提交到 Git,告诉别人需要哪些配置(值留空或填示例)
DATABASE_URL=sqlite:///./data.db
SECRET_KEY=change-me-to-a-random-string
DEBUG=false
LOG_LEVEL=INFO
ALLOWED_ORIGINS=http://localhost:3000
# .env(本地开发用,不提交到 Git!)
DATABASE_URL=sqlite:///./dev.db
SECRET_KEY=dev-secret-not-for-production
DEBUG=true
LOG_LEVEL=DEBUG
ALLOWED_ORIGINS=*
在 FastAPI 中用 pydantic-settings 读取:
# app/core/config.py —— 配置管理,用 pydantic-settings 自动读 .env 文件
from pydantic_settings import BaseSettings # pydantic v2 的 settings 模块
class Settings(BaseSettings):
"""应用配置,自动从 .env 文件和环境变量读取"""
database_url: str = "sqlite:///./data.db" # 数据库连接地址
secret_key: str # JWT 密钥,必须设置
debug: bool = False # 调试模式,生产环境必须关
log_level: str = "INFO" # 日志级别
allowed_origins: list[str] = ["http://localhost:3000"] # CORS 允许的源
model_config = { # pydantic v2 配置方式
"env_file": ".env", # 自动读取 .env 文件
"env_file_encoding": "utf-8", # 文件编码
}
settings = Settings() # 全局单例,其他文件 import 即用
4.3 虚拟环境工具对比¶
| 工具 | 适合场景 | 优点 | 缺点 |
|---|---|---|---|
| uv | Python 项目(2025 首选) | 极快(Rust 写的)、兼容 pip | 较新,文档少 |
| venv | 纯 Python | 内置、零依赖 | 功能少、速度慢 |
| conda | 科学计算/生信 | 能管理非 Python 依赖(如 R、C 库) | 体积大、慢 |
| Docker | 部署 | 完全隔离、可复现 | 学习成本高 |
推荐组合:开发用 uv(或 venv),生信工具用 conda,部署用 Docker。
# === 方案 1:uv(2025-2026 年 Python 官方推荐的包管理工具) ===
# uv 是 Astral 公司(Ruff 同厂)出品的 Rust 工具,一个工具替代 pip + venv + pyenv + pip-tools + poetry
# 不需要预装 Python!uv 自动管理 Python 版本
# 安装 uv(三选一)
curl -LsSf https://astral.sh/uv/install.sh | sh # Linux/macOS 官方脚本
# pip install uv # 或用 pip 安装
# brew install uv # macOS 用 brew
# ---- 项目管理模式(推荐,完整项目管理) ----
uv init t2d-api # 初始化项目(自动创建 pyproject.toml)
cd t2d-api
uv add fastapi uvicorn sqlalchemy # 添加生产依赖(自动写入 pyproject.toml)
uv add --dev pytest ruff pre-commit # 添加开发依赖(写入 [dependency-groups])
uv run uvicorn app.main:app --reload # 运行项目(自动管理虚拟环境,无需手动 activate)
uv run pytest # 运行测试(同上)
# uv run 会自动:1.检查 pyproject.toml 2.同步 uv.lock 3.激活 .venv 4.执行命令
# ---- pip 兼容模式(简单项目、快速迁移) ----
uv venv # 创建虚拟环境(在 .venv 目录)
source .venv/bin/activate # 激活环境
uv pip install -r requirements.txt # 安装依赖(比 pip 快 10-100 倍)
# === 方案 2:传统 venv(兜底方案) ===
python -m venv .venv # 创建虚拟环境
source .venv/bin/activate # 激活
pip install -r requirements.txt # 安装依赖
2026 年建议:新项目直接用
uv init+uv add+uv run三件套,不再需要手动管理虚拟环境。uv.lock锁文件保证跨环境可复现,必须提交到 Git。