gptupcn.com

前端开发很适合 AI,但也最容易出现一种假象:页面“看起来能跑”,实际上状态管理、可访问性、性能、类型、错误边界和组件职责已经开始失控。

所以这篇文章不做“让 GPT‑6 Astra 生成一个漂亮页面”的教程,而是讨论更偏工程化的用法:如何用 ChatGPT Pro + Codex + GPT‑6 Astra 维护一个中大型 React / TypeScript 项目。真正有价值的不是让 AI 多写几个 JSX,而是让它在状态、数据流、测试、构建和 Review 之间持续工作。

一、组件拆分不是越细越好

假设一个 Dashboard:

Dashboard
├── Header
├── Filters
├── Chart
├── Table
└── Pagination

很多 AI 会自然地把每个小块继续拆成很多文件。但真正应该问的是:哪些状态共享?哪些组件有业务语义?哪些只是展示?哪些数据请求应该集中?哪些组件会独立复用?

例如:

type Filters = {
  keyword: string
  status: "all" | "active" | "disabled"
}

如果 Filters 同时影响图表、表格和 URL,那么它更像页面级状态,而不是某一个子组件自己的状态。组件边界应该围绕职责和变化,而不是围绕代码行数。

二、把 URL 当作可分享状态

错误做法:

const [status, setStatus] = useState("all")

刷新页面后筛选消失。更好的方式可能是:

const params = new URLSearchParams(location.search)
const status = params.get("status") ?? "all"

function updateStatus(status: string) {
  const next = new URLSearchParams(location.search)
  next.set("status", status)
  navigate(`?${next.toString()}`)
}

这样刷新可恢复、链接可分享、浏览器前进后退也更自然。GPT‑6 Astra 可以帮助判断哪些状态应该进入 URL,哪些不应该。比如临时 Hover、弹窗动画进度就没必要放进 URL,而筛选、分页、排序往往适合。

三、类型系统应该表达业务状态

常见代码:

const [data, setData] = useState<any>(null)

然后:

if (!data) return <Loading />

问题是 null 到底表示 loading、error、empty 还是未请求?更清晰的方式是判别联合:

type LoadState<T> =
  | { type: "idle" }
  | { type: "loading" }
  | { type: "success"; data: T }
  | { type: "error"; message: string }

组件:

switch (state.type) {
  case "loading":
    return <Spinner />
  case "error":
    return <ErrorView message={state.message} />
  case "success":
    return <Table rows={state.data} />
  default:
    return null
}

非法状态更少,后续 Codex 修改也更容易保持一致。

四、让 Codex 先读组件调用链

不要直接:

重构 Dashboard。

可以改成:

阅读 Dashboard 以及所有直接子组件。
先不要修改。

输出:
1. 状态来源;
2. 数据请求位置;
3. props 传递链;
4. 重复计算;
5. any 使用;
6. 可能的性能问题;
7. 缺少的 loading/error/empty 状态。

先建立事实,再决定重构范围。很多前端问题不是“代码太长”,而是数据责任不清楚。

五、性能优化一定要先测量

不要因为模型建议 useMemo 就到处加 useMemo/useCallback。性能优化首先要问:真的慢吗?慢在哪?重新渲染次数?bundle 大小?接口延迟?主线程阻塞?

例如大列表:

{rows.map(row => (
  <Row key={row.id} row={row} />
))}

如果只有 50 行,虚拟化可能完全没必要;如果 50,000 行,才需要进一步设计。模型的建议必须结合 Profiling 证据。

可以让 GPT‑6 Astra 先根据 React Profiler 结果解释:

哪个组件重复渲染最多?
是 props 引用变化还是状态范围过大?
优化后如何证明有效?

这比盲目加缓存 Hook 更专业。

六、API 类型是前端工程最重要的边界之一

不要让多个组件手写互相不一致的类型。更理想的是:

OpenAPI → 自动生成 client/types → 前端统一使用

如果暂时不能生成,至少集中 API 层:

export async function getUser(id: number): Promise<User> {
  const res = await fetch(`/api/users/${id}`)

  if (!res.ok) {
    throw new ApiError(res.status)
  }

  return res.json()
}

不要让 30 个组件各自 fetch、各自解析错误。统一 API 层还可以集中处理 request id、超时、重试、鉴权刷新和错误映射。

七、Error Boundary 与请求错误是两回事

请求错误:

if (query.isError) {
  return <RetryPanel />
}

组件运行时错误则需要 Error Boundary。二者来源不同。做前端 Review 时,可以明确要求 GPT‑6 Astra 区分:网络失败、业务失败、渲染失败、权限失败、空数据和部分数据失败。

如果所有异常都只显示:

Something went wrong

用户体验和调试体验都会很差。

八、可访问性应该进入验收

按钮不要写成:

<div onClick={submit}>提交</div>

更适合:

<button type="button" onClick={submit}>
  提交
</button>

