前言:Vibe Coding 只解决了 0 → 1
一个周末,用对话就能做出带登录、数据库、AI 对话、甚至支付的 App,界面还挺好看。这不是夸张,是现在每天的日常。
但它只解决了 0 → 1。AI 写的代码有问题,你不问,它不会主动提;你不测,问题就一直留在那。它优化的是「能跑」,不是「安全」——而安全失败不会报错。
几个数字把这事说透了:
- 到 2025 年底,全球大约 41% 的代码是 AI 生成的;GitHub Copilot 一家就写了普通开发者约 46% 的代码。
- Veracode 的 GenAI 代码安全报告发现,AI 在约 45% 的测试任务里引入了安全缺陷。
- Escape.tech 扫了 5600 个线上公开的 vibe coding 应用,找到 2000+ 个高危漏洞、400 个暴露的密钥——大约每三个就有一个带着可被利用的严重缺陷,最常见的是访问控制缺失和未校验的 webhook。
- 更贵的是救火:约一万个这样上线的项目里,8000 多个需要部分重建或抢救,单个成本 5 万到 50 万美元;而且在没审计过的地基上继续加功能,每个月会把最终的重建账单推高 20–30%。
结论很直白:写了多少代码变便宜了,「能不能上线」这个判断没变便宜。
从 vibe 出来的 Demo 走到上线,中间缺两段。这篇就把这两段串起来,用全栈工程师的顺序讲:
第一部分 · 选型:语言 → 后端框架 → 前端框架 → 数据库
第二部分 · 清算:按「会出什么事」从致命往下查
第一部分 · 选型
三条硬规矩
顺序之外,每一样我都用同一把尺子量:
- 按约束选,不按热榜选。 先问自己:一个人还是团队?要不要 SEO?有没有合规要求?延迟卡不卡?
- 选主流栈。 这条在 AI 时代被放大——框架越主流,AI 训练数据越多,生成的代码越对。冷门框架的生成质量波动很大。同时记住一句话:约束架构,放开实现。约束给太死,AI 没发挥空间;给太松,它会引入你完全陌生的依赖。
- 先把部署故事想好。 这是我最想强调的一条:开始让 AI 写代码之前,就把部署目标告诉它。说一句「请生成适配 Vercel 部署的 Next.js 项目」,之后的目录结构、路由、环境变量都会更规范。不提的话,你大概率拿回一套本地跑得好、但全是绝对路径、没有环境变量的代码,部署时全返工。
有个数据挺能说明「主流」的威力。有人拿五个模型(Gemini、Perplexity、ChatGPT、Claude、Grok)问了 75 次「独立开发者最快出货的栈是什么」,答案高度趋同:
| 层 | 被点名的比例 |
|---|---|
| 数据库 / 后端 | Supabase 89% |
| 托管 | Vercel 84% |
| 框架 | Next.js 83% |
| 支付 | Stripe 71% |
| 认证 | Clerk 43% |
| 邮件 | Resend 43% |
ChatGPT 给的独行侠答案是一句话:Next.js + TypeScript + Tailwind + Supabase + Vercel + Stripe。这份统计本身不重要,重要的是它反映了训练数据里什么最多——那也正是 AI 写得最好的地方。
第一步:语言
只问两个问题:能不能一条语言管前后端?能不能第一时间接上 Agent / 模型 SDK?
| 场景 | 选择 | 理由 |
|---|---|---|
| 默认(Web、SaaS、全栈) | TypeScript | 前后端同构;MCP、LangChain.js 等 Agent 生态最全;AI 生成质量最高 |
| AI / 数据 / Agent 服务 | Python | ML 生态无人能敌(PyTorch、LangChain、LlamaIndex),FastAPI 对接模型最顺 |
| 高吞吐网关 / 基础设施 | Go | 1 万并发连接约 50MB 内存,Node 同场景可能 500MB;部署就是个静态二进制 |
| 极致性能 / 边缘 / Wasm | Rust | 冷启动、计算密集;代价是开发慢、招人贵 |
| 企业存量 / 合规 / 信创 | Java | 生态与人才池最厚,等保、信创适配齐全 |
| 实时长连接为主 | Elixir | Erlang VM 单机扛百万连接;要接受更小的生态 |
默认答案:TypeScript 打底,Python 补 AI,Go 补吞吐。三选一不够时再谈 Rust / Java。
「TypeScript」早就不只是前端语言了。Node + TS 现在是主流的全栈路线:Node + Prisma/Drizzle + tRPC,一条语言从数据库类型一路安全到组件。
第二步:后端框架
语言定了,这一步其实是选「壳」。
| 语言 | 框架 | 什么时候用 |
|---|---|---|
| TS | Hono | 轻、类型好,跑边缘/Serverless 都行,新项目我最常起这个 |
| TS | Fastify | 要吞吐、要插件生态,比 Express 快得多 |
| TS | NestJS | 团队协作、要规范分层;代价是样板代码 |
| TS | Next.js Route Handlers / Server Actions | 前后端同构,表单提交不用单独写 API 路由 |
| Python | FastAPI | 默认。原生异步、对接 AI 最顺,也是增速最快的 AI 后端选择 |
| Python | Django | 需要自带 ORM、认证、Admin 后台,一套全给你 |
| Go | Gin / Echo / Fiber | 高并发 API、网关 |
| Java | Spring Boot 3.5 + JDK21 | 企业级;虚拟线程特别适合大模型这种长耗时、流式响应场景 |
挑后端框架我看三个硬指标:
- 鉴权 / 校验 / ORM 是不是开箱的——省下的都是命
- 支不支持流式响应——要接模型对话,这几乎必需
- 能不能干净地挂一层 Agent——别等要加智能体时才发现要重构
第 3 条现在很实在。2026 年的后端正在从纯 CRUD 往「事件驱动 + 虚拟线程 + Agent 内嵌」挪,选型时预留 Agent 层接口,比事后重写便宜得多。
第三步:前端框架
前端选错的代价最直观:AI 生成质量下降、招人变难、返工周期长。
| 框架 | 定位 | 什么时候用 |
|---|---|---|
| React 19 + Next.js 16 | 事实标准 | 复杂 Web 应用、要 SEO、要全栈;RSC 把客户端 JS 砍掉 70%+,Turbopack 让开发循环几乎瞬间 |
| Vue 3 + Nuxt 4 | 国内主力 | 中小团队、中后台;上手快、中文社区与组件库丰富,维护成本低 |
| Svelte 5 + SvelteKit | 小团队利器 | 要极致 DX 和更小包体,不介意生态体量小 |
| Astro 5 | 内容站 | 官网、博客、文档;岛屿架构,默认零 JS,SEO 和首屏拉满 |
| SolidJS | 高交互 | 大屏、编辑器这类密集交互场景 |
两个我基本不再纠结的点:
- 样式:Tailwind 就是默认。 原子化 class 和 AI 生成的工作流天然契合——模型不用在
.css和组件文件之间来回跳,一次就能产出完整样式。优雅与否是次要问题。 - 组件库: 后台看生态成熟度。React 边用 shadcn/ui,Vue 边用 Element Plus / Ant Design Vue。
判断只需要两问:要不要 SSR/SSG(SEO、首屏)?组件生态够不够我把后台做完?
顺一句:React Compiler 在 19 稳定后,「手动 useMemo/useCallback」这类记忆化优化基本交给编译器了,选 React 的心智负担在变小。
第四步:数据库
这是我最不犹豫的一层。
默认:PostgreSQL。
以前一个典型项目要养三套:Postgres 存关系数据、MongoDB 存文档、再一个向量库做 AI 检索。现在一个实例全包——
关系数据 → 表、外键、事务、JOIN
文档数据 → JSONB(可变 schema 不用换库)
向量检索 → pgvector(RAG 的语义检索直接内建)
我不再需要维护库之间的同步,也不用为「多养三套库」付运维账单。这就是收敛期最划算的一笔交易:Postgres 把 MongoDB + Redis + 向量库的活吃掉了一大半。
| 场景 | 选择 |
|---|---|
| 默认 / 要事务和 JOIN | PostgreSQL |
| RAG 向量检索 | pgvector 起步;上亿量级再考虑 Qdrant / Milvus |
| 缓存 / Session / 队列 | Redis(按需,不是默认) |
| 本地优先 / 单机 / 嵌入 | SQLite(libSQL / Turso 可托管同步) |
| 存量兼容 | MySQL |
| 真·无 schema、超高写入 | MongoDB——但要有明确记下来的理由 |
| 省运维 / 实时同步 | Supabase(BaaS 默认)/ Firebase(实时强) |
ORM 跟着语言走:TS 用 Prisma 或 Drizzle(更贴 SQL、更轻),Python 用 SQLAlchemy,Go 用 GORM / sqlx。
一条经验:别按趋势选数据库。MongoDB 火了好几年,一批团队后来为了 JOIN、事务、数据完整性又搬回了 Postgres。除非你能写下一句明确理由,否则从 Postgres 开始。
可以直接抄的默认套餐
前端 Next.js 16 + React 19 + Tailwind + shadcn/ui
后端 Hono(或 Fastify)+ Drizzle + tRPC
AI 服务 FastAPI 单独一个服务(要模型/Agent 时再加)
数据库 PostgreSQL(Supabase / Neon 托管)+ pgvector
缓存 Redis —— 需要时再加,不做默认
部署 前端 Vercel/Cloudflare + 后端容器(Fly / Railway / 腾讯云)+ 托管 PG
形状是「一个主服务 + 一个可选 AI 服务」,不是一堆微服务。原因很简单:先单体,看清瓶颈再拆。Shopify 过十亿美元营收时,跑的还是 Rails 单体。
第二部分 · 清算
选型定完,进入正题:上线前按「会出什么事」从最致命的往下查。每一层我都给能直接用的命令、SQL 或提示词。
第 0 步:先画地图,别急着改代码
第一个要审的不是代码,是控制权。快速做出来的项目经常是碎的:仓库在一个人的账号,云在另一个邮箱,域名在早就离职的人手上。
先把这些清点一遍,确认每一处你都能登录、能转移:
仓库 云账号 DNS/域名 数据库 环境变量
第三方 API 支付 邮件 监控 备份
这张图没出来之前,不要重新部署任何东西。 你没法回滚的改动都是风险,而你不知道能不能回滚,直到第 1 步确认。
顺带两件基线:
- 可复现构建:能不能在干净环境里从源码重建、部署?
- 可回滚:部署失败能不能退回上一个可用版本?
这两条做不到,先冻结新功能。如果部署流程只活在某台笔记本或某个人的记忆里,之后每一次改动都是赌。
架构层面同理:让 AI 产出一份 ARCHITECTURE.md(数据模型、路由结构、鉴权策略、目录约定),当作后续每个会话的锚点。没有这张图,清理会退化成一堆互相打架的局部改动——你改了鉴权,另一处旧逻辑又把口子开回来。
第 1 步:密钥(最高发)
AI 为了让功能「先跑起来」,很容易把 API Key 直接写进前端代码。可前端代码和安装包都是要发到用户手里的,谁都能打开看。
# 1) 构建产物里搜(Next.js 里任何 NEXT_PUBLIC_ 前缀都会进浏览器)
grep -rE "sk_|sk-|secret|service_role|mongodb\+srv://|AIza" .next/ dist/ 2>/dev/null
# 2) git 历史也要搜——删掉当前文件 ≠ 删掉历史
git log --all -- .env*
# 3) 粗筛硬编码凭证
grep -rnE "(api[_-]?key|secret|password|token)\s*[:=]\s*['\"][^'\"]{8,}" \
--include="*.ts" --include="*.js" --include="*.py" .
两个关键认知:
- 已经进过 git 历史或公开 bundle 的凭证,一律当作已泄露——先轮换,别只删文件。
- 轮换之外还要管「爆炸半径」:按环境分凭证、最小权限、用量告警、请求与花费上限。
为什么第 2 条不是多余的:有一个真实案例,一个以 fail-open 鉴权上线的 vibe 应用被拿到 API Key,攻击者用掉的价值约 60 万美元的额度才被止住。密钥泄露的账单可以是六位数美元。
轮换顺序:先轮换客户端能拿到的,再数据库凭证,最后其余。
第 2 步:鉴权与授权(漏洞最集中的地方)
Escape.tech 的发现里,「访问控制缺失」是最常见的严重缺陷。记住几组不等号:
- 认证(你是谁)≠ 授权(你能干什么)
- 保护了页面 ≠ 保护了 API
- 前端藏了按钮 ≠ 访问控制
- 浏览器传来的 user_id ≠ 所有权证据
最典型的一类 bug 叫 IDOR / BOLA:/api/invoices/123 会把 123 号发票返回给任何已登录用户。每个查询都必须带上「并且属于这个用户」。
审计动作:换一个账号,试着读/改/删别人的数据。 如果改一个 ID 就能拿到别人的数据,直接判定不通过。
让 AI 先把清单拉出来:
For every Route Handler, Server Action and database query in this project, verify
(1) the user is authenticated and (2) they are authorized for that specific record.
Produce a table: endpoint | auth check | ownership check | issue.
代码级加固(以 FastAPI 为例,这几条在生成的代码里几乎必错):
# 1) 挂在 router 级 → 漏写的路由 fail closed,而不是默认公开
router = APIRouter(dependencies=[Depends(get_current_user)])
# 2) 严格模型:多余字段(role / is_admin)直接拒,而不是静默写入
class ProfileIn(BaseModel):
nickname: str = Field(max_length=32)
model_config = ConfigDict(extra="forbid")
# 3) JWT:密钥用 32+ 字节随机值,算法钉死,有效期缩短到小时级
SECRET_KEY = os.environ["JWT_SECRET"] # 不是 "secret"
jwt.decode(token, SECRET_KEY, algorithms=["HS256"]) # 绝不接受 none
第 3 步:数据库与数据层
如果你用 Supabase,或者把 Postgres 直接暴露给客户端,每一张表都必须开 RLS(行级安全)。CVE-2025-48757 就是这么来的——一批用 AI 应用搭建器做出来的项目,因为没配 RLS,数据库被敞开。
但别停在「开了吗」。「开了 RLS」不等于「策略真挡得住」:
- 用另一个账号登录,实测越权读、越权写、越权导出、越权删除都被拒
- 查询是否参数化(走 ORM / query builder)
- 迁移、备份、数据保留期、删除行为是否清晰
- 日志里有没有把敏感数据打出去
证据要能复现——另一个工程师能独立验证,才算通过。
第 4 步:业务逻辑、支付与 Webhook
静态扫描抓不到「业务规则」类的漏洞,而这类最致命:
- 支付还没确认,就把高级权益发了
- Webhook 用了 HTTPS,但接受未签名的请求
- 取消订阅只改了界面,后端权益还留着
这几类即使 AI 生成的单元测试全过,也会在线上炸。要补的是:webhook 验签、支付状态机、幂等(防止超时重试重复下单/重复扣款)。
第 5 步:输入输出与浏览器侧
- 所有外部输入在服务端校验:表单、JSON、文件上传、查询参数、搜索框、webhook body,以及模型生成的、会流向下游的值
- 文件上传:限大小、MIME 按内容嗅探(不只看 header)、文件名服务端重生成 UUID
- 渲染消毒:用户或模型生成的文本要当 HTML/Markdown 渲染时,先消毒——对存储的原始输入用
dangerouslySetInnerHTML就是存储型 XSS - 生产环境别回详细错误:
except Exception as e: return {"error": str(e)}会把栈、文件路径、数据库报错直接漏给客户端。用全局异常处理,日志留服务端,客户端只回一句通用错误
第 6 步:成本与限流(AI 应用特有)
这是 vibe 应用最容易忽略、也最快烧钱的一层。
- 登录 / 注册必须限流:不然就是撞库靶子
- 任何用你 key 调 LLM 的端点,必须限流 + 每用户配额:一个用户在循环里就能把你的账单在几分钟内跑爆
- 每个环境独立凭证 + 用量告警 + 花费上限
第 7 步:测试与质量闸门(四道防线)
AI 生成的代码动辄几十上百个文件,靠人肉逐行审不现实。我用四道防线:
第一道 · 架构审查(人工,但只看关键决策点)
审的是:数据模型合不合理、权限模型安不安全、关键接口契约稳不稳、有没有引入不必要的重型依赖。审架构,不是审每一行——架构对了,细节交给测试兜底。
第二道 · 自动化测试
不是追覆盖率,是先保命。哪些是保命流程:
登录 / 注册 密码找回
支付 / 扣款 权限校验
客户数据变更 文件上传
外部集成回调 重要计算
测的不是「语法对不对」,是「它第 2 天做的假设,到第 10 天加了四个功能之后还成不成立」。一条最小冒烟测试就能起步:
def test_checkout_happy_path(client):
r = client.post("/login", json={"u": "a", "p": "b"})
assert r.status_code == 200
r = client.post("/orders", json={"sku": "s-1", "qty": 1},
headers={"Authorization": f"Bearer {r.json()['token']}"})
assert r.status_code == 201 and r.json()["status"] == "created"
**第三道 · 静态检查与安全扫描**
严格 TypeScript 模式(禁 `any`)、ESLint、依赖漏洞扫描、密钥扫描。顺手抓一下幻觉出来的、根本不存在的依赖包(slopsquatting 是真的)。
**第四道 · 运行监控**
上线后持续盯错误率、接口延迟、异常日志、资源占用。AI 生成的代码常在特定负载或特定输入下才出问题。
把前三道固化成每次合并自动跑的闸门:
```yaml
name: production-gate
on: [pull_request]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx tsc --noEmit # 类型不严格直接挡
- run: npx vitest run --coverage # 测试不过直接挡
- run: npx snyk test # 依赖漏洞顺手扫
一条判断规则,我觉得最有用:
当 bug 没法用一句话说清(哪个字段缺了、哪个值不对、崩在哪一行栈),别再用提示词猜,去测量。你指不出是哪个函数,AI 也指不出。
第 8 步:上线与可回退
- 环境变量通过平台面板配置,不进代码
- Node 版本用
engines钉死(本地 20、云平台默认 18 或 22,依赖不兼容就构建失败):
{ "engines": { "node": ">=20" } }
- 能回滚才敢改;蓝绿发布更适合高风险改动
- 上线后:采样 1–5% 真实流量进评测管线,抓漂移;确认数据保留期与合规要求
补充:什么时候该上 Spec
清算是「事后补救」。如果这个项目要长期活下去,事前那一步是 Spec——把意图写进一份要评审的 Markdown,而不是留在聊天记录里。
我的粗判断:
| 场景 | 做法 |
|---|---|
| 一次性脚本、落地页、内部小工具 | 纯聊就行,清算也可以跳过 |
| 有真实用户、要长期维护 | 先写短 spec(用户故事 + 验收标准 + 不做什么),再让 Agent 实现 |
| 多人协作 / 涉及钱和权限 | spec 进仓库、跟着 PR 走,测试当契约 |
行业把这两种姿势算成一笔账:纯 vibe 是低 CapEx、高 OpEx——前期几乎零成本,但运维账单复利增长;加了 spec 和测试是前期投入换后期便宜,因为 AI 在没有约束的系统里工作,返工多。用一句话概括它的价值:结构能扩展,感觉不能。
结论 · 交付标准
一个 vibe 出来的 Demo,要走到「能上线」,我按这个顺序放行:
| # | 检查项 | 通过标准 |
|---|--------|---------|
| 0 | 地图与控制权 | 仓库/云/DNS/库/支付都可登录可转移;构建可复现、部署可回滚 |
| 1 | 密钥 | 前端 bundle 与 git 历史无凭证;已泄露的一律轮换;设了用量与花费上限 |
| 2 | 鉴权与授权 | 换账号测过越权;每个 route/query 都有认证 + 归属两道闸 |
| 3 | 数据层 | 每张表 RLS 开启且策略实测有效;查询参数化 |
| 4 | 业务逻辑 | 支付状态机 + webhook 验签 + 幂等 |
| 5 | 输入输出 | 服务端校验;上传与渲染消毒;生产不回详细错误 |
| 6 | 成本 | 登录与 LLM 端点都有限流和配额 |
| 7 | 质量闸门 | 架构审查 + 关键路径测试 + 静态扫描,进 CI |
| 8 | 上线 | 环境变量外置;Node 版本钉死;有监控和回滚 |
三个我最常给的默认答案:
- 一个人 / 小团队做 Web 产品:TypeScript 全栈 + PostgreSQL(Next.js + Supabase + Vercel 那条线)。一条语言管到底,AI 帮忙也最给力。
- AI 分量重:在上面加一个 Python + FastAPI 服务,别硬塞进主服务。
- 明确撞到吞吐天花板:把那一个瓶颈服务换 Go,别整体重写。
最后是边界:这套是给「要接真实用户、要长期维护」的项目准备的。 内部工具、一次性原型、落地页,别上这套重装备——那时候快就是唯一正确的选型。
Vibe coding 不坏,它把实现成本压得很低。代价是那 20% 的收尾变成了你的活——不是重写,是选型和清算。