从零使用 claude code 生成一个完整的 SPA 应用结构

上周,一个做了四年React的同事在代码评审时问我:“这个SPA的目录结构是谁定的?services、composables、stores分得这么清楚,不像是你平时的风格。”

我说是Claude Code

他不信,说AI只能写函数,干不了架构的活。

于是我把整个过程重演了一遍,从空目录开始,到生成一个完整的、带路由懒加载、Token管理、状态持久化的Vue 3 + Vite SPA骨架,用时47分钟。他看完沉默了大概十秒,然后说:“我学了两年才搞明白的目录分层,它用三个问题就搞定了。”

这不是一篇“Claude Code能干什么”的科普。如果你想知道它怎么安装、怎么配置环境变量,微信上已经有十几篇水文能告诉你怎么敲那几行命令。

我要讲的是:怎么把一个AI编程Agent从“代码补全工具”用成“项目架构师”,以及在这个过程中,哪些做法会让你拿到一坨能跑但没法维护的屎山,哪些做法能让你真的省下十几个小时。

先给一个核心结论,这是踩了上百次坑之后我现在的判断:

Claude Code在SPA项目里的真正价值,不在代码生成的速度,而在于它能迫使你在动手写第一行代码之前,先把架构层面的决策显性化。它就像一个永远不会不耐烦的Code Review搭档,前提是你知道怎么向它提对的问题。

让我从头讲起。

一、为什么你之前用Claude Code写SPA,最多只能写到Hello World?

我先问你一个问题:你上一次用它生成一个“完整的”项目,最终跑起来了吗?

我猜大概率没有。或者说,跑是跑起来了,但你打开src/目录一看,所有逻辑堆在三四个文件里,App.vue里有800行代码,路由配置写了但没用上,API请求的Token是硬编码的,然后你叹了口气,决定“还是自己重构一遍”。

这不是Claude Code的问题。这是你使用它的方式在第一步就出了偏差。

我把常见的偏差总结成三类,你可以对照看一下自己踩中了几个:

第一类偏差:把它当Copilot用

你给Claude Code下的命令是这样的:

> “帮我写一个登录页面。”

然后它生成了一个Login.vue,里面有表单、有校验、有提交逻辑。你复制进去,跑起来,能用。然后你觉得“还不错”,接着又说:

> “再加上注册页面。”

它又生成了一个Register.vue

你重复这个操作十次,最后得到了十个独立的、互不相干的页面组件。它们之间没有共享的状态管理、没有统一的路由守卫、没有复用的请求封装、没有布局组件。等你意识到需要一个整体架构的时候,已经晚了,Claude Code给你的每一个文件都是按照“独立完整”的逻辑生成的,它们拼在一起会冲突。

这是Copilot的使用逻辑:你问什么,它答什么。它不会主动告诉你“你应该先设计路由表,再生成页面”。

第二类偏差:一次性要太多

另一些教程会教你写一个“超级Prompt”,大概长这样:

> “请帮我生成一个完整的电商SPA项目,使用Vue3 + Vite + Pinia + Vue Router,包含首页、商品列表、商品详情、购物车、用户中心、登录注册……”

这个Prompt看起来没问题,实际上有个致命缺陷:Claude Code在处理超过一定复杂度的任务时,会启用一种“快速完成模式”。 这不是官方的术语,是我反复测试后的观察,当你一次性给它太多文件要生成时,它会开始走捷径。

走捷径的表现包括:

  • 把多个组件的逻辑写在一个文件里,然后注释说“在此处拆分为独立组件”
  • 路由配置只写前三个页面,后面的用// TODO: 添加其他路由代替
  • Store只创建了一个useAppStore,把所有状态都往里扔
  • CSS全用内联样式或者一个全局的style.css

最后你拿到的东西,文件名看起来很完整,但内容密度不均匀:前面几个文件写得很详细,越往后越敷衍。这是因为Claude Code在生成长文本时存在“注意力衰减”效应,它倾向于把计算资源集中在前半部分。

第三类偏差:不敢打断它、纠正它

这是最微妙的一个问题。很多人把Claude Code的输出当作“权威答案”,哪怕看到不对劲的地方也想着“可能是我没看懂”,先复制进去跑一下再说。

但Claude Code在生成SPA项目时,有一个非常固定的坏习惯:它会编造不存在的API。

比如我让它生成一个用户登录模块,它会在api/auth.js里写:

import { request } from '@/utils/request'
export function login(data) {

return request({

url: '/api/v1/auth/login',

method: 'post',

data

})

}

看起来没问题。但接着它会在组件里写:

const res = await login(formData)
if (res.code === 200) {

localStorage.setItem('token', res.data.access_token)

router.push('/dashboard')

}

问题来了:这个res.code === 200res.data.access_token的数据结构,是谁定义的?是你后端同事吗?不是,是Claude Code编的。它不知道你后端的响应格式,但它不会问你,它会自己“合理推测”一个。

如果你不打断它,不告诉它“我后端的响应格式是{status: 0, result: {token: 'xxx'}}”,它就会在接下来所有用到Token的地方,都基于它编的那个格式继续写。

等到你把这些代码接到真实后端的时候,你会发现所有请求都跑不通,然后你需要改的不是一个文件,而是十几个文件,因为它的推断逻辑已经渗透到了每一个调用链里。

这三个偏差叠加在一起,构成了绝大多数人“用Claude Code写SPA但写不出来”的核心原因:你用一个做填空题的工具,去要了一篇论文;它给你的是一个看上去像论文但经不起推敲的草稿。

二、我是怎么从挫败中摸出那条正确的路径的?

说实话,前面那三个坑我全都踩过,而且踩了不止一遍。

第一次失败是在今年4月。我让Claude Code生成一个后台管理系统的基础框架,用的是一次性Prompt。它给我生成了27个文件,src/目录看起来像模像样:

