NeuralOS
GuideAdvanced

AI 代码手术 · 让你的应用内部无懈可击的 7 阶段协议

AI 是一名飞快的泥瓦匠:几秒就砌好一面墙。但它到处留下瓦砾——没人调用的死代码,同一段逻辑复制到五个地方,像撒盐一样撒下的 `any`,让 GPU 出汗的动画。你的应用外表看着漂亮;内部却在生锈。这份资源给你一个 7 阶段协议,把你的 AI agent 变成一名外科医生:它进入代码,清除死的,合并重复,修正动画,调优 React 性能,驱逐 `any`,安抚 GPU——然后走出来,没有碰用户看到的一个像素。规则是神圣的:零视觉改动,零行为改动。只清理内部。我会告诉你什么时候需要它、为什么 AI 会弄脏、什么习惯能防止它腐烂,以及一个你交给它、让它一阶段一阶段动刀的主 prompt。

Jul 19, 202614 min
这份指南适合谁?
适合那些已经用 AI 构建了几周甚至几个月,却感觉这个应用再也不像最初那样好改了的人。加一个小功能变得很慢,冒出奇怪的 bug,AI 在自己写的代码里迷了路。这不是你的问题:是代码脏了,而没人来打扫。这份资源就是那次深度清洁——那台把内部收拾得干干净净、却完全不改动外表的手术。你不需要会编程:你只需要知道该让你的 agent 做什么、按什么顺序做。

1. 时机:应用外表能跑,内部却在吱嘎作响

一开始一切都像魔法。你对 AI 说"加一个个人资料页",它就出现了。"再来个导出按钮",它也出现了。你走得很快,非常快。但总有一个时刻——几乎都在第三周到第十周之间——某种东西变了。要一个小功能不再是瞬间完成。AI 变慢了,搞混了,动到了不该动的地方。在你根本没碰过的地方冒出 bug。应用能跑,但改动它变得沉重,就像鞋里进了泥在走路。

那就是那个时刻。没发生什么戏剧性的事:没有任何看得见的东西坏掉。发生的事是看不见的,它叫做技术债。AI 构建得快,而像所有构建得快的人一样,留下了瓦砾:没人再用却还在那里的代码,同一段逻辑被复制到五个文件里,让所有警报都失灵的 any 类型,随随便便搭起来的动画。这些在屏幕上都看不到。而这一切都让未来的每一次改动更加艰难。

这样想象它
外科医生不会给你换一张脸。他进去,修好里面的东西——去掉多余的,缝好,加固薄弱处——然后你带着和之前一模一样的脸,但内部健康地走出来。代码手术正是这样:任何使用你应用的人都不会察觉到一丝改变,但内部变得干净、类型完整、没有瓦砾。如果术后有什么看起来不一样了,那就不是手术:那是手术台上的一次事故。

2. 痛点:它从哪来,以及为什么 AI 会弄脏(哪怕它写得"好")

这里有个重要且诚实的点:AI 并不写烂代码。它写的是能跑的代码。问题在于它优化的是"现在能跑",而不是"三个月后好维护"。而这两件事往相反的方向拉扯。所以哪怕每一小块都没问题,加在一起还是会变脏。以下是它留下的四类瓦砾,以及它为什么会留下它们:

脏东西从哪来(四类瓦砾)
死代码。 你要一个改动,AI 重写了一个新函数……却忘了删掉旧的。它就留在那里,成了孤儿,没人调用。把这个乘以几百次改动,你就有了一整批毫无用处的文件。
重复。 AI 并不总是记得它之前已经写过同样的逻辑,于是又写了一遍。现在同一条规则住在五个地方。等这条规则要改的那天,得改五次——而且总会漏掉一个。
`any` 和松散的类型。 当 AI 不确定某个数据的类型时,它走捷径:标成 any。这样它就关掉了 TypeScript 用来提醒你错误的所有警报。代码能编译……然后在生产环境里爆炸。
粗糙搭起来的动画和特效。 AI 放了动画渐变、模糊、阴影——看起来不错,但搭得糟糕就会让 GPU 出汗,应用在手机和普通笔记本上感觉很卡。
真正的痛点:缓慢的事故,不是天启
这一切明天不会搞垮你的应用。它更阴险:是一场缓慢的侵蚀。每周加东西都稍微更费劲一点,AI 犯错稍微更频繁一点,bug 稍微更多一点。没有一个灾难日;只有慢慢滑向一堆让人不敢碰的代码。手术会在项目变得无法挪动之前刹住这场侵蚀。
如果你不做会怎样
如果你从不打扫,就会走到那一步:AI 自己在你的代码里被淹死。当有那么多重复、那么多死代码时,AI 不知道五个副本里哪个是好的,或者会去动那个孤儿函数而不是活的那个,在修旧 bug 时引入新 bug。脏代码不只拖慢你:它拖慢那个构建它的工具。手术把一块干净的画布还给 AI,让它在上面继续工作。

