先看出事的那一刻
2026 年 8 月 2 日,站长请 AI 审查一次大重构。打开一个章节页的截图,示意图里的标签背景和车辆全变成了黑色色块,线条也不见了;再打开术语页,本该是图解的地方,只剩一堆没有样式的文字。而这次重构的状态报告里写着:"Mintlify 视觉检查:通过"。
配图用到的颜色都写成了变量,比如 var(--teal)。搜一遍整个项目才发现,这些变量几乎都已经没有定义了。
这节课要回答的是:删掉一段"看起来没人用"的代码,为什么会弄坏另一个地方?重构之前,怎样找出那些看不见的依赖?
装备几个词
为什么要懂
AI 替你做了
AI 重构起来又快又彻底:按新的设计规范删掉旧变量、换掉整套样式表,一次改几千行,构建照样通过。
留给你的
删之前问一句“还有谁在用它”。样式、变量、共享组件之间的依赖,构建时不会报错,只会在页面上悄悄坏掉。
不懂的代价
删完之后一切看起来正常,测试全绿,报告写着“通过”,直到有人打开那个页面,才发现图全黑了。
分几步消失的变量
没有哪一步是"删掉了配图的颜色"。回头看,变量是这样一点点消失的:
| 时间 | 发生了什么 | 当时看起来 |
|---|---|---|
| 7 月 30 日 | 新的设计规范要求"全站颜色只使用五个根令牌",另一个 AI 按规范删掉了其中 7 个变量 | 规范执行到位 |
| 8 月 2 日 | 一个新皮肤的样式表把这 7 个变量重新定义了一遍,但只在它自己的容器里生效 | 在那个皮肤里,图又正常了 |
| 8 月 2 日 | 最终采用的是另一个版本,它挂在那个容器外面,看不到这些定义 | 没人注意到 |
| 8 月 2 日 | 旧样式表和那个局部样式表先后被删掉 | 构建通过,报告写"视觉检查 通过" |
每一步单看都说得通:按规范删、为新皮肤补、删掉不用的旧文件。坏在这一连串里,没有任何一步问过:"图形组件还在用这些变量吗?"
为什么偏偏是黑色
CSS 里引用一个不存在的变量,又没有写兜底值,这条样式就被当作无效,属性退回默认值。填充色的默认值会一路继承下来,最终落到黑色;描边的默认值是"不画",于是线条消失了。
这也解释了为什么构建和测试都没发现:对 CSS 来说,这不是错误,只是"这个值无效,用默认的"。当时项目的 7 项测试全部通过,因为没有一项测试会去看图是什么颜色。
找出看不见的依赖
这类依赖有个共同点:它们不走 import,编辑器和构建工具都帮不上忙。只能靠三个习惯:
- 删之前先搜。变量名、类名、组件名,在整个项目里还有谁在引用。
- 看作用域。定义在某个容器里的变量,只在那个容器里生效:搜得到定义,不等于用它的地方看得到它。
- 改完拿产物比。这个网站把几个组件抽成共用时,逐字节比对了构建出来的 HTML:95 个页面里 94 个完全一样,唯一不同的那个,恰好修掉了一个旧 bug(
/e2e的"主线"栏目从来没有高亮过)。
深潜兜底值的两面+
修复时,一部分变量加上了兜底值,比如 var(--teal, #00b48a):变量找不到时,至少还有一个颜色,不会再出现黑块。
但兜底值也会掩盖问题。下次变量又丢了,页面不会变黑,只会悄悄换成兜底的颜色,和设计规范慢慢对不上,而且更难被发现。
所以修复里更重要的是另一条:设计文档里写明了"图形组件依赖哪些变量",并规定删样式前先对照这份清单。只是这条规矩只写在文档里,没有任何自动检查:它能不能被遵守,取决于下一个动手的人或 AI 会不会去读。
找茬
下面是这条依赖链上的几段真实代码和文档(节选)。配图组件用 CSS 变量取颜色,没有兜底值。找出让这份依赖“看不见”、或者让它断掉却没人发现的地方。
这段 JSX / Markdown / CSS 里埋了 6 处问题。点击你觉得有问题的行,至少找出 3 处再揭晓。
·第 2 行中危
文件头只写了一个输入,漏了真正的依赖
文件头说这个组件的输入只有章节号,可它还依赖 8 个 CSS 变量。只看文件头的人(或 AI),不会知道删掉那些变量会影响这里。
该问的话:这个组件依赖哪些外部的东西?文件头注释里都写了吗?
·第 3 行中危
用变量,却不给兜底值
变量一旦没有定义,填充色就退回默认的黑色,描边直接消失。至少要在删除变量之前,确认这些引用都有着落。
该问的话:这些变量要是没有定义,图会变成什么样?
·第 6 行中危
写着“无输入”,其实依赖一串变量
"纯静态图"听起来和外界毫无关系,可它同样要读 8 个颜色变量。这句注释让依赖彻底隐身了。
该问的话:这个“纯静态”的组件,真的不依赖任何外部定义吗?
·第 9 行中危
按规范删变量,没问还有谁在用
规范本身没有错:统一颜色,是好事。问题在于执行时直接删掉了 7 个变量,没有先搜一遍,是谁在用它们。
该问的话:按规范删掉这些变量之前,有没有搜过它们在哪里被引用?
·第 12 行中危
定义只在这一个容器里生效
变量补回来了,但只写在这个皮肤的容器里。挂在容器外面的另一个版本看不到它们;而在项目里搜索,却能搜到定义,看起来一切正常。
该问的话:这些定义的作用域覆盖了所有用到它们的地方吗?
·第 16 行高危
删掉样式的同一个提交,写着视觉检查通过
把最后一个样式表删掉的那个提交,同时在状态报告里写下了"视觉检查 通过"。这份报告没有人真的去看过页面。
该问的话:这个“通过”是怎么检查出来的?看了哪些页面?
查看代码与答案(6 处问题)
1 // IntersectionScene.jsx(路口场景图,节选)
2 * input: chapter(1-8)
3 const TEAL = "var(--teal)"; const RED = "var(--red)"; const AMBER = "var(--amber)";
4
5 // MechanismFigures.jsx(机制图,节选)
6 * input: 无(纯静态图)
7
8 // docs/DESIGN.md(7 月 30 日,节选)
9 全站颜色只使用以下五个根令牌。组件不得另起 `--red`、`--teal`、`--accent` 或品牌色体系。
10
11 /* wired.css(8 月 2 日一个新皮肤的样式表,节选) */
12 .wired-experience {
13 --teal: #000000;
14
15 # STATUS.md(删掉最后一个样式表的同一个提交)
16 | Mintlify 视觉检查 | 通过 |- 第 2 行 · 中危 · 文件头只写了一个输入,漏了真正的依赖:文件头说这个组件的输入只有章节号,可它还依赖 8 个 CSS 变量。只看文件头的人(或 AI),不会知道删掉那些变量会影响这里。 该问的话:这个组件依赖哪些外部的东西?文件头注释里都写了吗?
- 第 3 行 · 中危 · 用变量,却不给兜底值:变量一旦没有定义,填充色就退回默认的黑色,描边直接消失。至少要在删除变量之前,确认这些引用都有着落。 该问的话:这些变量要是没有定义,图会变成什么样?
- 第 6 行 · 中危 · 写着“无输入”,其实依赖一串变量:"纯静态图"听起来和外界毫无关系,可它同样要读 8 个颜色变量。这句注释让依赖彻底隐身了。 该问的话:这个“纯静态”的组件,真的不依赖任何外部定义吗?
- 第 9 行 · 中危 · 按规范删变量,没问还有谁在用:规范本身没有错:统一颜色,是好事。问题在于执行时直接删掉了 7 个变量,没有先搜一遍,是谁在用它们。 该问的话:按规范删掉这些变量之前,有没有搜过它们在哪里被引用?
- 第 12 行 · 中危 · 定义只在这一个容器里生效:变量补回来了,但只写在这个皮肤的容器里。挂在容器外面的另一个版本看不到它们;而在项目里搜索,却能搜到定义,看起来一切正常。 该问的话:这些定义的作用域覆盖了所有用到它们的地方吗?
- 第 16 行 · 高危 · 删掉样式的同一个提交,写着视觉检查通过:把最后一个样式表删掉的那个提交,同时在状态报告里写下了"视觉检查 通过"。这份报告没有人真的去看过页面。 该问的话:这个“通过”是怎么检查出来的?看了哪些页面?
快测
1. 你删掉了一个 CSS 变量的定义,构建通过、测试全绿。可能出什么问题?
对了。这正是它难发现的原因:没有报错,只有页面变了。填充色的默认值一路继承成黑色,描边的默认值是“不画”。
你可能是这么想的:定义没了,引用它的那条样式就被当作无效,属性退回默认值,不会沿用旧值。
你可能是这么想的:CSS 里引用一个不存在的变量,不算错误。控制台里没有任何提示,构建照样通过,页面只是悄悄变样。
CSS 的依赖断了,不会报错,只会悄悄变样。
查看选项与答案
- A. 引用它的地方退回默认值,比如颜色变黑、线条消失(正确)——这正是它难发现的原因:没有报错,只有页面变了。填充色的默认值一路继承成黑色,描边的默认值是“不画”。
- B. 引用它的地方仍会沿用删除之前的值,页面外观保持不变——定义没了,引用它的那条样式就被当作无效,属性退回默认值,不会沿用旧值。
- C. 浏览器控制台会报出未定义的变量,一打开页面就能发现——CSS 里引用一个不存在的变量,不算错误。控制台里没有任何提示,构建照样通过,页面只是悄悄变样。
CSS 的依赖断了,不会报错,只会悄悄变样。
2. 在项目里搜索,找到了这个变量的定义。能说明用它的地方都没问题吗?
你可能是这么想的:拼写一致,只说明名字对得上,不说明看得到。定义写在某个容器里,就只有那个容器里面的元素读得到它。
对了。搜得到定义,不等于用它的地方看得到它。这次补回来的定义只写在一个皮肤的容器里,挂在容器外面的版本读不到。
你可能是这么想的:加载了样式表还不够。定义写在某个容器里,容器外面的引用照样是无效的。
查依赖时,既要看有没有定义,也要看定义在哪里生效。
查看选项与答案
- A. 能,只要引用处和定义处的变量名拼写完全一致——拼写一致,只说明名字对得上,不说明看得到。定义写在某个容器里,就只有那个容器里面的元素读得到它。
- B. 不一定,还要看定义生效的范围有没有盖住每一处引用(正确)——搜得到定义,不等于用它的地方看得到它。这次补回来的定义只写在一个皮肤的容器里,挂在容器外面的版本读不到。
- C. 能,只要定义所在的样式表已经被加载到页面里——加载了样式表还不够。定义写在某个容器里,容器外面的引用照样是无效的。
查依赖时,既要看有没有定义,也要看定义在哪里生效。
3. 重构之后,怎样最快确认页面外观没变?
你可能是这么想的:这次的测试也全绿:当时的 7 项测试都通过,因为没有一项会去看图是什么颜色。
对了。这个网站抽组件时,就是逐字节比对了构建出来的 HTML:95 个页面里 94 个完全一样,唯一不同的那个,恰好修掉了一个旧 bug。
你可能是这么想的:隐形依赖出在没被改动的地方:引用变量的组件不在这次的改动里,复查改动看不到它。
重构的承诺是外面看不出变化:用前后对比来证明。
查看选项与答案
- A. 跑一遍项目里的全部测试,全绿就可以放心合并——这次的测试也全绿:当时的 7 项测试都通过,因为没有一项会去看图是什么颜色。
- B. 重构前后各构建一次,再比对构建产物或页面截图(正确)——这个网站抽组件时,就是逐字节比对了构建出来的 HTML:95 个页面里 94 个完全一样,唯一不同的那个,恰好修掉了一个旧 bug。
- C. 让 AI 把这次的改动逐行复查一遍,没发现问题就行——隐形依赖出在没被改动的地方:引用变量的组件不在这次的改动里,复查改动看不到它。
重构的承诺是外面看不出变化:用前后对比来证明。
判断时刻
新的设计规范要求全站只用五个颜色变量。AI 准备删掉其余的变量定义,它给了三种做法。
你会选哪一个?
考察:信任构建
最快,也最危险:CSS 里引用不存在的变量不会报错,构建永远通过。这次就是这样删掉的,配图全变成了黑块。
考察:先找依赖
多花一些时间,但每个用到旧变量的地方都有了着落。搜的时候要注意作用域:搜得到定义,不等于用它的地方看得到它。
考察:兜底的两面
再删变量时不会出现黑块了。代价是变量丢了也没人发现,颜色悄悄变成兜底值,和设计规范慢慢对不上。兜底能防事故,也能掩盖事故。
删东西之前,先问还有谁在用它。构建和测试只能告诉你代码能不能跑,告诉不了你页面还是不是原来的样子。
三个选项各自的代价
- A. 按规范直接删掉,构建通过就行——考察信任构建:最快,也最危险:CSS 里引用不存在的变量不会报错,构建永远通过。这次就是这样删掉的,配图全变成了黑块。
- B. 删之前先搜遍整个项目,把还在用的地方改成新的变量——考察先找依赖:多花一些时间,但每个用到旧变量的地方都有了着落。搜的时候要注意作用域:搜得到定义,不等于用它的地方看得到它。
- C. 给所有引用加上兜底值,然后放心删——考察兜底的两面:再删变量时不会出现黑块了。代价是变量丢了也没人发现,颜色悄悄变成兜底值,和设计规范慢慢对不上。兜底能防事故,也能掩盖事故。
删东西之前,先问还有谁在用它。构建和测试只能告诉你代码能不能跑,告诉不了你页面还是不是原来的样子。
带走
下次让 AI 做这件事时,问它
- 这次要删或要改的变量、类名、组件,在整个项目里还有谁在引用?请全部列出来。
- 这些定义的作用域是什么?用到它们的地方都在作用域里面吗?
- 有哪些看不见的依赖(样式变量、全局类名、文件路径)?文件头注释里写清楚了吗?
- 改完之后,用构建产物或截图比对证明外观没变。
自己验证
- 全项目搜索要删的名字,比如
grep -rn "var(--teal" src,确认每一处引用都有着落。 - 改动前后各构建一次,逐个文件比对构建产物,看哪些页面变了、为什么变。
- 打开用到这些样式的页面,在开发者工具里看计算后的颜色,是不是预期的值。
删东西之前先问一句:还有谁在用它?