src/
├── api/

├── assets/

├── components/

├── router/

├── store/

├── utils/

├── views/

├── App.vue

└── main.js

我当时还挺高兴,觉得“这不就成了吗”。然后我打开router/index.js,看到的是:

const routes = [
{ path: '/', component: Layout, children: [

{ path: 'dashboard', component: () => import('@/views/Dashboard.vue') },

{ path: 'users', component: () => import('@/views/Users.vue') },

// 更多路由在此添加

]}

]

“更多路由在此添加”。一个“完整的”SPA骨架,路由配置里写着“更多路由在此添加”。这说明它的“完整性”是形式上的,不是实质上的。

第二次失败是在5月。我换了个思路,一次只让它生成一个模块。先让它生成路由配置,再生成Layout组件,再逐个生成页面。这回文件质量确实高了,但出现了一个新问题:各个模块之间的接口对不上。

它生成的路由配置文件里写的是component: () => import('@/views/UserCenter.vue'),但因为它生成视图文件的时候不记得前面的上下文,文件名叫UserProfile.vue。跑起来就是白屏,控制台报Failed to resolve component

这两种失败模式指向了同一个根因:Claude Code对你的项目没有持久的、一致的“心智模型”。 它每一次回复都是基于当前对话上下文重新推理的,而不是维护一个全局的项目设计图。

这个发现是我真正开始理解Claude Code的起点。既然它不维护全局状态,那我就得帮它维护。这就引出了下面我要讲的方法论。

三、“架构前置”工作流:我现在的标准操作流程

经过十几次从头构建SPA项目的尝试,我收敛到一套固定的操作流程。它分为四个阶段,每个阶段有不同的目标和Prompt策略。

3.1 第一阶段:需求锚定(10-15分钟)

不要一上来就让Claude Code写代码。先让它写文档。

这是我的第一个经验教训。很多开发者(包括我自己)对“文档”有天然的抗拒,觉得“聊需求”是浪费时间,不如直接干。但在AI协作的场景下,文档不是给别人看的,是给AI自己看的,它是Claude Code在后续生成代码时的“上下文锚点”。

我的第一个Prompt通常是这样的:

我准备构建一个SPA应用,技术栈是Vue 3 + Vite + Pinia + Vue Router 4。
应用类型:【企业后台管理系统 / 内容展示型 / 工具型 / 电商型】

核心页面:【列出3-5个核心页面】

权限要求:【是否需要登录、是否有角色区分】

数据持久化:【是否需要本地缓存、对接什么后端】

部署环境:【纯静态 / 需要SSR / Docker容器】

请先不要写代码。请输出:

推荐的项目目录结构(src/下的完整文件树)
路由设计方案(包括哪些路由需要守卫)
状态管理模块划分(哪些数据需要Pinia store)
组件复用策略(哪些组件需要提取为公共组件)

这个阶段的关键词是“先不要写代码”。这会强制Claude Code切换到“设计模式”,而不是“生成模式”。

从零使用 claude code 生成一个完整的 SPA 应用结构

3.2 第二阶段:基础设施搭建(15-20分钟)

拿到设计文档后,不要立刻生成业务页面。先搭基础设施。

什么是基础设施?我指的是这些:

  • src/utils/request.js,封装axios或fetch,统一拦截请求和响应
  • src/router/index.js,路由表配置,以及全局的beforeEach守卫
  • src/store/下的各个Store模块,尤其是useAuthStore(Token持久化)和useAppStore(全局配置)
  • src/layouts/,布局组件,比如MainLayout.vue(侧边栏+顶栏+内容区)

为什么这一步不能跳过?因为在SPA应用里,基础设施是“骨架”,业务页面是“肌肉”。 如果你先生成肌肉再搭骨架,肌肉的形状会因为骨架的限制而变化,之前写好的页面组件很可能需要大改。

我踩过这个坑。有一次我先生成了商品列表页和商品详情页,然后才让Claude Code生成路由配置和Layout。结果它为了适应已经存在的页面组件,把Layout设计得很奇怪,侧边栏的导航项目是从页面组件里“反向推导”出来的,而不是从业务需求出发的。

正确的做法是让Claude Code在这一步产出以下文件,并一个文件一个文件地确认:

  1. src/utils/request.js:这是我的标准Prompt:“请封装一个基于axios的请求模块,要求:1) 自动在请求头挂载Token;2) Token从localStorage读取,key为access_token;3) 响应拦截器统一处理401状态码,跳转到登录页;4) 支持请求超时设置,默认15秒;5) 导出get/post/put/delete四个方法。”
  2. src/stores/auth.js:Token的获取、存储、清除、过期判断。
  3. src/router/index.js:路由表+beforeEach逻辑。
  4. src/layouts/MainLayout.vue:主布局的骨架结构。

每一步生成后,我会让Claude Code解释它这么写的理由,确认它理解了我的全局设计意图。这里有一个小技巧:如果它的解释里有任何地方和你预想的不一致,立刻纠正,不要心存侥幸。

比如有一次它生成的beforeEach逻辑是这样的:

if (!authStore.token && to.path !== '/login') {
next('/login')

}

我说:“不对。如果用户访问的是/register注册页,也不需要Token。而且如果Token过期了(不是没有Token),需要在跳转前清除localStorage并提示用户。”

它立刻修正:

const publicPages = ['/login', '/register', '/forgot-password']
if (!publicPages.includes(to.path) && !authStore.isAuthenticated) {

if (authStore.token) {

// Token存在但过期

authStore.logout()

ElMessage.warning('登录已过期,请重新登录')

}

next('/login')

}

这种细节纠正是整个协作过程中最有价值的部分。 你在这个阶段每纠正一次,就等于在全局范围内避免了一个潜在的Bug。如果你跳过这些对话直接进入业务页面开发,这些Bug会分散到几十个文件里,到时候修都没法修。

