Skip to content

前端网络调试完全指南

🎯 DevTools + Charles + Wireshark 三大神器,线上问题排查实战


1. Chrome DevTools Network

1.1 面板功能总览

┌─────────────────────────────────────────────────────────────────────────┐
│                    Network 面板功能                                      │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  ┌─ 工具栏 ─────────────────────────────────────────────────────────┐  │
│  │  🔴 录制  🚫 清除  📥 导出HAR  🔍 过滤  ☐ Preserve log          │  │
│  │  ☐ Disable cache  🌐 Throttling  ☐ No throttling                 │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│                                                                         │
│  ┌─ 过滤器 ─────────────────────────────────────────────────────────┐  │
│  │  All | Fetch/XHR | JS | CSS | Img | Media | Font | Doc | WS | ... │  │
│  │  Filter: domain:api.example.com status-code:500 larger-than:100k │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│                                                                         │
│  ┌─ 请求列表 ───────────────────────────────────────────────────────┐  │
│  │  Name       Status  Type    Initiator   Size    Time    Waterfall │  │
│  │  ─────────────────────────────────────────────────────────────── │  │
│  │  api/users  200     fetch   main.js:42  1.2kB   120ms   ▓▓▓░░░░░ │  │
│  │  main.js    200     script  index.html  45kB    80ms    ▓▓░░░░░░ │  │
│  │  style.css  (cache) style   index.html  12kB    10ms    ▓░░░░░░░ │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│                                                                         │
│  ┌─ 请求详情 (点击单个请求) ────────────────────────────────────────┐  │
│  │  Headers | Preview | Response | Initiator | Timing | Cookies     │  │
│  └──────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

1.2 高级过滤语法

bash
# 按域名
domain:api.example.com

# 按状态码
status-code:500
status-code:4xx

# 按大小
larger-than:100k
larger-than:1M

# 按类型
is:running                # 进行中的请求
method:POST              # POST 请求
mime-type:application/json

# 排除
-status-code:200         # 非 200 的请求
-domain:cdn.example.com  # 排除 CDN 请求

# 组合
domain:api.example.com status-code:5xx

1.3 Timing 详解

┌─────────────────────────────────────────────────────────────────────────┐
│                      请求 Timing 详解                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  时间线:                                                                │
│  ────────────────────────────────────────────────────────────────────  │
│  │ Queueing │ Stalled │ DNS │ TCP │ TLS │ Request │ Waiting │ Content│  │
│  ────────────────────────────────────────────────────────────────────  │
│                                                                         │
│  各阶段说明:                                                            │
│  ───────────                                                            │
│  Queueing    - 排队等待 (浏览器连接数限制)                              │
│  Stalled     - 停滞 (等待代理/缓存检查)                                 │
│  DNS Lookup  - DNS 解析                                                 │
│  Initial Connection - TCP 三次握手                                      │
│  SSL/TLS     - TLS 握手                                                 │
│  Request Sent - 发送请求                                                │
│  Waiting (TTFB) - 等待首字节 (服务器处理时间)                           │
│  Content Download - 下载响应体                                          │
│                                                                         │
│  常见问题诊断:                                                          │
│  ──────────────                                                         │
│  TTFB 过长     → 服务器处理慢 / 网络延迟                                │
│  Queueing 长   → 请求太多,被浏览器排队                                 │
│  DNS 慢        → DNS 解析问题,考虑 dns-prefetch                        │
│  SSL 慢        → 考虑 TLS 1.3 / 会话复用                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

1.4 Waterfall 瀑布图分析

