阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > “这个 Bug 到底是前端还是后端的锅?”——甩锅的艺术

“这个 Bug 到底是前端还是后端的锅?”——甩锅的艺术

作者:陈川 阅读数:47392人阅读 分类: 前端综合

谁动了我的接口?

开发团队里最经典的场景莫过于:页面显示异常,测试同学甩出一张截图,产品经理眉头紧锁,而前后端开发者已经默默打开了各自的代码编辑器。这时候空气突然安静,所有人都在等一个答案——这次该谁背锅?

基础排查三板斧

先别急着甩锅,这几个基础操作能快速定位问题方向:

  1. 浏览器开发者工具:按下F12直奔Network标签,看看接口返回的数据是否符合预期。如果响应数据本身就是错的,那后端大概率要接锅。
// 前端期望的用户数据结构
const expected = {
  id: 123,
  name: '张三',
  avatar: 'https://example.com/1.jpg'
}

// 实际返回数据(缺失avatar字段)
const actual = {
  id: 123,
  name: '张三'
}
  1. 接口文档对照:拿出Swagger或YAPI文档逐字段比对,字段类型不匹配、缺失必填字段等问题一目了然。

  2. CURL命令验证:直接绕过前端用命令行测试接口:

curl -X GET 'https://api.example.com/user/123'

典型的前端背锅场景

当出现这些情况时,锅大概率在前端同学手里:

数据渲染问题

// 未做空值处理导致页面崩溃
function UserProfile({ user }) {
  return <div>{user.detail.address.street}</div> 
  // 当address为null时就GG
}

参数格式错误

// 后端需要的是字符串数字,前端传了Number类型
fetch('/api/delete', {
  method: 'POST',
  body: JSON.stringify({ id: 123 }) // 应该传"123"
})

缓存惹的祸

// 用随机参数绕过浏览器缓存
fetch(`/api/data?t=${Date.now()}`)

经典的后端问题现场

这些情况可以理直气壮找后端同学:

接口500错误: Network里看到鲜红的500状态码,特别是带着长长的异常堆栈信息时。

数据逻辑错误

// 前端传了pageSize=10,但接口返回了15条数据
fetch('/api/list?page=1&pageSize=10')

跨域问题: 浏览器控制台出现CORS错误时,多半是后端没配Access-Control-Allow-Origin。

灰度发布引发的罗生门

有时候问题出在发布流程本身:

  • 前端发布了新版本但后端接口还未就绪
  • 后端接口更新但前端还在用旧版缓存
  • 某个服务节点未成功部署新代码

这时候需要查:

# 查看前端版本
document.querySelector('meta[name="version"]').content

# 确认接口版本
curl -I https://api.example.com | grep X-Api-Version

高级侦查技巧

埋点日志分析

// 在关键操作处添加日志
console.log('API请求参数:', params)
console.log('DOM状态:', document.getElementById('app').innerHTML)

Mock数据验证

// 用本地JSON文件绕过真实接口
beforeEach(() => {
  jest.mock('./api', () => ({
    getUser: () => Promise.resolve(require('./mock/user.json'))
  }))
})

时间旅行调试: 使用Redux DevTools重放状态变更,查看哪个环节开始出现异常。

当问题变得复杂时

有些情况需要前后端联调:

  1. 数据不一致:前端显示"剩余1件",实际下单时提示已售罄
  2. 权限问题:管理员能看到按钮但点击报403错误
  3. 文件上传异常:前端显示上传成功但后端没收到文件

这时候需要:

  • 对比前端发送的FormData和后端接收到的数据
  • 检查请求头Content-Type是否正确
  • 查看Nginx等中间件的请求日志

自动化防御方案

与其事后甩锅,不如提前预防:

前端防御性编程

interface User {
  id: string
  name: string
  avatar?: string
}

function renderAvatar(user: User) {
  return user.avatar 
    ? <img src={user.avatar} />
    : <DefaultAvatar />
}

后端契约测试

// Spring Boot的测试示例
@WebMvcTest
public class UserApiTest {
  @Test
  void shouldReturnUserWithAvatar() throws Exception {
    mockMvc.perform(get("/user/1"))
      .andExpect(jsonPath("$.avatar").exists());
  }
}

监控报警体系

  • 前端异常监控(Sentry)
  • 接口成功率报警(Prometheus)
  • 日志聚合分析(ELK)

那些年我们甩过的锅

真实案例集锦:

  1. 缓存雪崩:前端说接口慢,后端说查询快,最后发现是Redis集群挂了
  2. 时区之谜:前端显示日期比实际少一天,结果是后端没转UTC时间
  3. 编码问题:用户输入emoji后显示乱码,前端说传的UTF-8,后端说收到的却是GBK
  4. CDN背锅:样式文件没更新,其实是CDN缓存策略配置错误
  5. Nginx搞事:接口返回403,结果是Nginx配置的client_max_body_size太小

终极和解方案

当问题实在难以定位时,可以尝试:

  1. 联调会议:前后端+测试一起过流程
  2. 代码交换:前端写临时后端接口,后端写临时前端页面
  3. 流量回放:用Charles等工具录制线上请求进行回放测试
  4. 全链路日志:通过TraceID追踪一个请求的完整生命周期
// 在全链路中加入追踪ID
const traceId = Math.random().toString(36).substr(2)
fetch('/api/data', {
  headers: { 'X-Trace-Id': traceId }
})

从甩锅到背锅的修养

优秀开发者的进阶之路:

  1. 先假设是自己的问题,查完再找别人
  2. 提交Bug时附带完整上下文(环境、操作步骤、日志)
  3. 能用代码解决的不用嘴解决
  4. 重要问题写事后分析报告
  5. 请杯奶茶能解决90%的甩锅冲突

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