AI多Agent协作系统实战(三十六):代码里明明写了,编译完怎么没了?

头像加载失败,排查半天:源码里明明白白写着"域名拼接"的逻辑,编译出来的产物里------这行代码消失了。不是bug,不是网络,是编译器悄悄把我的代码"优化"掉了。

现象:头像一片空白

移动端App更新后,登录进去------右上角头像空白。

正常来说,头像应该显示用户上传的照片。查网络、查接口、查权限......都没问题:

  • 接口正常返回头像路径:/uploads/avatar/1_1785567950217.png
  • 图片文件存在(直接访问200)
  • 但页面上就是不显示

打开浏览器控制台,看到一个404:

ruby 复制代码
GET http://192.168.3.150:8080/mobile/uploads/avatar/1_1785567950217.png → 404

注意看路径------多了一个/mobile 正确的路径应该是 http://192.168.3.150:8080/uploads/avatar/...(根路径),但它被解析成了 /mobile/uploads/...(移动端目录下)。

排查:源码里明明有拼接逻辑

页面在 /mobile/ 目录下,头像用的是相对路径 /uploads/avatar/...------相对路径在子目录页面下会被错误解析。解决办法是在路径前拼上域名(origin)。

打开源码,发现这个逻辑明明写了

javascript 复制代码
// 源码(login/index.vue)
const avatarUrl = computed(() => {
  if (!userInfo.avatar) return ''
  if (userInfo.avatar.startsWith('http')) return userInfo.avatar
  return window.location.origin + userInfo.avatar  // ← 拼接域名,明明在这!
})

window.location.origin------把域名拼到相对路径前面,得到完整的 http://192.168.3.150:8080/uploads/avatar/xxx.png逻辑是对的,代码是有的。

那为什么页面还是404?

根因:编译器把代码"优化"没了

打开编译后的产物(Vite打包生成的JS文件),搜索这段逻辑:

javascript 复制代码
// 产物(编译后的 chunk)
N = computed(() => {
  return userInfo.avatar || ''   // ← 拼接逻辑呢?没了!
})

window.location.origin + 这一段,在编译产物里消失了。 源码里明明有,编译完只剩 userInfo.avatar 直接返回。

这是构建工具(Vite 5.12)的产物生成缺陷------某个构建环节把这段拼接逻辑丢掉了(类似的问题还有:组件事件绑定丢失、输入框属性错乱、文字组件渲染异常------同一批构建事故)。

源码是完整的,产物是残缺的。 我们一直在查"代码有没有写错"------其实代码没错,是编译过程把对的代码弄丢了

修复:改产物 + 修源码,双保险

第一步,直接修复当前产物(生产环境跑的是产物,等不了重新构建):

javascript 复制代码
// 产物修复:把拼接逻辑补回去
N = computed(() => {
  const a = userInfo.avatar || ''
  return a && !/^https?:/.test(a) ? window.location.origin + a : a
})

第二步,源码也要加固 ------但更重要的是:以后每次构建完,必须验证产物和源码一致(关键逻辑在产物里 grep 验证)。

三条教训

第一,源码 ≠ 运行代码。 用户跑的是编译产物,不是你的源码。"我代码里写了"不是结论------"产物里也有"才是。 排查问题永远从产物入手,不要从源码入手------源码是愿望,产物是现实。

第二,构建工具也会出错。 我们默认"编译器是可靠的"------但遇到"源码有逻辑、产物没有"的灵异现象时,要敢于怀疑构建链本身。构建产物是"编译+优化+打包"的产物,任何一环都可能吃掉代码(尤其是tree-shaking、minify这类"优化"环节------优化器觉得"没用"的代码会被删掉,即使它有用)。

第三,修复要落在"运行的东西"上。 当时如果只改源码不修产物------构建一次又可能丢一次。先让线上恢复正常(改产物),再让源码正确(改源码),最后让流程防复发(构建后自动验证)。 三层都要做,只做一层是假修复。

结尾

头像修好后,我们给构建流程加了一步:构建完成后,自动在产物里验证关键逻辑 (比如grep location.origin,找不到就报警)。

从那以后,这种"编译吃掉代码"的事再没发生过------因为构建产物不再是黑盒,每次发布都被验证过

源码是愿望,产物是现实。别问"我是不是写错了"------去问"产物里到底有没有"。

你的代码没丢,只是编译器替你做主了。

(完)


本文是"多Agent派发系统"系列第36篇。第35篇讲AI幻觉(把见过当做过),这一篇讲构建产物丢失(把写过的当没有)------都是"现实与期望不符"的灵异事件,一个出在AI,一个出在编译器。

相关推荐
柠檬味拥抱1 小时前
代码看腻了,我让 Seed Evolving 把整个仓库搓成了一座能走进去的 3D 城市
后端
mit6.8242 小时前
archived
后端·python·flask
用户298698530142 小时前
效率工具分享:3 款免费 Markdown 转 Word 在线转换器
人工智能·后端
程序员天天困2 小时前
Spring Boot i18n 国际化实战:从资源文件到多语言接口完整指南
spring boot·后端·编程语言
睡觉时不困4422 小时前
8.conda 与 uv 环境管理完全指南:从概念到实战避坑
后端
是小李呀2 小时前
Spring Boot 配置加载机制解析:Docker 部署中 `spring.profiles.active` 与 `spring.config.location` 的本质区别
后端
步行cgn2 小时前
MyBatis 多参数绑定错误:Parameter 'name' not found 详解与解决方案
后端
步行cgn2 小时前
MyBatis 对单个简单类型参数的默认处理详解
后端
吃饱了得干活2 小时前
Java并发安全:看这一篇就懂了!
java·后端·面试