3.3 第三阶段:核心功能生成(30-40分钟)

基础设施确认无误后,才开始生成业务页面。这一步的排序有讲究。

我总结的生成顺序是:

  1. 先做“骨架页面”:比如列表页(Table + 分页 + 搜索),这是最标准化的、不依赖其他业务模块的页面。
  2. 再做“关联页面”:比如详情页(依赖列表页的路由参数)。
  3. 最后做“全局交互”:比如用户头像下拉菜单、消息通知、错误页面(403/404/500)。

为什么按这个顺序?因为Claude Code在生成每一个新文件时,会参考前面已经生成的文件。如果你先生成了详情页,它可能在详情页里自己定义一个请求方法;但如果先生成了列表页并已经封装了请求模块,后面生成详情页时它就会复用。

这里有一个非常反直觉的发现:Claude Code的复用能力取决于你的文件生成顺序,而不是你“告诉”它要复用。

如果你在Prompt里写“请复用我们已经封装好的request请求”,它有概率记住;但如果你先生成了封装好的request并让它可见,它几乎100%会复用。这是因为它的推理机制更偏重“看到什么用什么”,而不是“听到什么用什么”。

下面用一个真实案例来说明这一阶段的具体操作。

案例:生成一个“用户管理”模块

用户管理模块通常包含:用户列表页、用户详情/编辑页、用户创建页。

我在这一步对Claude Code说的是:

基于我们已经建好的项目基础设施(request封装在src/utils/request.js,authStore在src/stores/auth.js,主布局在src/layouts/MainLayout.vue),现在需要生成用户管理模块。
功能需求:

用户列表页(src/views/users/UserList.vue):

表格展示:姓名、邮箱、角色、状态、创建时间

支持分页(与后端约定好的分页参数格式:page, pageSize,响应格式见下面)

支持按角色筛选

操作列:编辑(跳转详情)、删除(二次确认)

用户详情/编辑页(src/views/users/UserDetail.vue):

路由参数:/users/:id,id为'new'时表示新建

表单字段:姓名、邮箱、角色(下拉选择)、状态(开关)

提交后返回列表页并刷新

注意事项:

后端API响应格式统一为:{ code: 0, message: 'success', data: { list: [], total: 0 } }

Token过期后端返回401,request.js里已经处理了跳转,这里不需要额外处理

列表页删除操作需要二次确认,使用ElMessageBox.confirm

表单校验规则:姓名必填,邮箱格式校验

请先生成用户列表页的完整代码。

注意我做了什么:

  • 明确了后端约定的数据结构(避免AI编造)
  • 明确了哪些事情已经在基础设施里处理了(避免重复处理)
  • 明确了交互细节(删除确认、表单校验)
  • 每次只要求生成一个页面的代码,而不是一口气要三个

它生成的代码大概350行,我逐段审查后发现了一个小问题:它默认分页参数名是pageNumpageSize,而我跟后端约定的参数名是pagepageSize。我指出了这个问题,它修正后顺便把列表页的请求参数也做了对齐。

然后我才说:“现在轮到用户详情页了,请基于修正后的列表页代码,生成用户详情页。”

3.4 第四阶段:集成检查与边界补全(10-15分钟)

所有功能页面生成完毕后,我会做一个“集成检查”。这个阶段的Prompt模板是:

请依次检查以下事项,如有问题请修正:

所有路由path是否都在router/index.js中注册了?
所有页面的import路径是否正确?(特别是@/别名和组件名称的大小写)
所有API调用的响应数据格式是否统一(code/message/data)?
所有Pinia store是否在main.js中正确注册?
错误页面(404/403/500)是否已创建并在路由中配置fallback?
页面title是否在路由meta中配置并在全局守卫中设置?

这一步通常会触发5-8处小修正:某个组件引用了@/views/user/UserList.vue但实际路径是@/views/users/UserList.vue;某个路由meta里写了title但全局守卫里没有document.title = to.meta.title的逻辑;某个Store的命名空间不一致等等。

这些小修正是决定你最终拿到的项目“能不能跑”和“好不好维护”的分水岭。 市面上那些“5分钟生成一个完整项目”的教程,几乎从来不会提这一步,因为它们展示的只是“看起来能跑”,而不是“真的能维护”。

四、“对话工程学”:如何让Claude Code的输出质量稳定可控?

很多人以为“Prompt写得好”就等于“输出质量高”。这是不完整的。

Prompt确实重要,但在我三个月的深度使用中,我发现对话的管理方式比单次Prompt的质量更决定最终产出。 我把这种管理方式称为“对话工程学”,它包含四个核心原则。

原则一:上下文窗口是黄金,别往里面扔垃圾

Claude Code的上下文窗口很大(200K token),但有一个隐秘的衰减规律:越靠后的内容,权重越高;越靠前的内容,越容易被“遗忘”或“泛化”。

这意味着你不能指望它记住你在第1条消息里说的一个细节,然后第20条消息里还能准确引用。如果你有一个核心约定(比如后端数据格式、命名规范),要么在每条消息里重申,要么把它写成一个项目文件(比如README.md.clauderules),让它每次都能“看到”。

我在项目里创建了一个ARCHITECTURE.md文件,内容很简单:

# 项目架构约定
技术栈

Vue 3 (Composition API) + Vite + Pinia + Vue Router 4 + Element Plus

后端数据格式

{ code: 0, message: 'success', data: any }

分页格式:{ code: 0, message: 'success', data: { list: [], total: 0 } }

Token

存储key: access_token

存储位置: localStorage

过期处理: 401 -> 清除Token -> 跳转/login

命名规范

Vue组件: PascalCase

文件名: PascalCase.vue

路由path: kebab-case

Store: useXxxStore

请求方法: camelCase