还要检查键盘操作、focus、label、aria、颜色对比、图片 alt 和表单错误提示。可以让 Codex 单独做 accessibility review,而不是把视觉和可访问性混在一起。

例如表单:

<label htmlFor="email">Email</label>
<input id="email" name="email" aria-describedby="email-error" />
<p id="email-error" role="alert">邮箱格式错误</p>

这些细节很适合被自动化检查和测试锁住。

九、测试用户行为,不要测试实现细节

React Testing Library:

render(<LoginForm />)

await user.type(
  screen.getByLabelText("Email"),
  "a@example.com"
)

await user.click(
  screen.getByRole("button", { name: "登录" })
)

expect(
  await screen.findByText("欢迎")
).toBeInTheDocument()

这种测试锁的是用户行为。AI 重构内部实现时,只要行为没变,测试就应该继续通过。

十、前端最容易被 AI 顺手破坏的是设计系统一致性

假设项目统一使用 8px spacing scale、语义颜色、固定圆角和统一组件。Codex 新增页面却直接写:

margin: 13px;
color: #3377ff;
border-radius: 7px;

所以 AGENTS.md 可以写:

## UI rules
- use existing design tokens
- do not introduce raw hex colors
- use spacing scale
- reuse Button/Input/Card before creating new variants

这样 AI 不容易制造第二套设计系统。

十一、Bundle 变化应该纳入 Review

构建前:

main.js 320 KB

修改后:

main.js 810 KB

即使测试全绿,也值得检查。常见原因包括引入完整图表库、日期库导入方式错误、tree-shaking 失效或把服务端包带入浏览器。

把 bundle 报告和代码 diff 一起交给 GPT‑6 Astra,分析会比只看源代码更靠谱。模型可以帮助追踪“哪个 import 导致体积变化”,但最终要用构建报告证明。

十二、Codex 前端任务最好做垂直切片

不要:

重做整个前端。

更建议:

本轮只完成 UserList:
- API client
- loading
- error
- empty
- table
- pagination
- tests

不修改全局主题。
不升级依赖。
不重构其他页面。

任务越明确,最终 diff 越容易审查。

十三、用 Story 或页面状态清单减少漏状态

一个常见页面至少可能有:

loading
empty
normal
partial data
permission denied
network error
server error

如果只看正常截图,AI 很容易忽略剩余状态。可以把它们写成 Storybook Story 或测试 Fixture,让 Codex 每次修改都能看到这些状态。

十四、表单逻辑适合做“Schema + UI”分离

例如使用 Zod:

const schema = z.object({
  email: z.string().email(),
  password: z.string().min(8),
})

UI 只负责呈现错误,不应该在多个组件里复制校验规则。这样以后需求变化,Codex 只需要修改统一 Schema 和对应测试。

十五、前端 Review Prompt

审查当前 PR 的前端改动。

按以下顺序:
1. correctness
2. type safety
3. loading/error/empty
4. accessibility
5. performance
6. API compatibility
7. design-system consistency
8. missing tests

每个问题必须给文件和代码证据。
不要把纯风格偏好列为 bug。

这能明显减少“泛泛而谈”的 Review。

十六、为什么重度前端工作更偏向 Pro

一个复杂前端需求可能需要:

需求
→ 设计
→ API
→ 组件
→ 状态
→ 测试
→ 类型
→ 性能
→ 可访问性
→ 构建
→ Review

Codex 在其中会反复读写很多文件。Plus 能很好地完成学习和大量单次任务;但如果你每天持续用 Astra + Codex 做页面、组件和工程 Review,Pro 更容易成为真正的主工作环境。

官方当前的使用安排也说明,Plus 的 Astra 在 Work/Codex 中属于有限使用,而 Pro 可以用现有完整 allowance。对重度开发者来说,这种持续任务能力比单次回答长度更有意义。

十七、前端任务完成标准

一个页面“能显示”并不等于完成。至少确认:类型检查通过;loading、error、empty、success 四类状态合理;键盘可操作;主要交互有测试;URL 状态可以恢复;API 错误有统一处理;没有把秘密打入 bundle;没有随意引入另一套颜色和间距;构建通过;bundle 变化可解释;移动端布局没有明显破坏。

把这些标准写进仓库后,Codex 才能持续按照团队真正的前端质量要求工作。

十八、真正需要 AI 帮忙的不是 JSX

今天模型生成 JSX 已经不难。真正费脑的是:状态是否合理?数据流是否可维护?失败路径是否完整?组件边界是否稳定?API 是否一致?性能是否真的有问题?

GPT‑6 Astra 的价值更容易出现在这些问题上,而 Codex 的价值则是把建议变成仓库修改、测试和构建结果。

结语

如果只是让 AI 生成页面,现代模型都能给出不错结果。但当你把 ChatGPT Pro + GPT‑6 Astra + Codex 放进一个真实 TypeScript / React 仓库,它的价值会从“写页面”转向“维护整个工程”。