3. 手术的 7 个阶段(一切的核心)

外科医生不会打开后随便乱翻:他遵循一套流程,按顺序,一步一步来。代码手术也一样。一共七个阶段,而且顺序很重要:先清除死代码(这样才不用去清理你本来要删的代码),然后合并重复,然后加固动画,然后 React 性能,然后类型,然后安抚 GPU,最后出一份健康报告。下面是每一个阶段。

阶段 1 · 清除死代码

第一件事是把所有不再呼吸的东西从手术台上搬走。这是最划算的阶段,因为它为其余所有阶段清理出地盘:去优化一个你打算删掉的函数毫无意义。

阶段 1 猎杀的目标
孤儿文件 —— 没有任何地方 import 的文件。它们留在那里,来自一个从没删掉的旧版本。
没有消费者的 export —— 导出了却没人用的函数或组件。它们"以防万一"被导出,而那个万一从没到来。
未使用的变量、函数和 import —— 声明了又被遗忘。linter 通常会标出来,但 AI 把它们留着,因为"它们不碍事"。它们碍事:它们是噪音。
无法到达的代码分支 —— 永远不可能为真的条件、return 之后的代码、再也没人触发的 if
删除前的保险
删除让人头晕——万一那个确实有用呢?所以这个阶段的第一条规则:开始前先在 GitHub 做一次 commit。如果手术删掉了需要的东西,你一键就能退回去。永远不要没有安全网就动刀。(最后我会给你留 GitHub 那个"撤销按钮"的资源。)

阶段 2 · 审计重复

地盘清理干净后,现在你要找重复的东西。这行的规则很简单:如果某样东西出现三次或以上,它就不再是巧合,而成了一个模式,值得有一个唯一的落脚地。

四类重复及其解药
重复的逻辑 → 抽到一个辅助函数(helper),让两处都调用它。一条规则,一个落脚地。
重复的魔法数字和文本(同一个 48、同一个 URL、同一个颜色)→ 把它们集中到有名字的常量里。改一次,处处都改。
重复三次或以上的 JSX(同一张卡片、带轻微变体的同一个按钮)→ 把它变成一个通过 props 接收差异的子组件。
重复的 `useState` + 它的 handler 这一模式(同一个状态和它的更新函数被复制到多个组件里)→ 把它抽到一个自定义 hook(custom hook)里,把逻辑封装一次。
重构的界限
小心别做过头。不是所有看起来像的东西都是同一样东西。两段今天看起来一样、但会因不同原因而改变的代码不该合并——把它们合起来会造成一种耦合,后来比重复更让人头疼。规则是:合并因同一个原因而改变的东西。如果拿不准,留下两份清晰的副本,好过一个混乱的抽象。

阶段 3 · 遵守动画规则

动画是 AI 最爱即兴发挥、也最容易留下细微毛病的地方——那些不会崩坏、却让应用感觉"廉价"的东西:闪烁、跳动、启动不了的过渡。以下是手术要核对的具体规则(适用于 React 的动画库,比如 Motion / Framer Motion,这是生态里的标准):

要审计的 5 条动画规则
从/向 `transparent` 做动画可能闪烁 → 改用 rgba(0,0,0,0)。当你把 transparent 这个词和一个颜色做插值时,过渡在中途可能出现难看的闪烁;rgba(0,0,0,0) 插值得干净。
没有重复的 `transition` —— 一个动画有两处相互打架的 transition 定义会给出不可预测的结果。计时只能有一个唯一的真相来源。
不要给简写属性 `border` 做动画(那个把粗细、样式和颜色合在一起的简写)→ 给分开的属性做动画,比如 borderColor。简写属性插值不干净。
动画里 `background` → `backgroundColor` —— 给完整的简写 background 做动画是有问题的;只给发生变化的那个具体属性做动画。
在进出的列表里用稳定的 key(AnimatePresence)—— 如果一个动画列表里的元素没有稳定且唯一的 key,退出动画就会崩坏、元素会跳动。key 必须是一个真实的 id,绝不能是数组的索引。