┌─────────────────────────────────────────────────────────────────────────┐
│                      Waterfall 颜色含义                                  │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  颜色说明:                                                              │
│  ─────────                                                              │
│  ░░░  白色/浅色  - Queueing / Stalled                                  │
│  ▒▒▒  浅绿色    - DNS Lookup                                           │
│  ▓▓▓  橙色      - Initial Connection (TCP)                             │
│  ███  紫色      - SSL/TLS                                              │
│  ███  绿色      - Request Sent + Waiting (TTFB)                        │
│  ███  蓝色      - Content Download                                     │
│                                                                         │
│  优化目标:                                                              │
│  ─────────                                                              │
│  理想: 蓝色占比大 (下载快)                                              │
│  问题: 绿色占比大 (TTFB 慢,服务器问题)                                 │
│  问题: 白色占比大 (请求排队,减少请求数)                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

1.5 实用技巧

javascript
// 1. Copy as fetch - 复制请求为 fetch 代码
// 右键请求 → Copy → Copy as fetch

// 2. Replay XHR - 重放请求
// 右键请求 → Replay XHR

// 3. Block request URL - 阻止特定请求
// 右键请求 → Block request URL
// 测试降级场景

// 4. Override response - 覆盖响应
// Sources → Overrides → Select folder
// 可以修改响应内容调试

// 5. 命令行快速过滤
// Ctrl + Shift + P → 输入 "Network"

2. Charles 抓包

2.1 基础配置

┌─────────────────────────────────────────────────────────────────────────┐
│                      Charles 配置步骤                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. 安装 Charles                                                        │
│     https://www.charlesproxy.com/                                       │
│                                                                         │
│  2. 配置 HTTPS 抓包                                                     │
│     Proxy → SSL Proxying Settings → Add                                │
│     Host: * (或具体域名)                                                │
│     Port: 443                                                           │
│                                                                         │
│  3. 安装根证书                                                          │
│     Help → SSL Proxying → Install Charles Root Certificate             │
│     macOS: 钥匙串 → 系统 → 双击证书 → 信任 → 始终信任                   │
│                                                                         │
│  4. 配置浏览器代理                                                      │
│     Charles 默认端口: 8888                                              │
│     或安装 SwitchyOmega 扩展                                           │
│                                                                         │
│  5. 移动端配置                                                          │
│     Help → Local IP Address → 记录 IP                                  │
│     手机 WiFi → 代理 → 手动 → IP:8888                                  │
│     Safari 访问 chls.pro/ssl 安装证书                                  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

2.2 常用功能

┌─────────────────────────────────────────────────────────────────────────┐
│                      Charles 常用功能                                    │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  1. Throttle (限速)                                                     │
│     ─────────────                                                       │
│     Proxy → Throttle Settings                                          │
│     模拟 3G/慢速网络,测试加载性能                                      │
│                                                                         │
│  2. Map Remote (远程映射)                                               │
│     ───────────────────                                                 │
│     Tools → Map Remote                                                 │
│     将线上请求映射到本地服务器                                          │
│     例: https://api.prod.com → http://localhost:3000                   │
│                                                                         │
│  3. Map Local (本地映射)                                                │
│     ────────────────────                                                │
│     Tools → Map Local                                                  │
│     将请求映射到本地文件                                                │
│     例: /api/users → /Users/me/mock/users.json                         │
│                                                                         │
│  4. Rewrite (重写)                                                      │
│     ──────────────                                                      │
│     Tools → Rewrite                                                    │
│     修改请求/响应的 Header、Body、URL                                  │
│                                                                         │
│  5. Breakpoints (断点)                                                  │
│     ─────────────────                                                   │
│     Proxy → Breakpoint Settings                                        │
│     拦截请求/响应,手动修改后再发送                                     │
│                                                                         │
│  6. Repeat (重复请求)                                                   │
│     ─────────────────                                                   │
│     右键请求 → Repeat / Repeat Advanced                                │
│     压测或重现问题                                                      │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

2.3 Mock 数据

json
// Map Local 示例
// Charles → Tools → Map Local → Add

// Map From:
// Host: api.example.com
// Path: /api/users

// Map To:
// Local Path: /Users/me/mock/users.json

