AI 写前端很快,但为什么一接设计稿和 Socket 就开始失控?

0 阅读10分钟

从“能跑一整局的 Demo”到“可联调的成品”:一次五子棋联机高保真重构复盘

一开始,我以为这个项目已经差不多做完了。

因为从功能层面看,它并不差:能创建房间、能加入房间、能通过 Socket 联机、能完整下一整局棋,判赢也能跑,演示的时候看上去并没有什么明显问题。放在很多场景里,这样的结果已经足够被称作“一个做出来的 Demo”。

但这次在按原图重新做高保真重构,并把前后端联调真正跑顺之后,我才非常明显地意识到一件事:

“能跑的 Demo”和“可交付的成品”,中间隔着的不是几个功能点,而是一整套边界控制、状态治理和工程收束能力。

这篇文章,不是想讲五子棋本身怎么写,而是想复盘一个更真实的问题:

为什么一个“看起来已经做完”的前端 Demo,在真正按需求落地的时候,会突然暴露出这么大的差距?


一、项目表面上很小,实际并不轻

如果只看需求描述,这个项目非常容易被低估。

目标看起来很简单:

  • 按设计稿高保真还原 3 个页面
  • 支持房间创建与加入
  • 支持局域网联机
  • 支持悔棋
  • 支持最后一步红点标记
  • 支持移动端全屏适配

很多人第一反应都会是:

“这不就是一个小游戏前端吗?AI IDE 补一补,几小时就差不多了。”

我一开始其实也有类似判断。毕竟自己之前已经做过一个版本,基础逻辑和联机流程都通了,甚至已经可以完整下一整局棋。当一个项目已经满足“能玩”的时候,人很容易高估它离“做完”还有多近。

但真正开始重构后,问题就一点点露出来了。

这个项目真正的难点,不在于某一项功能本身,而在于它同时叠加了几种很容易互相打架的约束:

  1. 视觉约束:不能自由设计,必须贴原图
  2. 状态约束:页面切换不能靠感觉,必须由房间状态驱动
  3. 通信约束:Socket 事件、payload、状态枚举必须与服务端一致
  4. 渲染约束:棋盘不是普通 DOM,而是 Canvas,需要处理尺寸、自适应、点击换算和高 DPI
  5. 联调约束:不仅要“看起来对”,还要在双端操作、悔棋、重开、返回大厅时都正常

这些约束叠在一起以后,它就不再是一个“很快能糊出来的小页面”,而更像一个中小型实时交互前端模块


二、项目真正失控的起点,不是代码,而是“AI 的过度理解”

这次复盘里最值得说的,其实不是某段代码,而是 AI IDE 的角色。

一开始之所以会跑偏,并不是因为 AI 不会写,而是因为它太会“补全”了。

问题在于,这种补全很多时候不是你要的。

比如你给它的真实任务是:

  • 按原图做
  • 不要改布局
  • 不要改气质
  • 只在现有结构里补功能

但如果约束不够严格,AI 往往会自动理解成:

  • 我可以顺手优化布局
  • 我可以补完整个大厅页
  • 我可以加入更常见的产品模块
  • 我可以让页面“更合理”“更完整”“更现代”

于是很快就会出现这些问题:

  • 原图里没有的 topbar、快捷入口、聊天区、状态栏被补出来了
  • waiting 页从“安静的对弈室”等待页,变成了“功能完整的房间大厅”
  • game 页的棋盘被缩小,信息栏反而占了主视觉
  • 视觉气质从原图的深蓝金色克制风,慢慢偏成另一套更“标准”的游戏 UI

这一步给我的冲击其实很大,因为它让我非常明确地意识到:

AI 最大的优点是补全,最大的风险也是补全。

在工程场景里,很多时候你最需要的不是它“帮你想更多”,而是它不要多想


三、这次真正起作用的,不是继续生成代码,而是先“锁边界”

项目后来能被拉回来,核心不是因为我们又换了一版代码,而是因为方法变了。

在前期几次跑偏之后,我开始意识到,继续让 AI 一边理解需求一边往下写,只会不断引入新的偏差。真正有效的方式,是先让它停下来,先把边界说死。

后来整个流程逐步稳定下来,靠的是这几步:

1. 先提取视觉锚点

先明确每个页面里绝对不能动的东西

  • lobby 的大标题、左侧装饰棋盘、右侧主卡片
  • waiting 的三栏构图
  • game 的左右玩家卡 + 中央棋盘 + 底部操作栏

2. 明确禁止新增内容

把原图里没有的内容直接列成黑名单,比如:

  • 顶部复杂导航
  • 快捷入口
  • 聊天区
  • 在线人数
  • 资产模块
  • 多余统计面板

3. 先压最小 HTML 骨架

不是一开始就让 AI 做完整产品,而是先让它只输出:

  • 最小 screen 结构
  • 最小 DOM 骨架
  • 最少必要容器

4. 再逐步补 CSS、补 JS

顺序改成:

  • HTML 骨架
  • 基础 CSS
  • 页面 CSS
  • 状态层
  • UI 层
  • 棋盘层
  • Socket 层
  • App 协调层

这个过程本质上是在做一件事:

把 AI 从“设计师”切换成“施工队”。

一旦边界先被锁住,后面的代码补全才真正开始变得有价值。


四、我以前那个版本为什么“能跑”,但还是不像成品

这次让我最有感触的一点,是重新理解了“Demo 做完”和“项目做成”之间的差别。