阶段 4 · React 性能

这里手术要找 React 没必要重复做的活儿。每一次不必要的重渲染都是一点点卡顿;加起来,就让应用感觉沉重。要检查四件具体的事:

React 性能的 4 项检查
作为 props 传下去、却没有 `useCallback` 的 handler → 把它们包起来。否则每次渲染都创建一个新函数,逼着子组件重渲染,哪怕什么都没变。
没有 `useMemo` 的昂贵计算(过滤/排序一个大列表、繁重的运算)→ 把它们 memo 化。否则每次渲染都会重新计算,哪怕数据一模一样。
依赖声明错误的 `useEffect` —— 依赖多了会无缘无故触发 effect;依赖少了会让它用到旧数据。两者都是 bug。依赖数组必须精确列出 effect 用到的东西。
没有稳定 `key` 的 `.map` —— 渲染列表时没有唯一 key(或用了索引)会让 React 在重排时搞混、丢失状态。每个元素都需要它自己的 id。
优化不是把所有东西都 memo 一遍
这个阶段新手的错误是"以防万一"把一切都包进 useCallbackuseMemo。不:memo 化本身也有代价(内存、复杂度)。手术只在有真实且可衡量收益的地方 memo 化——一个传给很多子组件的 handler、一个真正昂贵的计算。过度优化是它自己的一种脏。

阶段 5 · TypeScript 卫生

TypeScript 是你代码的警报系统:它在错误抵达用户之前提醒你。但它只有在你让它看到类型时才管用。每一个 any 都是有人关掉的一个警报。这个阶段把它们重新打开。

类型的清理
`any` → 一个真实的类型,或 `unknown` —— any 关掉所有检查。如果你真的不知道类型,用 unknown,它逼你在使用前先做校验(安全),而不是 any,它什么都不逼(危险)。
审查 `as 类型` 的强制转换 —— 对 TypeScript 说"相信我,这是这个类型"是一个可能是谎言的承诺。每一个 as 都是编译器停止检查的一个点。要一个一个审:它是真的,还是一个补丁?
把只用一次的 export 内部化 —— 如果一个类型或函数被导出、却只在它自己的文件里用,它就不该是公开的。把它降为私有:更少的表面积,更少的噪音。
给组件的 props 加类型 —— 每个组件都该声明它接收哪些 props、是什么类型。没类型的 props 就是伪装的 any

阶段 6 · 审计 GPU 崩溃

这是几乎没人知道的阶段,也是在普通设备上最明显的一个。某些视觉特效美得很,但绘制起来贵得惊人:如果你滥用它们,显卡就会饱和,应用就一顿一顿的。手术要找三个经典的罪魁祸首:

GPU 的 3 个沉默杀手
做动画的锥形渐变(`conic-gradient`) → 把它挪到用 @keyframes 的 CSS 动画里。用 JavaScript 在每一帧给锥形渐变做动画贵得离谱;用 keyframes 浏览器会帮它优化。
很多 `repeat: Infinity`(好几个无限循环动画同时跑)→ 把它们合并。十个永恒动画并行跑着会让 GPU 一直醒着、不停烧电池。把它们合起来,或者减到真正需要的那些。
在很多重复的小元素上用 `backdrop-blur` → 如果同一个背景模糊在二十张小卡片上重复,GPU 就重算二十次。对小而重复的元素,一个纯色背景(或半透明的)看起来几乎一样,却只花一小部分代价。
为什么 blur 那么疼
背景模糊(backdrop-blur,那个很流行的磨砂玻璃效果)逼着 GPU 看清元素背后的所有东西并实时把它糊掉。单独一个大的,没事。二十个小的重复着,就像要求显卡每一帧把屏幕糊二十次。就是在那里,你用户的笔记本开始吹风扇。

阶段 7 · 健康报告

每台手术都以一份报告结束。没有报告你就不知道动了什么,也没法确信没有附带损伤。最后一个阶段,是让 agent 用你的语言给你交一份清晰的总结,列出它做的一切:

最终报告应该包含什么
按阶段计数 —— 多少个孤儿文件、合并了多少个重复、删掉了多少个 any、修正了多少个动画,等等。
清除的行数 —— 被搬走的死代码总行数。这是最让人满足的数字:你再也不用维护的代码。
"可上生产"的裁决 —— 明确确认没有改动任何视觉或行为,只改了内部结构。
它没动的东西以及原因 —— 那些看起来像候选、却被故意留下的东西(因不同原因而改变的重复、不值得的 memo 化)。诚实地说明决定不做什么。
整台手术的神圣规则
把它当咒语一样重复,并塞进每一个 prompt 里:零视觉改动。零行为改动。 应用在前后必须看起来和表现得一模一样。如果一个按钮挪了一个像素、如果一个流程变了、如果有什么不再工作——那就不是手术,是一道伤口。在"多清一点"和"保住行为"之间犹豫时,永远是保住行为赢。

4. 习惯:手术是保养,不是一次性的手术

最常见的错误是把手术当成一件一切都乱成一团后才做一次的事。不是的。AI 代码持续变脏,因为每一次构建会话都留下新的瓦砾。手术不是急诊手术:它是你每六个月做一次、好让你永远不用做根管治疗的洗牙。

总是值得动刀的那些时刻
一次大的构建冲刺之后 —— 当 AI 刚刚一口气生成了大量代码,那就是新鲜的瓦砾。趁它上面还没堆更多东西前清掉它。
开始一个重要功能之前 —— 给 AI 一块干净的画布去构建。在脏代码上,它会构建出脏的。
当你注意到 AI 开始犯迷糊 —— 如果工具动了不该动的东西或迷了路,那是噪音太多的信号。手术把清晰还给它。
一次一个文件或模块,而不是整个项目一口气 —— 只做一个模块是安全且可审查的。一次做全部是没有麻醉的开胸手术。分批来。
一句话概括
错的不是 AI 弄脏了代码——那不可避免,构建得快总会留下瓦砾。错的是从不清理它。持续的手术,正是把一个随时间越来越好改的项目,和一个变得不敢碰的项目区分开来的东西。

5. 主 prompt · 交给你的 agent,一阶段一阶段动刀

这里是关键的一块:一个 prompt,把你的代码 agent 变成一名外科医生,按顺序把这 7 个阶段应用到一个文件或模块上——不动任何视觉的东西。填好 [方括号],粘贴进去,让它动刀。动手前一个建议:先在 GitHub 做一次 commit(你的安全网),并把它对准一个模块,而不是整个项目。

主 prompt · 7 阶段代码手术文本
扮演一名精于调试的代码外科医生。你要给这个文件/模块动刀:[文件或文件夹路径,例:src/components/Dashboard/]。技术栈是:[例:React + TypeScript + Motion/Framer Motion + Tailwind]。

神圣且不可违背的规则:零视觉改动、零行为改动。应用在前后必须看起来和表现得一模一样。你只清理和加固内部。在"多清一点"和"保住行为"之间有任何犹豫时,永远是保住行为赢。如果你不确定某样东西是否被使用,就不要删它;把它标出来问我。

按顺序应用这 7 个阶段。不完成上一个就不要进入下一个。在每个阶段结束时,用一行告诉我你发现了什么、改了什么。

阶段 1 —— 死代码:清除孤儿文件(没人 import 的)、没有消费者的 export、未使用的变量/函数/import,以及无法到达的代码分支。删除任何可疑的东西之前,把它列给我并等我确认。

阶段 2 —— 重复:找重复的逻辑(→ 抽到一个 helper)、重复的魔法数字/文本(→ 有名字的常量)、重复三次以上的 JSX(→ 带 props 的子组件),以及重复的 useState+handler 模式(→ custom hook)。不要合并那些只是看起来像、却因不同原因而改变的东西。

阶段 3 —— 动画规则:修正 transparent→rgba(0,0,0,0),清除重复的 transition,不要给简写 border 做动画(用 borderColor),动画里把 background→backgroundColor,并确保带 AnimatePresence 的列表里 key 稳定且唯一(绝不用索引)。

阶段 4 —— React 性能:把作为 props 传下去的 handler 包进 useCallback,用 useMemo memo 化昂贵的计算,修正 useEffect 的依赖数组(不多不少),并给每个 .map 加稳定的 key。不要以防万一去 memo:只在有真实收益的地方做。