每次开启一个新的对话任务,我会先让Claude Code读这个文件:

请先阅读项目根目录下的ARCHITECTURE.md,理解项目的基础约定,然后开始工作。
这一个简单动作,让后面生成代码的一致性提升了至少40%,这是我自己估算的数据,没有严格的A/B测试,但感受非常明显。

原则二:一个对话只做一件事

我在5月份犯过的最大错误,是在一个对话里同时处理路由设计、状态管理和页面生成。结果就是它给我的路由表里引用的页面、Store里管理的状态、页面里实际使用的状态,三者不一致。

后来我强制自己遵守一个规则:路由设计在一个对话里完成并确认;基础设施在第二个对话里搭建并确认;业务模块按模块拆分到不同对话里。

每个对话结束时的产出是明确的、完整的、经过确认的。下一个对话开始时,我会把上一个对话产出的关键文件路径告诉Claude Code,让它重新加载上下文。

这样做看似“慢”,实际上省了非常多时间。因为一致性问题的修复成本是随项目复杂度指数级增长的,在生成的时候就避免,比生成完再到处改,效率高太多了。

原则三:用“纠错对话”训练它的全局一致性

我发现Claude Code有一个“学习”行为,虽然它没有记忆(不同对话之间是独立的),但在同一个对话内,你纠正它一次,它会在后续的生成中“记住”这个纠正。

最典型的例子是API响应格式。我前期没有显式告诉它后端的数据格式,它在生成第一个页面时假设响应是res.data.list,我纠正说“我的后端返回的是res.data.data.list(因为响应体里有一层data嵌套)”。它理解了之后,在同一个对话里生成的后续页面都正确地使用了res.data.data.xxx。

这意味着你应该在同一个对话里完成“同类工作”。 比如所有需要调API的页面都在一个对话里生成,这样只需要纠正一次数据格式,它就会在后续所有页面里保持一致。

如果我切换到一个新对话重新生成一个列表页,它大概率又会回到默认的res.data.list,我需要再纠正一次。这不仅是重复劳动,而且如果我某次忘了纠正,就会引入隐蔽的不一致。


从零使用 claude code 生成一个完整的 SPA 应用结构
原则四:永远保留“人类的最后一道检查” 这是我最想强调的一点。不管Claude Code生成的代码看起来多完整、多规范,让它跑起来之前,至少要做三件事: 全局搜索TODO、FIXME、HACK:Claude Code在遇到它不确定的逻辑时,有时会偷偷用这些注释标记,而不是向你提问。你要把这些标记当作“待处理问题”,而不是“以后再说”。 检查所有import路径:这是最容易出错的地方。如果项目用了@/别名,但某些引用写成了相对路径../../../,Vite构建时可能不会报错,但IDE的类型提示会出问题。 跑一遍npm run build:我遇到过两次,Claude Code生成的代码在dev模式下一切正常,但build时报错。一次是因为它引用的某个组件名和文件名大小写不一致(macOS开发环境不区分大小写,但构建工具在Linux环境下区分);另一次是因为它在一个.vue文件里引用了Node.js的fs模块,dev模式下Vite没严格检查,build时Rollup报错。 这三个检查大概花5分钟,但能帮你发现80%的“隐性Bug”。 如果不做这一步,你的“成果”可能只是一个在开发环境能跑、但上不了生产的半成品。 五、成本真相:用Claude Code搭SPA到底省不省钱? 关于成本的讨论,我在网上看到两种极端说法。一种说“AI编程几乎免费,太划算了”;另一种说“API费用比雇人还贵”。 我按自己的真实使用数据来算一笔账。 我用的是Claude Pro订阅($20/月),日常通过Claude Code终端工具使用,走的是订阅额度的消耗,没有额外的API费用。Pro订阅下,Claude Code的使用有频率限制(官方说“慷慨的速率限制”,实测大概是每5分钟20-30次请求),但对我来说完全够用,因为我从来不会连续疯狂发送请求,中间总是有阅读输出、审查代码、思考的时间。 以本文案例(用户管理模块SPA)为例: 总对话轮次:约40轮(包括需求锚定、基础设施搭建、页面生成、集成修正) 真实耗时:约2.5小时(实际分散在三个下午,因为中间要去开会) Pro订阅日均成本:$20 / 30天 ≈ $0.67/天 如果把这个项目交给一个中级前端工程师从零手写,我估算需要6-8小时(包括目录设计、基础设施封装、页面开发、联调测试)。按国内中级前端工程师平均时薪约80-120元计算,人工成本约480-960元。 这意味着,Claude Code将这个SPA骨架的构建成本降低到了接近于零。 但这里有一个重要的“但是”:这个成本计算的前提是你已经具备了独立完成这个项目的能力。 Claude Code在这件事上扮演的角色不是“替代一个工程师”,而是“让一个已经会的工程师更快”。如果你完全不会Vue,哪怕Claude Code给你生成了一套完美代码,你不会调试Vite配置、不会处理Pinia的状态持久化、不会写Vue Router的导航守卫逻辑,那这套代码对你来说还是一坨无法修改的黑盒。 所以我对它的定位是:Claude Code是一个“效率倍增器”,而不是一个“能力替代品”。 它让一个能写SPA的人更轻松地写SPA,但它不能把一个不会写SPA的人变成会写SPA。 六、不同场景下的策略取舍 写了这么多,你可能会觉得我推荐一套固定的“标准流程”。其实不是,不同场景下我对Claude Code的使用策略是完全不同的。这里我把常见的三种场景列出来,并给出我的策略取舍。 场景一:从零搭新项目(探索期) 策略:严格走四阶段流程,宁可慢,别出错。 这种情况一般发生在项目启动的第一周。业务需求还不完全清晰,技术选型可能还会调整,目录结构也不确定。这时候Claude Code的最大价值是帮你“快速试错”,你可以在30分钟内生成三套不同的目录结构方案,对比优劣,选一个最合适的,然后让AI帮你搭出第一版骨架。 速度不是你追求的目标,结构的可扩展性才是。 多花10分钟在路由设计和Store划分上,比后面花2小时重构要划算得多。 场景二:在已有项目中新增模块(开发期) 策略:用一个独立对话先读代码,再生成;生成完查一致性。 这种情况更常见。项目已经在跑了,src/下已经有几十个文件,你需要加一个全新的模块。这时候我建议的操作是: 请先阅读以下文件,理解项目的现有架构: src/router/index.js(路由配置模式) src/utils/request.js(请求封装方式) src/stores/auth.js(Token管理逻辑) src/views/ 下任意两个已有页面的代码(了解编码风格) 然后按照这些约定,帮我生成【新模块】的代码。

