[{"data":1,"prerenderedAt":83},["ShallowReactive",2],{"case-h5-debug-console-mock-zh":3,"blog-list-zh":13},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11,"html":12},"h5-debug-console-mock","H5 调试实战（二）：Android WebView 白屏排查，从 Console 远程定位到 Mock 验证","活动 H5 在部分 Android 设备中点击按钮后白屏，请求全部 200 却没有页面反馈。通过 DevPeek Console 获取线上 WebView 运行日志，远程 eval 确认 polyfill 覆盖问题，再使用 Mock 验证异常状态下的降级页面。","2026-07-13",true,"H5 调试实战第二篇：排查 Android WebView 白屏问题。通过 Console 远程调试定位 JavaScript polyfill 兼容问题，并结合 Mock 验证接口异常场景下的页面降级逻辑。","h5-debug",2,"\u003Ch2>白屏了\u003C/h2>\n\u003Cp>事情发生在一次活动 H5 压测。\u003C/p>\n\u003Cp>测试在群里发了一段录屏：\u003C/p>\n\u003Cblockquote>\n\u003Cp>「三星 S23，Android 14，微信里面打开活动页，点击『立即参与』之后页面白屏。」\u003C/p>\n\u003C/blockquote>\n\u003Cp>比较奇怪的是，这不是完全打不开。\u003C/p>\n\u003Cp>页面能够正常加载：\u003C/p>\n\u003Cul>\n\u003Cli>首页内容正常展示；\u003C/li>\n\u003Cli>按钮可以点击；\u003C/li>\n\u003Cli>点击后有 loading；\u003C/li>\n\u003C/ul>\n\u003Cp>但是随后页面直接白屏。\u003C/p>\n\u003Cp>iOS 正常，其他 Android 设备也正常。\u003C/p>\n\u003Cp>这种问题第一反应通常会看几个方向：\u003C/p>\n\u003Cul>\n\u003Cli>JavaScript 是否运行异常；\u003C/li>\n\u003Cli>接口返回数据是否导致渲染失败；\u003C/li>\n\u003Cli>Android WebView 是否存在兼容问题。\u003C/li>\n\u003C/ul>\n\u003Cp>先从网络层开始排查。\u003C/p>\n\u003Ch2>抓包正常，但页面还是挂了\u003C/h2>\n\u003Cp>先看接口请求。\u003C/p>\n\u003Cpre>\u003Ccode>POST /api/campaign/join\n\u003C/code>\u003C/pre>\n\u003Cp>返回：\u003C/p>\n\u003Cpre>\u003Ccode>200 OK\n\u003C/code>\u003C/pre>\n\u003Cp>请求参数正常。\u003C/p>\n\u003Cp>响应数据结构也符合预期。\u003C/p>\n\u003Cp>至少可以确定：接口没有直接失败。\u003C/p>\n\u003Cp>但是页面依然白屏。\u003C/p>\n\u003Cp>这类问题比较麻烦：请求成功了，页面也加载了，但某一步执行失败。\u003C/p>\n\u003Cp>如果没有运行时日志，只能靠猜。\u003C/p>\n\u003Ch2>vConsole 和 Remote Debug 都不太适合这个场景\u003C/h2>\n\u003Cp>通常 H5 页面调试，第一个想到的是 vConsole。\u003C/p>\n\u003Cp>但是这个活动页面已经上线，测试环境无法直接重新打包注入 vConsole。\u003C/p>\n\u003Cp>而且问题只发生在特定 Android 设备。\u003C/p>\n\u003Cp>Chrome Remote Debug 也尝试过：\u003C/p>\n\u003Cpre>\u003Ccode>chrome://inspect\n\u003C/code>\u003C/pre>\n\u003Cp>可以连接 WebView。\u003C/p>\n\u003Cp>但是问题发生在点击按钮之后。刷新页面时错误已经不存在。\u003C/p>\n\u003Cp>另外：\u003C/p>\n\u003Cul>\n\u003Cli>WebView 调试开关需要客户端支持；\u003C/li>\n\u003Cli>USB 连接有环境要求；\u003C/li>\n\u003Cli>线上版本不方便反复调整。\u003C/li>\n\u003C/ul>\n\u003Cp>现在的问题是：手机里的微信 WebView 已经出现异常，但我需要看到它真实运行时的状态。\u003C/p>\n\u003Ch2>先拿到线上 WebView 的 Console\u003C/h2>\n\u003Cp>测试机通过代理连接 DevPeek。\u003C/p>\n\u003Cp>完成：\u003C/p>\n\u003Cul>\n\u003Cli>安装 HTTPS 证书；\u003C/li>\n\u003Cli>配置代理；\u003C/li>\n\u003Cli>开启目标域名 SSL 解密。\u003C/li>\n\u003C/ul>\n\u003Cp>完整前置清单见 \u003Ca href=\"/docs/debug-replay/\">移动端网页调试\u003C/a>；若预览区停在「等待设备连接」，先过一遍 \u003Ca href=\"/docs/faq/\">常见问题\u003C/a>。\u003C/p>\n\u003Cp>然后在 DevPeek \u003Cstrong>调试\u003C/strong> Tab 中选择对应设备，测试重新打开活动页面。\u003C/p>\n\u003Cp>控制台马上出现了一条异常：\u003C/p>\n\u003Cpre>\u003Ccode>Uncaught TypeError:\ne.isIntersecting is not a function\n\nat IntersectionObserver polyfill\n(chunk-vendors.js:1847)\n\u003C/code>\u003C/pre>\n\u003Cp>\u003Cimg src=\"/docs/figures/debug_console_eval.png\" alt=\"DevPeek 调试 Console：报错与远程 eval\">\u003C/p>\n\u003Cp>\u003Cem>真机控制台输出实时推送到调试面板。\u003C/em>\u003C/p>\n\u003Cp>问题方向开始明确。\u003C/p>\n\u003Ch2>原因：polyfill 覆盖了 Android 原生实现\u003C/h2>\n\u003Cp>这里涉及 \u003Ccode>IntersectionObserver\u003C/code>。\u003C/p>\n\u003Cp>Android 14 的 WebView 已经支持这个 API。\u003C/p>\n\u003Cp>但是项目里仍然加载了一份旧版 polyfill，而这份 polyfill 又覆盖了浏览器原生实现。\u003C/p>\n\u003Cp>于是页面实际运行的不是 native \u003Ccode>IntersectionObserver\u003C/code>，而是 polyfill 版本。两套实现之间存在兼容差异。\u003C/p>\n\u003Cp>继续通过 Console 远程执行几行代码确认：\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-javascript\">navigator.userAgent.match(/Android\\s([\\d.]+)/)?.[1];\n// &quot;14&quot;  ——确认 Android 版本\n\ntypeof IntersectionObserver;\n// &quot;function&quot;  ——确认 API 存在\n\nIntersectionObserver.toString().includes(&quot;native code&quot;);\n// false  ——确认当前实现不是浏览器原生版本\n\u003C/code>\u003C/pre>\n\u003Cp>定位完成。\u003C/p>\n\u003Ch2>问题定位了，但测试还没结束\u003C/h2>\n\u003Cp>前端开始修复 polyfill。\u003C/p>\n\u003Cp>但是压测窗口还在继续。\u003C/p>\n\u003Cp>测试还需要确认：如果接口返回异常状态，页面的降级逻辑是否正常。\u003C/p>\n\u003Cp>例如：\u003C/p>\n\u003Cul>\n\u003Cli>活动已结束；\u003C/li>\n\u003Cli>用户没有权限；\u003C/li>\n\u003Cli>活动库存不足。\u003C/li>\n\u003C/ul>\n\u003Cp>这些场景不能每次都等后端配合，所以需要模拟接口响应。\u003C/p>\n\u003Ch2>用 Mock 验证异常场景\u003C/h2>\n\u003Cp>在 DevPeek 抓包列表找到 \u003Ccode>POST /api/campaign/join\u003C/code>。\u003C/p>\n\u003Cp>创建 Mock 规则。\u003C/p>\n\u003Cp>\u003Cstrong>匹配条件：\u003C/strong>\u003C/p>\n\u003Cul>\n\u003Cli>URL 包含 \u003Ccode>campaign/join\u003C/code>\u003C/li>\n\u003Cli>Method 为 POST\u003C/li>\n\u003C/ul>\n\u003Cp>\u003Cstrong>修改响应：\u003C/strong>\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;code&quot;: 10086,\n  &quot;message&quot;: &quot;活动已结束&quot;\n}\n\u003C/code>\u003C/pre>\n\u003Cp>保存并启用。\u003C/p>\n\u003Cp>\u003Cimg src=\"/docs/figures/mock_wizard_auto_response.png\" alt=\"DevPeek Mock 规则编辑：匹配条件与响应篡改\">\u003C/p>\n\u003Cp>\u003Cem>Mock 规则保存即生效，不需要重启代理。\u003C/em>\u003C/p>\n\u003Cp>测试重新点击按钮。\u003C/p>\n\u003Cp>这次页面没有白屏，而是正常显示「活动已结束」。\u003C/p>\n\u003Cp>降级逻辑验证通过。\u003C/p>\n\u003Cp>如果继续测试其他错误场景，例如：\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n  &quot;code&quot;: 10010,\n  &quot;message&quot;: &quot;当前活动不可用&quot;\n}\n\u003C/code>\u003C/pre>\n\u003Cp>可以继续修改 Mock 响应，快速验证不同异常状态下的页面表现。\u003C/p>\n\u003Cp>整个过程不需要：\u003C/p>\n\u003Cul>\n\u003Cli>修改后端接口；\u003C/li>\n\u003Cli>等待接口发布；\u003C/li>\n\u003Cli>重新打包 H5。\u003C/li>\n\u003C/ul>\n\u003Cp>Mock 规则是持久化的，关掉 DevPeek 再打开仍然有效。联调结束后记得禁用或删除临时规则，避免影响后续抓包。\u003C/p>\n\u003Ch2>整个排查过程\u003C/h2>\n\u003Cp>这次的问题最终定位链路：\u003C/p>\n\u003Cpre>\u003Ccode>点击按钮\n    ↓\n抓包确认接口正常返回 200\n    ↓\nConsole 获取 WebView 运行时异常\n    ↓\n远程 eval 确认 polyfill 覆盖问题\n    ↓\n修复方案确认\n    ↓\nMock 模拟异常接口\n    ↓\n验证页面降级逻辑\n\u003C/code>\u003C/pre>\n\u003Cp>整个过程中，没有重新打包 H5，也没有要求客户端开启调试模式。\u003C/p>\n\u003Ch2>为什么这次排查比较顺\u003C/h2>\n\u003Cp>以前遇到类似问题，通常需要几个工具配合：\u003C/p>\n\u003Cul>\n\u003Cli>抓包工具确认请求；\u003C/li>\n\u003Cli>vConsole 查看运行日志；\u003C/li>\n\u003Cli>修改接口响应测试异常流程。\u003C/li>\n\u003C/ul>\n\u003Cp>每个工具都能解决一部分问题。\u003C/p>\n\u003Cp>但排查过程中经常会遇到：\u003C/p>\n\u003Cul>\n\u003Cli>刚才那个错误日志在哪里？\u003C/li>\n\u003Cli>这个接口刚才返回了什么？\u003C/li>\n\u003Cli>Mock 修改之后手机有没有重新触发？\u003C/li>\n\u003C/ul>\n\u003Cp>问题信息分散在不同工具里。\u003C/p>\n\u003Cp>这次所有信息都在同一条调试链路中：\u003C/p>\n\u003Cpre>\u003Ccode>Network\n   ↓\nConsole\n   ↓\nMock\n   ↓\n真实设备页面\n\u003C/code>\u003C/pre>\n\u003Cp>对于移动端 H5 调试来说，减少工具切换，本身就是减少排查成本。\u003C/p>\n\u003Ch2>一些实际限制\u003C/h2>\n\u003Cp>当然，Console 和 Mock 也不是万能的。完整边界见 \u003Ca href=\"/docs/debug-replay/\">移动端网页调试\u003C/a> 文档。\u003C/p>\n\u003Cp>\u003Cstrong>1. 页面已经彻底崩溃\u003C/strong>\u003C/p>\n\u003Cp>例如无限循环、栈溢出、主线程阻塞——这种情况下调试脚本可能也无法注入。需要先从资源加载和网络请求方向排查。\u003C/p>\n\u003Cp>\u003Cstrong>2. iframe 页面\u003C/strong>\u003C/p>\n\u003Cp>Console 默认运行在当前页面上下文。如果问题发生在 iframe 内，需要单独打开 iframe 地址调试。\u003C/p>\n\u003Cp>\u003Cstrong>3. Mock 不一定能拦截所有请求\u003C/strong>\u003C/p>\n\u003Cp>Mock 依赖代理链路。Service Worker 缓存、客户端原生网络层拦截、某些特殊 WebView 内核行为可能绕过。需要确认请求确实经过代理。\u003C/p>\n\u003Cp>\u003Cstrong>4. 远程 eval 的执行环境\u003C/strong>\u003C/p>\n\u003Cp>远程执行脚本和页面共享上下文。简单检查没有问题，但不要直接执行大量遍历 IndexedDB 或长时间计算任务，建议使用异步方式。\u003C/p>\n\u003Ch2>下一篇\u003C/h2>\n\u003Cp>\u003Cstrong>《H5 调试实战（三）：待整理》\u003C/strong>——继续记录一些真实移动端 H5 联调案例。\u003C/p>\n\u003Chr>\n\u003Cp>如果你也经常遇到接口正常但是页面异常、Android WebView 兼容问题、线上 H5 无法直接调试，欢迎 \u003Ca href=\"/\">下载 DevPeek 试用\u003C/a>，或到 \u003Ca href=\"https://github.com/GYPengDev/devpeek/discussions\">GitHub Discussions\u003C/a> 聊聊。\u003C/p>\n\u003Ch2>相关文档\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/docs/debug-replay/\">移动端网页调试\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/mock/\">Mock 规则\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/capture/\">抓包界面与请求详情\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/proxy-ssl/\">代理与 SSL 证书\u003C/a>\u003C/li>\n\u003Cli>\u003Ca href=\"/docs/faq/\">常见问题\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Ch2>系列文章\u003C/h2>\n\u003Cul>\n\u003Cli>\u003Ca href=\"/blog/wechat-h5-storage-debug/\">H5 调试实战（一）：微信 H5 localStorage 调试，在电脑上修改真机缓存\u003C/a>\u003C/li>\n\u003C/ul>\n",{"items":14},[15,24,32,38,44,51,57,63,64,70,77],{"slug":16,"title":17,"summary":18,"date":19,"featured":20,"seoDescription":21,"series":22,"seriesOrder":23},"https-ssl-skip-decrypt","开了 SSL 抓包，有些网站反而打不开？把域名加进「跳过 SSL 代理」","系统代理和证书都没问题，一开 SSL 代理个别站却打不开。多半是源站证书和 Host 对不上。把域名加进「跳过 SSL 代理（隧道）」即可，不必关掉整站 SSL 抓包。","2026-09-01",false,"DevPeek 开了 SSL 代理后部分网站打不开？ERR_TLS_CERT_ALTNAME_INVALID 是源站证书与 Host 不匹配，不是 CA 未信任。用 Include / Exclude：把域名加入「跳过 SSL 代理（隧道）」。","api-debug-new-tricks",3,{"slug":25,"title":26,"summary":27,"date":28,"featured":20,"seoDescription":29,"series":30,"seriesOrder":31},"dev-build-log-silent-auto-update","换掉 Electron 后，自动更新也得重做","DevPeek 换成 Tauri 后，更新的不只是一个窗口，而是 Launcher、Core 和 Shell 三个进程。我们把检查和下载挪到后台，等安装包准备好后，再由托盘完成最后一次重启。","2026-08-28","DevPeek 开发实录：桌面端从 Electron 换到 Tauri 后，如何为 Launcher、Core 和 Shell 重做自动更新，并避免更新过程影响系统代理。","dev-build-log",4,{"slug":33,"title":34,"summary":35,"date":36,"featured":20,"seoDescription":37,"series":30,"seriesOrder":23},"dev-build-log-ws-mock-dsl","为什么我们重新设计了 WebSocket Mock DSL，而不是用 YAML、JSON 或 JS","轻量 WebSocket Mock 不该比 HTTP Mock 更重。YAML、JSON、JS 都能做，但写「连上、登录、心跳」太啰嗦。我们自研短 DSL，就是让轻量 Mock 更轻。","2026-08-13","DevPeek 开发实录：为什么 WebSocket Mock 自研 Flow DSL。现成 YAML、JSON、JS 能做重活；轻量顺序剧本用更短的文本来写。",{"slug":39,"title":40,"summary":41,"date":42,"featured":20,"seoDescription":43,"series":30,"seriesOrder":11},"dev-build-log-electron-to-tauri","DevPeek 架构改造：抛弃 Electron，拥抱 Tauri","联调工具不该为「开一个窗口」再拖一整套 Chromium。我们把业务收到 Core，桌面壳换成 Tauri，安装更轻、后台更省，关窗后托盘里也能随时唤回来。","2026-08-08","DevPeek 开发实录：桌面壳从 Electron 迁到 Tauri，业务留在 Core，壳只负责窗口与系统能力，体积与资源占用更友好。",{"slug":45,"title":46,"summary":47,"date":48,"featured":20,"seoDescription":49,"series":30,"seriesOrder":50},"dev-build-log-sqljs-to-better-sqlite3","抓包历史为什么从 sql.js 迁到原生 SQLite","早期 DevPeek 用纯 JavaScript 版 SQLite 存抓包记录，联调一忙就占内存、列表发紧。我们换成系统级原生 SQLite 后，代理可以连续挂一整天，内存也稳。","2026-08-05","DevPeek 开发实录：抓包历史存储从 sql.js 换成原生 SQLite，解决长时间联调内存上涨、列表卡顿，让代理可以挂一整天。",1,{"slug":52,"title":53,"summary":54,"date":55,"featured":20,"seoDescription":56,"series":22,"seriesOrder":11},"mock-map-route-split-api","API 已迁新服务，前端还没发版？用「转发规则」联调","服务拆分后，前端仍请求旧 API，订单接口却已经迁到新服务。使用 DevPeek「转发规则」无需修改前端代码，即可把指定接口转发到新域名；若新服务未完成，还可以用 Mock 先跑通页面。","2026-07-26","微服务联调与 API 域名迁移：用 DevPeek「转发规则」做 API 转发，不改前端即可把旧域名请求指到新服务；服务迁移未完成时可用 Mock 先验页面。附接口联调 Demo。",{"slug":58,"title":59,"summary":60,"date":61,"featured":20,"seoDescription":62,"series":22,"seriesOrder":50},"api-param-encryption-debug","H5 接口参数加密？DevPeek 一键解密调试","联调时接口参数 AES 加密看不到明文？用 DevPeek 参数转换功能，填好密钥和 IV 就能自动解密，还能改参重放。","2026-07-18","用 DevPeek 参数转换功能解密 AES-GCM 加密的 H5 API 请求，支持双向转换、明文编辑、调试重放。",{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"series":10,"seriesOrder":11},{"slug":65,"title":66,"summary":67,"date":68,"featured":8,"seoDescription":69,"series":10,"seriesOrder":50},"wechat-h5-storage-debug","H5 调试实战（一）：微信 H5 localStorage 调试，在电脑上修改真机缓存","微信 H5 换测试号后头像仍显示旧用户，抓包确认接口正常，却定位到 localStorage 遗留旧数据。本文记录一次真实联调过程，以及如何在电脑上查看、修改微信 WebView 的 localStorage、sessionStorage 和 IndexedDB。","2026-07-11","微信 H5 调试实战：通过真实案例定位 localStorage、sessionStorage、IndexedDB 导致的数据缓存问题，对比 vConsole、Remote Debug 等方案，介绍真机 WebView 调试思路。",{"slug":71,"title":72,"summary":73,"date":74,"featured":8,"seoDescription":75,"series":76,"seriesOrder":11},"why-we-built-devpeek-h5-debug","我们为什么做 DevPeek（二）：App 里那页 H5，在电脑上也能对着查","登录接口用参数转换啃下来了，活动页 H5 却在 App WebView 里才崩。真机 remote debug 折腾一圈，DOM 和抓包还是两拨窗口——于是把镜像和自研调试面板收进 DevPeek。","2026-07-10","DevPeek 起源系列第二篇：App 内嵌 H5 只在真机出问题、remote debug 与抓包割裂的联调痛点，以及调试 Tab 如何把页面镜像到电脑并用自研面板查 DOM、Console 与 Network。","origin",{"slug":78,"title":79,"summary":80,"date":81,"featured":8,"seoDescription":82,"series":76,"seriesOrder":50},"why-we-built-devpeek","我们为什么做 DevPeek（一）：HTTPS 解密了，Body 还是天书","版本日前那晚，TLS 早就解开了，改请求里一个字段却还要翻脚本加解密。于是萌生做一个把业务加解密收进代理的工具——DevPeek 从这儿开始。","2026-07-09","DevPeek 起源系列第一篇：联调时请求体加解密的手工折腾，以及为什么先做一款把业务加解密收进代理的工具。",1788746290042]