// users.json 内容:
{
    "code": 0,
    "data": {
        "list": [
            { "id": 1, "name": "Mock User 1" },
            { "id": 2, "name": "Mock User 2" }
        ],
        "total": 2
    },
    "message": "success"
}

2.4 Rewrite 规则

// 修改响应 Header
Location: Response
Type: Add Header
Match: *
Replace:
  Name: Access-Control-Allow-Origin
  Value: *

// 修改响应 Body
Location: Response
Type: Body
Match: "error": true
Replace: "error": false

// 修改请求 URL
Location: URL
Type: Path
Match: /api/v1/
Replace: /api/v2/

3. 移动端调试

3.1 iOS Safari 调试

┌─────────────────────────────────────────────────────────────────────────┐
│                    iOS Safari 远程调试                                   │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  准备工作:                                                              │
│  ─────────                                                              │
│  1. iPhone: 设置 → Safari → 高级 → 网页检查器 → 开启                   │
│  2. Mac: Safari → 偏好设置 → 高级 → 显示开发菜单                       │
│                                                                         │
│  调试步骤:                                                              │
│  ─────────                                                              │
│  1. USB 连接 iPhone 到 Mac                                             │
│  2. iPhone 用 Safari 打开目标网页                                      │
│  3. Mac Safari → 开发 → [设备名] → [网页]                              │
│  4. 打开 Web Inspector,与桌面版功能相同                               │
│                                                                         │
│  注意:                                                                  │
│  ──────                                                                 │
│  - 需要 macOS + Safari                                                 │
│  - 适用于调试 Safari、WebView                                          │
│  - 不适用于第三方浏览器 (Chrome iOS 等)                                │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3.2 Android Chrome 调试

┌─────────────────────────────────────────────────────────────────────────┐
│                   Android Chrome 远程调试                                │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  准备工作:                                                              │
│  ─────────                                                              │
│  1. Android: 设置 → 开发者选项 → USB 调试 → 开启                       │
│  2. Chrome 版本 ≥ 32                                                   │
│                                                                         │
│  调试步骤:                                                              │
│  ─────────                                                              │
│  1. USB 连接 Android 到电脑                                            │
│  2. Android 用 Chrome 打开目标网页                                     │
│  3. 电脑 Chrome 访问 chrome://inspect                                  │
│  4. 找到设备和网页,点击 "inspect"                                     │
│  5. 打开 DevTools,可以看到手机屏幕镜像                                │
│                                                                         │
│  WebView 调试:                                                          │
│  ─────────────                                                          │
│  APP 需要在代码中开启:                                                  │
│  WebView.setWebContentsDebuggingEnabled(true);                         │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

3.3 vConsole / Eruda

html
<!-- vConsole - 移动端调试面板 -->
<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>
    // 仅在开发/测试环境启用
    if (location.hostname !== 'prod.example.com') {
        new VConsole();
    }
</script>

<!-- Eruda - 功能更丰富 -->
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>
    eruda.init();
</script>
javascript
// 条件加载 (推荐)
function loadDebugTool() {
    const script = document.createElement('script');
    script.src = 'https://unpkg.com/vconsole@latest/dist/vconsole.min.js';
    script.onload = () => new VConsole();
    document.head.appendChild(script);
}

// URL 参数触发
if (location.search.includes('debug=1')) {
    loadDebugTool();
}

// 手势触发 (5 次点击)
let clickCount = 0;
document.addEventListener('click', () => {
    clickCount++;
    if (clickCount >= 5) {
        loadDebugTool();
        clickCount = 0;
    }
    setTimeout(() => clickCount = 0, 3000);
});

4. 线上问题排查

4.1 常见问题清单