我之前那个版本,客观上已经不是玩具了。
它可以完整对弈,逻辑链路也基本闭环,作为一个演示版本其实已经能说明很多问题。

但它的问题在于:

1. 它解决的是“有没有”

比如:

  • 有没有房间系统
  • 有没有联机
  • 有没有落子
  • 有没有判赢
  • 有没有页面切换

这些答案都是“有”。

2. 但它没有真正解决“为什么稳”

比如:

  • 页面切换是不是状态驱动的?
  • 是否和原图足够一致?
  • UI 和 Socket 是否耦合过重?
  • 返回大厅会不会残留旧状态?
  • 重开/悔棋这些边缘流程是否可控?
  • 代码结构是否经得住继续加需求?

这些问题,在 Demo 阶段经常会被忽略,因为它们不会立刻阻止功能演示成功。

但到了真正想把东西做“像样”的阶段,这些问题会一起冒出来。

也正是在这个过程中,我才真正理解到一句话:

Demo 证明你会把功能拼起来,成品才证明你能把系统收住。


五、这次最重要的工程收益:不是页面,而是分层

从工程角度看,这次最值钱的结果,其实不是某个页面做得多像,而是最终形成了一个比较清晰的前端分层:

  • state.js:收敛全局状态树
  • ui.js:只负责 DOM 更新与弹窗/提示
  • board.js:只负责 Canvas 棋盘绘制和坐标换算
  • socket.js:只负责通信和状态同步
  • app.js:只负责初始化、事件绑定和模块协调

这个拆分听起来普通,但对这种项目来说非常关键。

因为五子棋联机这种东西,非常容易长成下面这种“能跑但不敢动”的结构:

  • Socket 收包时直接改 DOM
  • 点击棋盘时顺手判赢顺手弹 toast
  • 页面切换和房间状态混在一起
  • 棋盘绘制和 UI 状态写在同一个文件
  • 返回大厅时靠刷新页面兜底

这样写不是完全不能跑,但一旦你继续加:

  • 悔棋
  • 最后一步红点
  • 再来一局
  • 返回大厅
  • 移动端适配
  • 断线重连

整个结构会迅速变脆。

而这次至少做到了:每一层各管一件事
这意味着它已经不再只是“一个能演示的原型”,而是一个可以继续长功能的基础盘。


六、联调前最值钱的一步:读服务端代码,做协议对表

如果说这次前端部分的分层是工程上的收获,那联调前的协议对表就是项目成功的关键节点之一。

因为前端在没有明确协议之前,非常容易陷入一种假象:

“我大概知道服务端会返回什么。”

但“大概”这个词,在 Socket 项目里是最危险的。

后来真正去读 server.js,把这些内容一一对齐之后,很多问题一下就清楚了:

  • 客户端 emit 的事件名是否真实存在
  • 服务端返回的 on 事件名是否匹配
  • payload 字段结构是否一致
  • 状态枚举值是不是同一套
  • 有没有前端擅自虚构的协议方法

比如这次就发现了两个典型问题:

  • replyRestart 是前端脑补出来的,服务端实际没有
  • resignGame() 也是前端默认以为会有,但后端并未实现

如果这两处不提前对表,到联调阶段就会出现一种非常浪费时间的情况:

  • 页面看起来没问题
  • 按钮逻辑也写了
  • 但就是点了没反应

这种问题表面像前端 bug,实质上是协议不一致。

所以这一步给我最大的提醒是:

实时项目里,前端写得再漂亮,如果协议是猜的,本质上都不算完成。


七、从这次经历里,我学到的不是“怎么写五子棋”,而是“怎么收束一个项目”

如果只从技术点来说,这个项目涉及的东西都不算特别新:

  • HTML / CSS
  • JavaScript
  • Canvas
  • Socket.io
  • 状态管理
  • 页面切换

单独拿出来,每一样都不至于难到离谱。

但真正难的,是把它们放在一起以后,依然能保持:

  • 设计不跑偏
  • 逻辑不打架
  • 状态不乱流
  • 通信不猜测
  • 结构不塌掉

也正因为这样,这次最大的成长其实不是“学会了某个 API”,而是第一次更清楚地理解了一个前端项目在变成成品之前,究竟需要经历什么:

不是只会写

还要会:

  • 锁边界
  • 控复杂度
  • 做分层
  • 对协议
  • 查风险
  • 修收口

这些东西平时在做原型时感受不深,但一旦你真的想把东西做成成品,它们就会变成决定成败的关键。


八、结语:AI 能帮你提速,但工程收束必须靠人

如果让我用一句话总结这次复盘,我会这么说:

AI 可以帮你快速把房子搭起来,但房梁怎么放、承重怎么做、线路怎么走、哪里不能改,最终还是要靠人来做边界控制。

这次项目最开始差点被做成一个“功能看着很多,但结构和视觉都失控”的缝合怪。
但也正因为经历了这轮纠偏,我反而更清楚地看到了:

  • AI 适合补全
  • 人负责判断
  • Demo 解决的是可行性
  • 工程解决的是成立性

以前我会觉得“能下一整局就算做完了”。
现在更愿意承认:那只是做出了一个功能闭环的 Demo。

而这次,才算是真正逼近了一个可联调、可维护、可继续扩展的成品前端

如果以后再遇到这种“看起来不大、做起来却像真项目”的需求,我大概不会再低估它了。
因为我已经很清楚地知道:

真正难的,从来不是把功能写出来,而是把所有边界一起收住。