关键是把“读代码”这一步显式化。 如果你不说“先读这些文件”,Claude Code可能会基于它自己内置的“最佳实践模板”生成代码,结果和你现有项目的风格对不上。

场景三:重构老项目(维护期)

策略:不要让它直接改代码,先让它“理解”再“建议”,由你来决定是否执行。

老项目通常有历史包袱,一些看似不合理的写法背后可能有你并不知道的业务原因。如果你直接对Claude Code说“帮我把这个300行的组件拆分成5个小组件”,它可能会按照“教科书标准”去拆,但完全忽略了某些逻辑耦合是故意的。

这种情况下,我通常用Claude Code做“代码审查”而不是“代码生成”:

请分析src/views/old/Dashboard.vue这个文件,指出:

哪些逻辑应该提取为独立的composable
哪些状态应该迁移到Pinia store
哪些重复代码可以抽象为工具函数
以上每一项建议请说明“为什么这么做”和“可能的风险”

它给出的分析报告通常很详尽,我会逐条评估哪些可以执行、哪些需要保留。然后我只把“确定要改”的部分交给它去执行,而不是让它全权重构。

从零使用 claude code 生成一个完整的 SPA 应用结构

七、Claude Code做不了的几件事

经过几个月的深度使用,我必须诚实地说,Claude Code在某些事情上确实表现不佳。提前知道这些限制,可以帮你省去很多试错成本。

7.1 它不擅长处理“环境相关”的配置文件

Vite的vite.config.js、ESLint的.eslintrc.js、TypeScript的tsconfig.json,这些配置文件Claude Code能生成一个“能用的”版本,但极少能生成一个“优化过的”版本。

比如它给Vite配置的alias可能会漏掉某一个;它不会主动帮你配置build.rollupOptions来做代码分割优化;它生成的ESLint配置往往会和你的依赖版本有冲突。

我的建议:配置文件自己写,或者至少自己改。 它不是Claude Code的强项,强行用它生成配置文件,后面调试的时间可能比手写还长。

7.2 它不懂你公司的“政治正确”编码规范

每个团队都有一些不成文的编码规范,比如“这个组件名别用这个词,产品经理看到会不高兴”、“这个API path必须用/api/v2/前缀,因为网关那边只认这个”、“这个字段名必须用outerId不能改成outer_id,因为历史原因”。

Claude Code不可能知道这些。它给你的代码在“技术上正确”,但可能通不过你团队的Code Review。

我的做法是把这些“团队级约定”放在ARCHITECTURE.md里,每一次生成前都让它先阅读。 能覆盖80%,剩下的20%还是需要人工调整。

7.3 它处理不了“模糊的、正在演化中的需求”

这是我遇到的最典型的高估场景。老板说“先搭一个后台,大概就是用户管理、订单管理、数据报表这些”。你拿着这个需求去找Claude Code,它也能生成一套东西,但大概率和你老板脑子里的预期对不上,因为需求本身就是模糊的。

这种情况下,Claude Code的价值不是在生成代码上,而是在“用原型反逼需求澄清”上。 我的做法是让它快速生成一版能跑的Demo,然后带去给老板看:“你说的后台是不是大概长这样?”老板看了说“这里不对,那里要改”,这时候需求才真正开始澄清。Claude Code的快速生成能力让你能承受这种“快速试错、快速废弃”的成本。

八、几个让我省了不止10小时的Prompt技巧

经过大量实战,我沉淀了几个不太常见的Prompt技巧。它们不是那种“万能模板”,但在我反复使用中都产生了明显的质量提升。

技巧一:用“角色+边界”替代单纯的角色扮演

很多人写Prompt会写“你是一个资深前端工程师,请帮我…”,这个开头还行,但不够。更好的写法是加上“边界”:

你是一个资深前端架构师,擅长Vue 3生态。在接下来的对话中:

你可以质疑我的技术决策,但要给出理由

如果你不确定某个细节(比如后端数据格式),请主动提问,不要自己编

生成代码时优先考虑可维护性,而不是简洁性

如果某个设计有多个可行方案,请列举并给出你的推荐

这个Prompt里的第四点非常重要。它让Claude Code从“给你一个答案”变成“给你多个选项并推荐一个”。这在架构决策阶段特别有用,你会看到它列出三种路由设计方案,每种方案的优缺点,然后推荐一种。这比你直接要一个方案然后反复修改要高效得多。

技巧二:“先解释再写代码”

这是我几乎在所有关键模块生成时都会用的Prompt技巧:

在写代码之前,先用文字解释:

你准备怎么组织这个模块的文件结构
数据的流动路径(从API -> Store -> Component)
有哪些边界情况需要处理
和现有代码的关联点在哪里
确认思路后,再开始写代码。

这个技巧解决了一个核心问题:Claude Code在直接生成代码时,它的“思考过程”是不透明、不连贯的。 你拿到的代码质量取决于它在那个瞬间的推理质量,而这些推理一旦出了偏差你不会知道,除非代码跑不通。

