Prompt Engineering for Nuxt
Rules 解决了"AI 知道项目规范"的问题,但每次具体的编码请求,你仍然需要写一个好的 Prompt。同样是"写一个视频上传组件",好的 Prompt 能让 AI 一次生成 90% 可用的代码,差的 Prompt 可能需要来回修改五六轮。本章总结面向 Nuxt4 开发的 Prompt 工程实践——不是通用的 Prompt 技巧,而是专门针对前端/全栈场景的实战方法论。
1. 高质量 Prompt 的五个要素
1.1 CRAFT 框架
| 要素 | 英文 | 说明 | 示例 |
|---|---|---|---|
| C Context | 上下文 | 当前项目状态和技术栈 | "Nuxt4 项目,使用 Drizzle ORM" |
| R Role | 角色 | AI 应该扮演的角色 | "作为 Nuxt4 全栈开发者" |
| A Action | 行动 | 具体要做什么 | "创建视频上传组件" |
| F Format | 格式 | 输出格式要求 | "Vue SFC,使用 script setup" |
| T Target | 目标 | 验收标准 | "支持分片上传、进度显示" |
1.2 对比:差 Prompt vs 好 Prompt
差 Prompt:
写一个上传组件
问题:不知道用什么框架、什么 UI 库、上传到哪里、要不要分片、需不需要进度条。AI 只能猜,大概率猜错。
好 Prompt:
在 AI 视频平台(Nuxt4 + Nuxt UI)中,创建一个视频上传组件 `VideoUploader.vue`:
技术要求:
- 使用 `useChunkUpload` composable(已有,见 composables/useChunkUpload.ts)
- UI 使用 Nuxt UI 的 UButton、UProgress 组件
- 拖拽上传区域,支持点击选择文件
- 文件类型限制:video/*,最大 2GB
功能:
- 选择文件后显示文件名和大小
- 上传过程中显示进度条(百分比)
- 上传完成后跳转到 /video/[id]/edit
- 上传失败显示错误提示
不要:
- 不要创建新的 composable,使用现有的 useChunkUpload
- 不要用原生 fetch,useChunkUpload 内部已处理
好 Prompt 的特点:明确依赖(指出已有的 composable)、明确 UI 库(Nuxt UI)、明确行为(进度、跳转、错误处理)、明确边界(不要做什么)。
2. Nuxt 特定 Prompt 模式
2.1 创建 API 路由
创建 Nuxt Nitro API 路由 `server/api/videos/[id]/like.post.ts`:
功能:切换视频点赞状态(已赞则取消,未赞则添加)
要求:
- 使用 requireAuth(event) 做认证
- 使用 Zod 做空 body 校验(不需要参数)
- 操作 likes 表(schema 已在 packages/database/schema/likes.ts)
- 同时更新 videos 表的 likeCount(sql 原子操作)
- 返回 { liked: boolean }
参考现有路由:server/api/videos/[id]/danmaku.post.ts
关键技巧:指定参考文件。让 AI 看一个已有的类似实现,它会模仿风格和模式,比你用文字描述准确得多。
2.2 创建页面组件
创建 Nuxt 页面 `pages/video/[id].vue`:
数据获取:
- 使用 useFetch 获取 /api/videos/:id(SSR)
- 使用 useSeoMeta 设置标题、描述、OG 图片
- 404 时使用 showError({ statusCode: 404 })
组件组合:
- VideoPlayer(已有,props: src, poster)
- LikeButton(已有,props: videoId, initialLiked, initialCount)
- 视频标题、描述、标签、播放量、创建时间
- 相关视频推荐(调用 /api/videos/related?id=xxx)
布局:
- 使用 default layout
- 左侧 2/3 视频 + 信息,右侧 1/3 相关视频
- 响应式:移动端单列
2.3 创建 Composable
创建 composable `composables/useVideoFilter.ts`:
功能:视频列表的筛选和排序状态管理
输入:
- 初始查询参数从 route.query 读取
状态:
- category: string | null(分类筛选)
- sortBy: 'latest' | 'popular' | 'trending'
- duration: 'short' | 'medium' | 'long' | null
输出:
- query: computed 的查询参数对象(用于传给 useFetch)
- reset(): 重置所有筛选
- 每次状态变化自动同步到 URL query(使用 router.replace)
注意:
- SSR 安全(初始值从 route.query 读取)
- 不要在 composable 内调用 useFetch(由调用者负责)
3. 任务拆分策略
3.1 为什么要拆分
AI 模型有上下文窗口限制和注意力衰减——任务越大,出错概率越高。一个"创建完整的用户系统"的请求,AI 很可能遗漏边界情况;但拆成"创建用户注册 API"、"创建登录页面"、"创建个人资料页"等小任务,每个都能做得很好。
3.2 拆分原则
按层拆分(推荐用于新功能):
功能:视频收藏
├── 任务 1:数据库 schema(favorites 表 + migration)
├── 任务 2:API 路由(收藏/取消/列表)
├── 任务 3:Composable(useFavorite)
├── 任务 4:UI 组件(FavoriteButton + 收藏列表页)
└── 任务 5:测试
按功能拆分(推荐用于重构):
重构:视频状态管理
├── 任务 1:抽取 useVideoPlayer composable
├── 任务 2:抽取 useVideoProgress composable
├── 任务 3:抽取 useVideoQuality composable
├── 任务 4:重构 VideoPlayer.vue 使用新 composables
└── 任务 5:验证所有功能正常
3.3 任务之间的上下文传递
拆分后的关键问题:后续任务需要知道前面的产出。两种方式:
方式 1:引用文件(Cursor / Windsurf)
上一步我们创建了 packages/database/schema/favorites.ts。
现在基于这个 schema,创建 API 路由:
- @packages/database/schema/favorites.ts
- 参考 @server/api/videos/[id]/like.post.ts 的风格
方式 2:总结传递(Claude Code / 新会话)
项目已有:
- favorites schema:id, userId, videoId, createdAt(唯一约束 userId+videoId)
- 用户系统:requireAuth(event) 返回 session.user.id
创建 server/api/favorites/ 下的 CRUD 路由
4. 多轮对话策略
4.1 渐进式细化
不要试图一次把所有需求说完。先给出核心需求,然后逐步细化:
第 1 轮:创建一个视频搜索页面,使用 /api/search 接口
→ AI 生成基础版本
第 2 轮:添加搜索防抖(300ms)和加载骨架屏
→ AI 在现有代码上增强
第 3 轮:搜索结果为空时显示推荐视频,从 /api/videos/popular 获取
→ AI 添加空状态处理
第 4 轮:添加搜索历史(localStorage),最多保存 10 条
→ AI 添加历史功能
这比一次写一个巨大的需求文档效果好得多——每一轮 AI 都能集中注意力在一个小的改进上。
4.2 修正与引导
AI 犯错时,不要重写整个 Prompt,而是精确指出问题:
差:重新生成,上次的不对
好:上面的代码有两个问题:
1. useFetch 不应该在 onMounted 里调用,直接在 setup 顶层调用
2. computed 里不要用 .value,直接引用 ref 变量名
请修正这两处
5. Nuxt 开发 Prompt 模板库
5.1 创建 CRUD 模块
为 [实体名] 创建完整的 CRUD 模块:
数据库:
- Schema 文件:packages/database/schema/[实体].ts
- 字段:[列出字段和类型]
- 关系:[外键关系]
API 路由(server/api/[实体]/):
- index.get.ts:分页列表(支持 page, limit, search 参数)
- [id].get.ts:详情
- index.post.ts:创建(需要认证)
- [id].put.ts:更新(需要认证 + 权限检查)
- [id].delete.ts:删除(需要认证 + 权限检查)
所有路由使用 Zod 校验,返回 typed 响应。
参考现有的 videos 模块实现风格。
5.2 添加新功能
在现有 [页面/组件] 上添加 [功能名]:
当前代码:@[文件路径]
需要添加:
- [具体功能描述]
- [交互行为]
- [边界情况]
约束:
- 不要修改现有的 [xxx] 逻辑
- 使用现有的 [yyy] composable
- 保持与现有代码相同的风格
5.3 Bug 修复
Bug:[描述现象]
预期行为:[描述正确行为]
实际行为:[描述错误行为]
复现步骤:[1, 2, 3]
相关文件:
- @[文件 1]
- @[文件 2]
请分析根本原因并修复。如果需要看更多代码请告诉我。
5.4 代码重构
重构 @[文件路径]:
目标:[重构目标,如"拆分过长的组件"、"提取重复逻辑"]
当前问题:
- [问题 1]
- [问题 2]
约束:
- 保持所有现有功能不变
- 保持组件的 public API(props, emits)不变
- 新文件放在 [目录]
请先给出重构方案,我确认后再实施。
6. 常见陷阱与应对
6.1 AI 的常见错误
| 错误 | 原因 | Prompt 中的防范 |
|---|---|---|
手动 import ref | 不知道 Nuxt 自动导入 | Rules 中声明 + Prompt 提醒 |
在 onMounted 中用 useFetch | 不理解 Nuxt 的 SSR 数据获取 | 给出正确示例 |
生成 .js 文件 | 默认行为 | 明确指定 TypeScript |
用 fetch 替代 $fetch | 通用习惯 | Rules 中 NEVER 声明 |
| 不处理加载/错误状态 | 只关注 happy path | Prompt 中列出边界情况 |
6.2 提升 Prompt 效果的技巧
- @引用文件:让 AI 看到真实代码,比文字描述准确 10 倍
- 指定参考:"参考 xxx 的风格"比"遵循最佳实践"有效
- 列出不要做的事:反约束比正约束更能减少错误
- 先方案后实施:"先给方案,我确认再写代码"避免做无用功
- 小步迭代:一次一个小功能,比一次做整个模块可靠
本章小结
- CRAFT 框架:Context + Role + Action + Format + Target,好 Prompt 的五个要素
- Nuxt 特定模式:API 路由、页面组件、Composable 各有对应的 Prompt 模板
- 任务拆分:按层拆分(新功能)或按功能拆分(重构),每个子任务保持聚焦
- 多轮策略:渐进式细化优于一次写完,精确修正优于重新生成
- 模板库:CRUD 模块、添加功能、Bug 修复、代码重构四大模板覆盖 90% 场景
- 防范陷阱:Rules 声明反模式 + Prompt 中指定参考文件 + 列出不要做的事