更成熟的工作方式是:模型辅助判断,Codex 修改仓库,类型系统限制错误,测试锁住用户行为,构建与性能数据提供证据,人工决定产品体验。

官方参考资料

  • OpenAI Help:ChatGPT Work and Codex
    https://help.openai.com/en/articles/20001275
  • OpenAI Help:GPT‑5.6 and GPT‑6 Pro in ChatGPT
    https://help.openai.com/en/articles/20001354-gpt-56-and-gpt-6-pro-in-chatgpt
  • OpenAI Release Notes:Introducing GPT‑6 Astra
    https://openai.com/products/release-notes/
  • OpenAI Developers:GPT‑6 Astra
    https://developers.openai.com/api/docs/models/gpt-6-astra

十九、进阶实践:把页面状态做成可枚举测试矩阵

前端 Bug 经常不是正常状态出错,而是“两个边缘状态同时出现”。例如用户有权限但数据为空、请求失败后点击重试、分页最后一页删除一条记录、搜索条件改变时旧请求稍后返回。

可以先列矩阵:

permission: allowed / denied
request: loading / success / error
result: empty / non-empty
viewport: desktop / mobile

不需要把所有组合都做成 E2E,但至少能识别关键组合。让 GPT‑6 Astra 根据组件状态机挑出高风险组合,再让 Codex 补成测试,通常比单纯要求“提高测试覆盖率”更有效。

二十、异步请求要考虑竞态

假设用户快速输入:

a → ab → abc

如果三个请求都发出,最早请求可能最后返回,从而覆盖最新结果。可以使用 AbortController 或请求序号控制:

useEffect(() => {
  const controller = new AbortController()

  fetch(`/api/search?q=${encodeURIComponent(q)}`, {
    signal: controller.signal,
  })

  return () => controller.abort()
}, [q])

GPT‑6 Astra 做前端 Review 时,如果只看单个 render 很容易忽略这种时间维度;可以明确让它检查“快速连续操作、旧请求覆盖新请求、重复提交”等异步问题。

二十一、前端错误监控要能映射到发布版本

生产错误如果只有堆栈,没有版本号,很难知道是哪个部署引入。建议日志或错误监控同时记录:

app_version
route
release_sha
request_id
browser

再把 Source Map 与发布版本对应。这样 Codex 在处理线上问题时,可以根据明确版本定位仓库状态,而不是拿当前 main 去猜昨天的 Bug。

二十二、服务端状态和客户端状态不要混为一谈

很多前端项目把所有数据都塞进一个全局 Store,最后用户信息、弹窗开关、搜索结果、分页缓存和服务器请求状态混在一起。随着 AI 不断加功能,这种结构会越来越难维护。

更清晰的思路是区分:服务器状态来自 API,需要缓存、失效、重试;客户端 UI 状态属于当前页面或交互。像 React Query 一类工具适合管理服务器状态,而简单弹窗开关可能只需要本地 useState。是否需要全局状态,要根据共享范围决定,而不是因为“以后可能用到”。

可以让 GPT‑6 Astra 对现有 Store 做分类:哪些字段其实是远程缓存、哪些只被一个组件使用、哪些是跨路由真正共享的。Codex 再按小范围迁移,避免一次性重写整个状态层。

二十三、SSR/CSR 边界也应该进入 Review

现代前端越来越多地混合服务端渲染和客户端交互。如果把只应在服务器运行的代码带进浏览器,可能泄露环境变量或增加 bundle;反过来,把依赖浏览器 API 的代码放到服务端又会直接报错。

Review 时可以明确检查:

哪些组件必须 client?
哪些数据可以 server fetch?
哪些密钥只存在服务器?
 hydration 后是否会产生状态不一致?

GPT‑6 Astra 对跨文件依赖比较适合找这类边界问题,而构建工具和测试负责最终证明。

二十四、视觉回归可以补足“代码正确但页面变了”

单元测试不容易发现按钮错位、字体溢出或移动端布局破坏。关键页面可以加入截图基线或视觉回归测试。它不需要覆盖所有像素,但至少保护登录、订单详情、核心表格等高价值页面。

Codex 修改 CSS 后,除了 npm testnpm run build,还可以生成新的截图差异供人 Review。AI 可以解释变化原因,但是否接受视觉变化应该由设计规范和 Reviewer 决定。这样前端 AI 工作流就从“代码层”延伸到真实用户看到的结果。

二十五、补充:前端 AI 开发要保留浏览器中的真实验证

即使类型、单测和构建全部通过,也应该对关键页面做一次真实浏览器验证。因为焦点顺序、滚动、响应式断点、输入法、文件选择、下载行为等问题,未必能从静态代码中发现。可以让 Codex 准备检查清单和自动化脚本,但最终仍要用浏览器结果确认。对高频 Pro 用户来说,这种“代码→测试→浏览器→再修正”的完整闭环,比单纯生成组件更能体现 Astra 与 Codex 的价值。

Logo

AtomGit AI 社区提供模型库、数据集、Agent、Token等资源

更多推荐