┌─────────────────────────────────────────────────────────────────────────┐
│                     线上网络问题排查清单                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  □ 请求不发出                                                           │
│    ├── CORS 预检失败 (看 Console 和 Network)                           │
│    ├── 代码逻辑问题 (断点调试)                                          │
│    ├── URL 拼接错误                                                     │
│    └── 请求被拦截器阻止                                                 │
│                                                                         │
│  □ 请求超时                                                             │
│    ├── 网络不稳定 (测试其他请求)                                        │
│    ├── 服务端处理慢 (看 TTFB)                                          │
│    ├── DNS 解析慢 (看 Timing)                                          │
│    └── 防火墙/代理拦截                                                  │
│                                                                         │
│  □ 返回 4xx                                                             │
│    ├── 401: Token 过期/无效                                            │
│    ├── 403: 权限不足                                                    │
│    ├── 404: URL 路径错误                                               │
│    └── 422: 参数格式错误                                               │
│                                                                         │
│  □ 返回 5xx                                                             │
│    ├── 500: 服务器内部错误 (联系后端)                                  │
│    ├── 502: 网关错误 (Nginx/负载均衡问题)                              │
│    ├── 503: 服务不可用 (服务宕机)                                      │
│    └── 504: 网关超时 (后端处理超时)                                    │
│                                                                         │
│  □ 数据异常                                                             │
│    ├── 检查请求参数是否正确                                            │
│    ├── 检查响应数据格式                                                │
│    ├── 检查是否有缓存问题                                              │
│    └── 检查是否有编码问题 (UTF-8)                                      │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

4.2 CORS 问题排查

┌─────────────────────────────────────────────────────────────────────────┐
│                      CORS 问题排查                                       │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│  症状:                                                                  │
│  ──────                                                                 │
│  Console: "Access to fetch at 'xxx' from origin 'xxx' has been         │
│           blocked by CORS policy"                                       │
│                                                                         │
│  排查步骤:                                                              │
│  ─────────                                                              │
│  1. Network 面板找到请求                                                │
│  2. 检查是否有 OPTIONS 预检请求                                         │
│  3. 检查预检请求的响应头:                                               │
│     - Access-Control-Allow-Origin                                      │
│     - Access-Control-Allow-Methods                                     │
│     - Access-Control-Allow-Headers                                     │
│                                                                         │
│  常见原因:                                                              │
│  ─────────                                                              │
│  1. 服务端未配置 CORS 头                                                │
│  2. Allow-Origin 是 * 但使用了 credentials                             │
│  3. 自定义 Header 未在 Allow-Headers 中                                │
│  4. 请求方法未在 Allow-Methods 中                                      │
│                                                                         │
│  临时绕过 (仅开发):                                                     │
│  ─────────────────                                                      │
│  1. 使用开发代理 (vite proxy)                                          │
│  2. 浏览器禁用安全检查 (不推荐)                                         │
│     Chrome: --disable-web-security                                     │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

4.3 调试代码注入

javascript
// 线上注入调试代码
// 在 Console 中执行

// 1. 拦截所有 fetch 请求
const originalFetch = window.fetch;
window.fetch = async (...args) => {
    console.log('[Fetch]', args[0], args[1]);
    const start = Date.now();
    try {
        const response = await originalFetch(...args);
        console.log('[Fetch Response]', args[0], response.status, `${Date.now() - start}ms`);
        return response;
    } catch (error) {
        console.error('[Fetch Error]', args[0], error);
        throw error;
    }
};

// 2. 拦截所有 XHR 请求
const originalOpen = XMLHttpRequest.prototype.open;
const originalSend = XMLHttpRequest.prototype.send;

XMLHttpRequest.prototype.open = function(method, url) {
    this._method = method;
    this._url = url;
    return originalOpen.apply(this, arguments);
};

XMLHttpRequest.prototype.send = function(body) {
    console.log('[XHR]', this._method, this._url, body);
    this.addEventListener('load', () => {
        console.log('[XHR Response]', this._url, this.status);
    });
    return originalSend.apply(this, arguments);
};