阶段 5 —— TypeScript:把每个 any 换成真实类型或换成 unknown;审查每个 'as 类型' 强制转换(它是真的还是一个补丁?);把只在自己文件里用的 export 内部化;并给所有组件的 props 加类型。

阶段 6 —— GPU 崩溃:把做动画的锥形渐变挪到 CSS @keyframes;如果有很多 repeat:Infinity 同时跑就合并它们;并在重复很多次的小元素上把 backdrop-blur 换成纯色/半透明背景。

阶段 7 —— 健康报告:结束时,交给我一份报告,包含:按阶段计数、清除的总行数、明确确认你没改动任何视觉或行为,以及一份你决定不动的东西及原因的清单。

一阶段一阶段地做,给我看每一个阶段的 diff,如果有什么会危及神圣规则,就停下来在继续前问我。
为什么 prompt 一个模块一个模块地做
注意到 prompt 对准的是一个文件或文件夹,而不是整个项目。这是故意的。一次性的大手术是无法审查的——diff 出来有成千上万行,你没法确信没有混进一个行为改动。一个模块一个模块地做,每次手术都小、可审查、可回退。精准的手术,不是拆迁。

6. 验证手术没留下伤口

一台手术不是在你缝合时结束:它是在你确认病人无恙时结束。那条神圣规则(零行为改动)必须去验证,而不只是相信它。有两张自动的安全网能在几秒内替你确认,而且你的 agent 可以跑它们,你完全不用编程。

terminal
# 1) 类型检查:零错误 = 手术没破坏契约
npx tsc --noEmit

# 2) 测试:如果之前通过、之后也照样通过,
#    行为就被保住了
npm test
diff 是你的 X 光片
接受手术之前,在 GitHub Desktop 或用 git diff 看一看它的 diff(改动)。阅读规则:你看到的几乎所有东西都该是红色的行(被删的)或位置移动,而不是新逻辑。如果冒出用户能看到的、被改动的文本字符串,不同的默认值,或者新的条件,那里就有一处可能的伤口——在接受前问问 AI 为什么。

7. 最省事的路径 · AI 在聊天里做什么、你来决定什么

为了不把事情搞复杂:手术的大部分由你的代码 agent 自己在聊天里完成。你的活儿是指挥和批准。分工如下。

AI 替你做的(在聊天里)
扫过模块,检测出死代码、重复、any 和搭得糟的动画——你只需给它主 prompt。
一阶段一阶段地应用修正,给你看每一个的 diff。
tsc 和测试,确认它没破坏任何东西。
写出最终的健康报告,附上计数和它决定不动的东西。
你来决定的(在网页上 / 用按钮)
动手前做那次安全 commit —— 你的撤销按钮。这个由你在动刀前从 GitHub Desktop 或聊天里做。
批准可疑的删除 —— 当 AI 不确定某样东西是否被使用时,它会问你;最终决定是你的。
审查 diff —— 读一读改动,在接受前确认没有行为上的伤口。
决定范围 —— 动哪个模块、按什么顺序。别把"全动了"委托出去:分批来。
在 NeuralOS 里,这套纪律是出厂自带的
这种工作方式——一边构建、一边审计/清理,分成不同的回合,不动已经能用的东西——正是 NeuralOS 内部构建时所用的同一套哲学:每个战线先搭起来,然后在被认可之前经受一遍对抗性审计。你在界面里已经看得见、摸得着的那套愿景——那个替你构建应用的聊天、那些编辑器、那台流程引擎——就靠着这种不让代码腐烂的习惯。产品背后的核心理念,和这份资源是同一个:构建得快和构建得干净,不必是敌人。
C-A-R 协议 · 无 bug 地构建
手术是 C-A-R 的表亲:分回合构建和审计。这份资源给你那套审计方法,那是"边清理边不搞坏"这一纪律的源头。
在 AI 搞坏之前把一切都存进 GitHub
任何手术之前的安全网:那次 commit 让你在某个阶段删掉了需要的东西时,一键就能退回去。
#代码手术#重构#dead code#typescript#性能#进阶
Ready to build?

Start building in
under 3 minutes

Join 4,200+ builders. No credit card. Build your first app with AI in minutes.