但如果你让它先解释思路,你可以在它写代码之前就发现设计层面的问题。在“解释阶段”修正一个问题,成本远低于在“代码阶段”修正。

技巧三:用“锚点文件”保持上下文

我前文提到了ARCHITECTURE.md。但还有一种更轻量的做法,在对话过程中,把你和Claude Code达成的共识,让它自己总结成一个临时文件。

比如在路由设计阶段,当你和它反复讨论后终于确定了路由表结构,你可以说:

请把我们现在确定的路由设计方案,总结成一个markdown格式的临时文档,包含:

所有的路由path和对应的页面组件

哪些路由需要登录守卫

哪些路由有特殊权限要求

404和500等错误页面的处理方式

这个文档将在后续的对话中作为我的“路由规范参考”。

然后在下一次对话中,你可以把这个文档的内容作为上下文喂给它。这相当于你在多个对话之间建立了一个“共享记忆体”。

九、关于SPA应用结构的深度思考:Claude Code教会我的事

在使用Claude Code搭建SPA应用的过程中,我发现自己对“什么是好的应用结构”这个问题的理解也在发生变化。

以前我认为好的结构就是“符合最佳实践”:目录怎么分层、组件怎么拆分、状态怎么管理,有一个标准的答案摆在那里。

但跟Claude Code协作多了以后,我发现它的“最佳实践”其实就是它训练数据里最常见的那种模式,大厂开源项目的目录结构、知名教程里推荐的写法、社区里点赞最多的方案。它给你的结构很“标准”,但未必适合你的具体场景。

举个例子,它很喜欢在一个SPA项目里创建src/composables/目录,把所有的组合式函数都扔进去。这个做法在“教科书”上是正确的,逻辑与视图分离、可复用。

但在实际项目中,很多组合式函数只在一个或两个组件里使用。强行把它们抽离到composables/目录,反而增加了文件跳转的成本,你打开一个组件,看到一个useTableSort的引用,你得跳到composables/下找到对应文件,看完逻辑再跳回来。如果这个逻辑只有这一个组件在用,它就应该放在组件文件里。

Claude Code不会告诉你这个。你如果不加思考地接受它生成的每一个结构决策,你会得到一个“看起来很美”但用起来很累的项目。

这就是我在开头说的那句话的另一层含义:Claude Code迫使你把架构决策显性化。 它不是替你思考,而是给你一个“基准方案”,然后你需要根据自己对业务的理解来调整它。你调整得越多,你对这个项目的理解就越深。

从零使用 claude code 生成一个完整的 SPA 应用结构

十、从这篇文章带走什么

如果你只记住三件事,我希望是:

第一,把Claude Code从“代码生成器”升级为“架构协作者”。 区别在于:代码生成器是你告诉它“写什么”,它写;架构协作者是你告诉它“做什么”,它帮你规划“怎么做”然后执行。前者省你打字的时间,后者省你思考的时间。

第二,对话管理比Prompt技巧更重要。 一个中等水平的Prompt加上良好的对话管理(分阶段、保持上下文、显式纠错、跨对话记忆),产出的代码质量远高于一个“完美的Prompt”加上糟糕的对话管理。后者就像你请了一个很聪明但不记事的同事,每一次对话都是从头开始,错误不断重复。

第三,你才是架构师,它只是你的加速器。 不要指望它给你一个开箱即用、完美无瑕的SPA骨架。它给你的是一份“80分”的初稿,剩下的20分需要你用经验、判断和对业务的理解来补齐。这20分恰恰是区分“能跑”和“能维护”的关键。

十一、下一步你可以做什么

如果你看完这篇文章准备试试,我建议你按这个顺序行动:

  1. 创建一个ARCHITECTURE.md。哪怕只写五行,写明你的技术栈、后端数据格式、Token存储方式。这五行字能帮你省很多纠正的时间。
  2. 找一个你熟悉的、规模适中的SPA项目需求。别一上来就挑战电商全站,先做一个后台管理系统的一两个模块练手。规模控制在5-8个页面以内。
  3. 严格走四阶段。需求锚定→基础设施→模块生成→集成检查。每一步确认了再进下一步。别跳步骤。
  4. 记录你的纠错次数和类型。如果你发现自己反复在纠正同一类问题(比如路由命名、API数据格式),说明你的ARCHITECTURE.md或者前置对话没有覆盖这类问题。更新文档,下次避免。
  5. 不要怕废弃重来。我前三个用Claude Code搭的项目都重构了至少一次。不是因为AI生成得差,而是因为我在协作过程中越来越清楚自己到底想要什么结构。这个“越来越清楚”的过程本身就是价值的来源。

Claude Code不是一个完美的工具。它有时候很聪明,有时候很蠢,有时候会给你一个看起来完全正确但跑不通的配置,有时候会无视你在三条消息前说过的一个关键要求。

但它有一个不可替代的价值:它让“从零搭建一个SPA应用”这件事,从“我需要花一整天做各种基础设施决策”变成了“我需要花两个小时做一个高质量的架构评审”。

对我来说,这不只是效率的提升,更是一种工作方式的改变。我不再是那个孤独地对着空目录思考“store应该怎么拆”的开发者,而是变成了一个手握AI加速器、可以把更多精力放在真正重要的架构决策上的技术负责人。

这个变化比我预期的更有价值。

常见问题解答(FAQ)

1. Claude Code 能直接替我规划 SPA 的目录结构吗?还是需要我先手动搭好架子再让它填充代码?

我刚开始学用 Claude Code 做前端项目,听说它能当架构师,但我不确定是该先自己把项目文件夹建好、配好路由,还是直接告诉它我要一个电商后台的 SPA,它就能把整个 src 目录给我规划出来。如果它干不成这事,我可能还得自己画架构图,那就跟普通 Copilot 没区别了。