// 3. 监控性能
const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
        if (entry.entryType === 'resource') {
            console.log('[Resource]', entry.name, entry.duration.toFixed(2) + 'ms');
        }
    }
});
observer.observe({ entryTypes: ['resource'] });

5. 性能分析

5.1 Performance API

javascript
// 获取所有资源加载时间
const resources = performance.getEntriesByType('resource');
resources.forEach((entry) => {
    console.log({
        name: entry.name,
        type: entry.initiatorType,
        duration: entry.duration.toFixed(2) + 'ms',
        size: entry.transferSize,
        // 各阶段时间
        dns: (entry.domainLookupEnd - entry.domainLookupStart).toFixed(2),
        tcp: (entry.connectEnd - entry.connectStart).toFixed(2),
        ttfb: (entry.responseStart - entry.requestStart).toFixed(2),
        download: (entry.responseEnd - entry.responseStart).toFixed(2),
    });
});

// 获取导航时间
const nav = performance.getEntriesByType('navigation')[0];
console.log({
    // 关键指标
    domContentLoaded: nav.domContentLoadedEventEnd.toFixed(2) + 'ms',
    load: nav.loadEventEnd.toFixed(2) + 'ms',
    // 各阶段
    redirect: (nav.redirectEnd - nav.redirectStart).toFixed(2),
    dns: (nav.domainLookupEnd - nav.domainLookupStart).toFixed(2),
    tcp: (nav.connectEnd - nav.connectStart).toFixed(2),
    request: (nav.responseStart - nav.requestStart).toFixed(2),
    response: (nav.responseEnd - nav.responseStart).toFixed(2),
    domParsing: (nav.domInteractive - nav.responseEnd).toFixed(2),
});

// 监控慢请求
const observer = new PerformanceObserver((list) => {
    list.getEntries().forEach((entry) => {
        if (entry.duration > 3000) { // 超过 3 秒
            console.warn('[Slow Resource]', entry.name, entry.duration);
            // 上报监控系统
        }
    });
});
observer.observe({ entryTypes: ['resource'] });

5.2 Lighthouse

bash
# CLI 运行
npx lighthouse https://example.com --view

# Chrome DevTools
# → Lighthouse 面板 → Generate report

# 关注指标
# - Performance: 性能评分
# - FCP: First Contentful Paint
# - LCP: Largest Contentful Paint
# - TBT: Total Blocking Time
# - CLS: Cumulative Layout Shift

6. 面试高频问题

Q1: 如何分析请求慢的原因?

  1. 打开 Network 面板,找到慢请求
  2. 查看 Timing 选项卡
  3. 分析各阶段耗时:
    • DNS 慢 → dns-prefetch
    • TCP/TLS 慢 → HTTP/2、预连接
    • TTFB 慢 → 服务端优化
    • Download 慢 → 压缩、CDN

Q2: 如何调试线上问题?

  1. 复现问题,记录环境信息
  2. 打开 DevTools Network,开启 Preserve log
  3. 分析失败请求的状态码和响应
  4. 检查 Console 报错
  5. 使用 Charles 抓包详细分析
  6. 必要时注入调试代码

Q3: CORS 预检请求什么时候触发?

触发条件(满足任一):

  • HTTP 方法不是 GET/HEAD/POST
  • Content-Type 不是 application/x-www-form-urlencoded、multipart/form-data、text/plain
  • 包含自定义 Header
  • 使用了 ReadableStream

Q4: 如何调试移动端页面?

  1. iOS: Safari 远程调试(需 Mac)
  2. Android: chrome://inspect
  3. 通用: vConsole / Eruda
  4. 抓包: Charles + 手机代理

Q5: 如何分析首屏加载性能?

  1. Performance API 获取关键时间点
  2. Lighthouse 生成性能报告
  3. Network 瀑布图分析阻塞资源
  4. 关注 LCP、FCP、TTFB 指标

前端面试知识库