一句话生成的应用通常能直接启动、页面也齐,但接手时卡住的不是“能不能改”,而是从哪个文件下手不会把已经能跑的部分弄坏。判断顺序建议是:先看渲染层的文案、样式、布局能不能直接改,再看状态、请求、路由这些逻辑层是不是占位实现。前者一般只影响一个组件,后者往往牵连多个调用方,需要先定位、再替换、最后验证。
生成结果里能直接改的多是组件样式、静态文案和配置型参数;需要替换或重写的是写死的示例数据、请求地址和业务状态流转。建议先跑通启动拿到第一条真实报错,再用一处文案改动确认热更新链路,然后按关键词搜索占位数据逐处替换,每一步用一次提交或备份留住回退点。改 store、路由和请求封装前,先数一遍调用方,调用方超过两处就先不急着动。
在生成项目里按目录确认各层职责
生成项目常落成下面这类结构,名字可能不同,职责划分基本一致。先打开文件树对照一遍,比逐文件读代码更快。
src/
├── components/ 局部 UI 与复用组件
├── pages/ 或 app/ 路由与页面入口
├── hooks/ 复用逻辑
├── services/ 或 api/ 请求封装
├── store/ 或 context/ 全局状态
├── utils/ 工具函数
├── config/ 或 constants/ 常量与配置
├── styles/ 或 assets/ 样式与静态资源
public/
.env 或 .env.local
- components:改动影响范围落在单个组件或局部布局,样式与文案改动优先从这里进。
- pages / app:改动会影响路由入口、页面布局和该页的数据装配,动之前先翻它的引入关系。
- services / api:改动直接影响请求地址、入参和返回结构,通常是被多处调用的中间层。
- store / context:全局状态,改字段名或结构很容易连带多个组件报错,属于高风险区。
- utils、config:被谁引入就从谁开始验证,工具函数改动的影响范围靠搜索调用点确认。
- .env:只放环境相关配置;改完一般需要重启开发服务才生效。
从入口文件把生成结果在本地跑起来
先确认能启动,再谈改动。按仓库里的 lock 文件选包管理器,不要在同一个项目里混用 npm、pnpm、yarn,否则依赖树容易对不上。
npm install
npm run dev
# 使用 pnpm 时
pnpm install
pnpm dev
正常启动时终端能看到本地地址,形状大致如下,端口和构建工具会不同:
> dev
> vite
ready in 400 ms
➜ Local: http://localhost:5173/
如果起不来,先原样记下第一条报错,再判断是缺依赖、路径写错还是版本不匹配。缺依赖的典型形态是这几类:
Error: Cannot find module 'xxx'
Module not found: Can't resolve './yyy'
ERR_MODULE_NOT_FOUND
看到“Cannot find module”时,先确认该依赖是否在 package.json 里,再决定是补安装还是改引入路径,不要直接删掉报错的引入。
改一处文案或样式验证改动生效路径
用一个最小改动确认热更新和构建链路正常。挑一个组件里的按钮文案,改前是“Submit”,改成“提交”:
// 改动前后对比
- <button>Submit</button>
+ <button>提交</button>
保存后浏览器应自动刷新该区域,终端一般会打印类似“hmr update”的记录。页面没变化时,按顺序排查:文件是否真的保存、改的是不是被引用的那份组件、浏览器是否命中了缓存。
有几类改动不靠热更新,需要重启开发服务才生效:.env 里的环境变量、构建工具配置文件(如 vite.config、next.config)、样式框架的扫描路径配置(如 tailwind.config 的 content)、以及代理或路由的全局配置。判断方式很简单,改完不生效就先重启一次再看。
在逻辑文件里定位需要替换的占位数据
生成代码里最常见的坑是数据没接真实接口,数组直接写在函数体里。用关键词搜一遍,范围先限制在 src 下:
grep -rn "localhost:3000\|example.com\|mock\|dummy\|TODO" src/ \
`--include`="*.ts" `--include`="*.tsx" `--include`="*.js" `--include`="*.jsx"
中文项目再加“示例”“测试数据”“假数据”几个词。搜到的结果里,services 或 api 目录优先处理,组件内部的硬编码数组看它是否只是展示兜底。
// 生成结果里的常见形态
export async function fetchList() {
- return [
- { id: 1, name: '示例项目 A' },
- { id: 2, name: '示例项目 B' },
- ];
+ const res = await fetch(`${import.meta.env.VITE_API_BASE}/list`);
+ if (!res.ok) throw new Error(`请求失败:${res.status}`);
+ return res.json();
}
替换后不要只看页面有没有数据。打开浏览器网络面板确认请求地址和状态码,再确认渲染出来的字段名和接口返回一致;顺手点一次空数据或错误状态,看组件是否有兜底,避免接口异常时整页白屏。
把改动控制成可对比可回退的粒度
生成结果一上来就大改,出问题时无法判断是哪一步引起的。先把当前状态固定成基线:
git init
git add -A
git commit -m "baseline: generated code"
之后按类别分别提交:样式与文案一次、请求数据源一次、全局状态一次。每类改动完成后跑一次构建确认没有引入编译错误,再打开目标页面确认行为符合预期、控制台没有新增报错。构建通过了但页面行为不对,说明问题在逻辑而不是语法,回到这次提交的 diff 里看。
git diff # 看这次改了什么
git checkout -- src/xxx.ts # 放弃单个文件的改动
git stash # 临时收走未提交改动再复现问题
如果某个文件改动后牵连多处报错,先回退到上一个检查点,把这次改动拆成更小的两步再做。凡是涉及 store 字段、路由结构、请求返回格式的改动,都建议单独提交一次,方便逐个回退而不是整段推翻。