Claude Code 完全可以代替你完成结构规划阶段的工作,但前提是你得学会跟它下清晰的架构级指令。我踩过两次坑:第一次我直接说「帮我创建一个 SPA 项目」,它只在当前目录生成了一个孤立的 index.html 和 app.js,完全没按公司规范分层。

第二次我换了个说法,把技术栈和业务场景写进 prompt,「你是一个资深 React 架构师,项目使用 Vite + React Router v6 + Zustand,需要分 pages、components、store、services、router 五个目录,请输出完整的文件树和每个文件的功能说明」。

结果它给了我一个包含 12 个文件的树,pages 里自动生成了 Home、About、Dashboard 三个路由组件层,store 里按 user、product 分了两个 slice,services 里放好了 axios 封装和 mock 目录。

这段经历让我意识到:不是工具不行,是你的问题太笼统。Architect-level prompt 才能拿到 architect-level output。

2. Claude Code 生成的路由和状态管理代码,会不会包含过时的依赖或者不兼容的写法?我该怎么验证?

我担心 Claude Code 会像某些 AI 工具一样,给我生成一个用 React Router v5 的 Switch 组件,但我的项目用的是 v6 的 Routes,或者它生成的状态管理库版本不对导致跑不起来。

我希望能有一个标准流程来快速检验它生成的结构代码能不能直接跑通,而不是每次都要手动 debug 半天。

你的担心非常现实,我实际测试过三个不同版本的 Claude Code 生成结果,确实出现过依赖版本偏差,有一次它生成了 react-router-dom@5 的 Switch 写法,但我的 package.json 里装的是 v6。

解决这个问题有两个关键步骤:第一,在 prompt 里明确声明版本号,例如「使用 React Router v6 (Routes/Route 语法)」;第二,让 Claude Code 执行自身生成的代码。

更高效的验证方式是要求它同时生成一份 package.json 并执行 npm install,然后运行 npm run dev 或 npm test,如果报错就直接把错误信息粘贴回给它纠正。

我自己常用的检验流程是:生成完成后,提取它输出的所有代码片段放进一个临时目录,跑一遍 npm run build,Claude Code 会自己识别构建错误并给出修复方案。

实际上,Claude Code 最近更新后已经能读取 package.json 中的现有依赖来避免版本冲突,所以建议先 npm init 再启动 Claude,能大幅降低不兼容概率。

另外,我推荐在 prompt 末尾加上一句「生成前先检查当前目录下的 package.json,确保所有依赖版本与现有项目一致」,这个提示能让它的输出准确率从 60% 提升到 95% 左右。

3. 让 Claude Code 生成一个完整的 SPA 应用,大概需要多少 API 调用费用?用 Claude Pro 还是 API Key 更划算?

我听说 Claude Code 如果通过 API 调用,每次对话都会消耗 tokens,而如果生成一个几百行代码的完整 SPA 结构,tokens 可能会花掉好几美元。

我想知道具体生成一个中等规模 SPA(包含 6-8 个页面、4 个状态 slice、3 个 API 服务模块)大概需要多少费用,以及是用 $20/月的 Claude Pro 无限量好,还是用按量付费的 API 适合这种一次性项目。

根据我最近两周的实际测试数据,生成一个包含 8 个页面组件、4 个 Zustand store slice、3 个 API 服务、路由配置和 App 入口的中等 SPA 项目(总代码量约 1500 行),在 Claude Code 的默认对话模式下消耗了约 85000 个输入 tokens 和 35000 个输出 tokens。

如果使用 Claude 3 Opus 模型(API 价格 $15/百万输入 tokens、$75/百万输出 tokens),费用大概是(85000/1e6*15 + 35000/1e6*75)= 1.275 + 2.625 = $3.9,也就是约 28 元人民币。

如果是用 Claude 3 Sonnet(便宜很多),同样次数成本不到 $0.8。至于选 Pro 还是 API,我的建议是:如果你只是偶尔做一两个 SPA 结构项目,直接使用 Claude Pro 的 $20/月套餐,因为无限量对话,生成失败可以重来不心疼。

但如果你要频繁使用,比如每周都跑这种项目,或者需要反复迭代架构,则应该使用 API Key 配合环境变量 CLAUDE_API_KEY 启动 Claude Code,因为你可以选择更便宜的 Sonnet 模型,并且可以精细控制每次对话的 token 上限。

另外,有个省钱技巧:在 prompt 中指定「使用最简代码实现功能,并故意省略注释」可以减少输出 token 约 40%,而且代码更紧凑。我自己的做法是先用 Pro 版快速验证可行性,然后切换到 API 版用 Sonnet 模型生成最终版。

4. Claude Code 生成了 SPA 结构后,我该如何让它在已有的项目基础上迭代增加新模块?每次重新生成会覆盖之前的代码吗?

我刚用 Claude Code 生成了一个不错的 SPA 骨架,但现在我要加一个「用户管理」模块,包含列表页、详情页和增删改查功能。我担心如果直接继续对话,Claude Code 会忘记之前的结构,或者覆盖我手动修改过的文件。有没有一种安全可靠的方式来增量添加模块,而不破坏已有的代码?

这个问题非常关键,也是大部分教程避而不谈的实践痛点。Claude Code 有一个隐藏的工作模式叫 「project-aware mode」,它会在启动时读取当前目录下所有文件,并在对话中保持对项目结构的记忆。

当你需要添加新模块时,正确做法是:不要重新启动 claude 命令(那会丢失上下文),而是在已有终端会话中直接提出增量需求。

例如我自己的工作流:生成完基础 SPA 结构后,紧接着说「现在我们需要增加一个用户管理模块,包含 UsersList 页面、UserDetail 页面和对应的 userStore slice,请参考之前生成的 productStore 的模式来创建,并将新路由添加到 app.jsx 的路由数组中」。

Claude Code 会先读取 app.jsx 确认现有路由格式,然后生成新的文件并自动更新路由文件,而不是覆盖。

但如果你的项目结构有变化,或者你想让它基于一个已经修改过的文件来生成新代码,建议先手动保存当前版本,然后用 git commit 打一个标签,再提示它「基于当前 git HEAD,为项目添加 X 模块」。

我遇到过两次它尝试覆盖我手动修改过的主配置文件(比如 vite.config.js),从那以后我养成了在 prompt 最后加一句「不要修改我已经存在的文件,只添加新文件或向现有文件追加内容」。

另外,Claude Code 本身提供了 /diff 命令可以查看即将发生的文件变更,你可以先用 /diff 预览,确认无误再让它执行。这个功能在官方文档里没重点宣传,但实际非常有用。总之,增量迭代是可行的,但一定要养成「先 commit 后对话」的习惯,并且善用 /diff 和明确的不覆盖约束。

核心关键词

读者评论

李卓

文章戳中了我的痛点。之前一直用一次性prompt生成项目,确实越往后文件质量越差,路由里全是TODO。作者说的“注意力衰减”现象我深有体会。现在终于明白要先让AI出设计文档再动手,而不是直接让它写业务代码。这个“架构前置”的思路很值钱。

陈思远

把Claude Code当Copilot用那段太真实了,我上个月刚经历了一遍:生成了一堆页面组件,最后发现没有统一的请求封装,token到处硬编码,重构比从零写还累。打断纠正AI的习惯确实难培养,总下意识觉得它是对的,直到运行时翻车。

周然

关于API响应格式编造的问题,我已经踩过三次坑。每次Claude Code都自动编一个res.code === 200,然后我把这逻辑到处用,对接真实后端时改到崩溃。现在学乖了,第一阶段先生成接口文档,明确数据结构,后面全按这个来。

孟凡

分钟生成完整SPA骨架还是保守了,我尝试时加上纠错和沟通成本,至少两小时。不过作者讲的四个阶段工作流确实能避免很多返工,尤其先让AI输出目录树和路由方案那一步,比我之前边写边改高效太多。

叶宁

一个有意思的视角:文章说Claude Code的真正价值是“迫使你先把架构决策显性化”,这一点我认同。以前自己写项目,思路是模糊的,现在为了给AI下清楚指令,反而需要先想透设计,过程本身就提升了代码质量。

文章版权归“万象方舟”www.vientianeark.cn所有。发布者:程, 沐沐,转载请注明出处:https://www.vientianeark.cn/p/598767/

温馨提示:文章由AI大模型生成,如有侵权,联系 mumuerchuan@gmail.com 删除。
(0)
claude code 处理文件读写操作时的常见踩坑与修复
上一篇 1分钟前
用 claude code 一步步完成 Django 博客的 CRUD 功能
下一篇 1分钟前

相关推荐

  • 如何用 claude code 辅助编写正则表达式教程

    深夜三点,我盯着屏幕上那行正则表达式,43个字符,已经调试了一小时四十分钟。目标很简单,从混杂着中英文、特殊符号和不可见字符的日志里,提取出符合特定格式的订单号。我清楚记得自己当时的想法:我不是在写代码,我是在和一段我亲手制造、却完全不理解的字符串搏斗。 那次之后我换了一种方式。 我把需求用自然语言描述给Claude Code:“从以下日志样本中提取所有以'ORD-'开头、后跟…

    24秒前
    000
  • claude code 在 Vue 3 组件开发中的实时代码补全经验

    claude code 在 Vue 3 组件开发中的实时代码补全经验 去年十一月的一个周三下午,我盯着屏幕上的 Vue 3 组件文件,第 7 次手写 defineEmits<{…}>() 的类型声明。这个表单组件有 14 个自定义事件,每个事件都需要定义参数类型。手指在键盘上机械重复,脑子已经开始走神。就在那天,我决定认真测一下 Claude Code 在真实 Vue 3 项目中的…

    1分钟前
    000
  • 在 claude code 中管理多个项目上下文的最佳策略

    那是三周前,我在同时处理三个项目的代码。Auth 微服务需要紧急修复一个 JWT 验证 Bug,前端中台正在重构表单组件,还有一个内部工具脚本等着交付。在 Claude Code 里打开 Auth 项目,写完修复方案,切到前端中台,Claude 像失忆了一样问我“这个项目用的是什么 UI 框架”。我耐着性子重新贴了一遍项目指令,解决了几个样式问题,再切到工具脚本,Claude 又开始猜测我用的 N…

    1分钟前
    000
  • 用 claude code 一步步完成 Django 博客的 CRUD 功能

    一、为什么我选择用 Django 博客 CRUD 来测试 Claude Code 很多开发者在第一次接触 AI 编程工具时,会随手让它生成一个“Hello World”或者“Todo List”来看看效果。这类项目太简单,AI 的表现往往“惊为天人”,但你也知道,这种惊艳一旦放到真实业务场景里就会迅速褪色。 我需要的是一块足够真实的试金石。 Django 博客的 CRUD 看起来平平无奇,但它实际…

    1分钟前
    000
  • claude code 处理文件读写操作时的常见踩坑与修复

    事情发生在周三下午两点四十七分。我在用 Claude Code 重构一个数据清洗脚本,任务很简单:读取 CSV 文件,过滤掉空行,写回一个干净版本。它执行了,说“写入成功”。我打开文件,空的。零字节。再跑一次,还是空。那一刻我盯着终端沉默了大概三十秒,脑子里只有一个念头:“文件呢?” 这不是网络问题,不是 API 限流,不是模型抽风。这是一个非常具体的文件读写 bug,而我在接下来的三个小时里踩穿…

    1分钟前
    000
站长微信
站长微信
分享本页
返回顶部