[{"data":1,"prerenderedAt":20},["ShallowReactive",2],{"case-why-we-built-devpeek-h5-debug-zh":3,"blog-list-zh":11},{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9,"html":10},"why-we-built-devpeek-h5-debug","我们为什么做 DevPeek（二）：App 里那页 H5，在电脑上也能对着查","登录接口用参数转换啃下来了，活动页 H5 却在 App WebView 里才崩。真机 remote debug 折腾一圈，DOM 和抓包还是两拨窗口——于是把镜像和自研调试面板收进 DevPeek。","2026-07-10",true,"DevPeek 起源系列第二篇：App 内嵌 H5 只在真机出问题、remote debug 与抓包割裂的联调痛点，以及调试 Tab 如何把页面镜像到电脑并用自研面板查 DOM、Console 与 Network。","\u003Ch2>登录修好了，活动页又红了\u003C\u002Fh2>\n\u003Cp>\u003Ca href=\"\u002Fblog\u002Fwhy-we-built-devpeek\u002F\">上一篇\u003C\u002Fa>里，预发登录靠 \u003Cstrong>参数转换\u003C\u002Fstrong> 把密文 Body 收成「改个字、点发送」。测试确认能登了，群里刚松口气，产品又丢过来一条：\u003C\u002Fp>\n\u003Cblockquote>\n\u003Cp>「活动页有个按钮在 Android 上点不动，iOS 正常，帮看下？」\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\u003Cp>不是接口挂了。抓包里 \u003Ccode>GET \u002Fapi\u002Factivity\u002Fconfig\u003C\u002Fcode> 是 \u003Cstrong>200\u003C\u002Fstrong>，Mock 也试过——数据没问题。问题出在 \u003Cstrong>App 里嵌的那页 H5\u003C\u002Fstrong>：同一个 URL，Chrome 里开响应式模式看着正常，真机 WebView 里按钮区域被底部安全区盖住了一截，点不到。\u003C\u002Fp>\n\u003Cp>这类 bug 我们熟：只在 \u003Cstrong>App 内 WebView\u003C\u002Fstrong> 或某款机型上才冒头，桌面浏览器怎么缩放都对不上。\u003C\u002Fp>\n\u003Ch2>真机里硬啃，窗口永远对不齐\u003C\u002Fh2>\n\u003Cp>我的第一反应还是老路子。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Remote debug\u003C\u002Fstrong>：Android 开 WebView 调试、USB 连上，\u003Ccode>chrome:\u002F\u002Finspect\u003C\u002Fcode> 里找页面。有时列表里根本没有——得找客户端同学开 debug 包，或者确认是不是 X5 内核。iOS 更绕：Safari 开发菜单、证书、Web Inspector 一套下来，页面一刷新连接就断。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>vConsole \u002F eruda\u003C\u002Fstrong>：能在页面上看 log，但要改 H5 代码或走代理注入，而且 DOM 树小屏上划来划去，跟设计稿对像素很费眼。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>抓包工具\u003C\u002Fstrong>：Charles 里能看见 H5 发的 XHR，Request\u002FResponse 也解得开——可 \u003Cstrong>Network 是一扇窗，DOM 和 Console 是另一扇\u003C\u002Fstrong>。你在列表里对上了 \u003Ccode>POST \u002Fapi\u002Fxxx\u003C\u002Fcode> 返回 500，还得切回手机上看是哪块 UI 触发的；Console 里报的 \u003Ccode>TypeError\u003C\u002Fcode> 跟抓包列表对时间戳，人肉对齐。\u003C\u002Fp>\n\u003Cp>测试把录屏发群里：「就点这个红色按钮，没反应。」\u003C\u002Fp>\n\u003Cp>我盯着六寸屏上的 H5，另一台显示器开着抓包列表，第三屏试着挂 remote debug——三个窗口，没有一个能同时告诉我 \u003Cstrong>「页面上这个节点」\u003C\u002Fstrong> 和 \u003Cstrong>「它刚发的请求」\u003C\u002Fstrong> 是不是同一条链路。\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs\u002Ffigures\u002Fproxy_requestlist.png\" alt=\"DevPeek 抓包列表：可见 H5 发出的 XHR\">\u003C\u002Fp>\n\u003Cp>\u003Cem>抓包能看见 H5 的请求，但 DOM 和 Console 还在另一头。\u003C\u002Fem>\u003C\u002Fp>\n\u003Ch2>卡住的从来不是「看不见流量」\u003C\u002Fh2>\n\u003Cp>代理和 SSL 那关，第一篇已经啃过了。H5 联调里更磨人的是：\u003Cstrong>流量看得见，页面上下文在另一头。\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>桌面 responsive 换的是 viewport，跑的还是桌面 Chrome——不是 App 里的 WebView。Remote debug 连上时很准，但 USB 连不上、没有 debug 包、X5 内核或 iOS Web Inspector 一刷新就断，排查还是卡在小屏上。\u003C\u002Fp>\n\u003Cp>DevPeek 走的是另一条路：经代理注入调试脚本，在\u003Cstrong>真机页面自己的 JS 环境里\u003C\u002Fstrong>查 DOM、Console；Network 跟抓包列表同源，\u003Ca href=\"\u002Fdocs\u002Fmock\u002F\">Mock\u003C\u002Fa> 也在同一条链路上——改响应、模拟错误码，页面里点按钮触发的请求走的就是你 Mock 过的结果，不必为了验 UI 再切工具。\u003C\u002Fp>\n\u003Cp>我们图的不是「比 DevTools 仿真更全」。注入受 CSP、可注入 HTML 等限制；镜像是 rrweb 回放，不是把 GPU 渲染流推过来；软键盘、原生壳层、JSBridge 也管不到。\u003Cstrong>图的是方便\u003C\u002Fstrong>——大屏对着查、页面和网络（含 Mock）一体——以及 \u003Cstrong>remote debug 连不上时\u003C\u002Fstrong>仍能继续排查。\u003C\u002Fp>\n\u003Ch2>镜像到调试 Tab，用自研面板对着查\u003C\u002Fh2>\n\u003Cp>参数转换解决的是 \u003Cstrong>Body 密文\u003C\u002Fstrong>；H5 这类问题，DevPeek 收进来的是 \u003Cstrong>页面本身\u003C\u002Fstrong>——也就是现在的 \u003Cstrong>移动端网页调试\u003C\u002Fstrong>（主窗口 \u003Cstrong>调试\u003C\u002Fstrong> Tab）。\u003C\u002Fp>\n\u003Cp>前提跟抓包一样：手机走 DevPeek 代理、信任根证书、目标域名在 \u003Ca href=\"\u002Fdocs\u002Fproxy-ssl\u002F\">SSL 解密范围\u003C\u002Fa> 里。详见 \u003Ca href=\"\u002Fdocs\u002Fdebug-replay\u002F\">移动端网页调试\u003C\u002Fa> 文档里的清单；缺任何一项，预览区会一直停在「等待设备连接」。\u003C\u002Fp>\n\u003Cp>条件满足后，流程很直：\u003C\u002Fp>\n\u003Col>\n\u003Cli>切到 \u003Cstrong>调试\u003C\u002Fstrong> Tab，顶部 \u003Cstrong>客户端 Tab\u003C\u002Fstrong> 选中测试那台 Android（与抓包页共用，同一设备只对应一个 Tab）。\u003C\u002Fli>\n\u003Cli>在 App 里 \u003Cstrong>重新打开或刷新\u003C\u002Fstrong> 那页 H5。代理在 HTML 响应里注入调试脚本，页面通过 WebSocket 连回 DevPeek，左侧预览区 \u003Cstrong>实时镜像\u003C\u002Fstrong> 手机上的 DOM 与交互（基于 rrweb 录制回放，不是把整页视频推过来）。\u003C\u002Fli>\n\u003Cli>下方是 \u003Cstrong>自研调试面板\u003C\u002Fstrong>——不是把 Chrome DevTools 嵌进来，而是按「代理镜像」场景自己搭的分区。\u003C\u002Fli>\n\u003C\u002Fol>\n\u003Cp>\u003Cstrong>Elements（DOM）\u003C\u002Fstrong>：右侧树形结构跟左侧镜像同源。可以开选取模式，在镜像画面上点节点，树里高亮对应条目；改样式、改 DOM 的操作 \u003Cstrong>下发到真机\u003C\u002Fstrong>，镜像随 rrweb 事件更新——你在电脑上看，改的是手机里的页面。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Console\u003C\u002Fstrong>：目标页 \u003Ccode>console.log\u003C\u002Fcode>、报错会推到面板里，并按页面会话过滤，避免切 Tab 后旧页日志串线。面板里也能输入表达式，在 \u003Cstrong>实机页面上下文\u003C\u002Fstrong> 里 eval——跟 remote debug 的控制台类似，但不用先搞定 \u003Ccode>chrome:\u002F\u002Finspect\u003C\u002Fcode>。\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Network\u003C\u002Fstrong>：列出镜像页发出的请求，数据源与 \u003Ca href=\"\u002Fdocs\u002Fcapture\u002F\">抓包列表\u003C\u002Fa> \u003Cstrong>一致\u003C\u002Fstrong>——同一条代理转发、同一套 \u003Ca href=\"\u002Fdocs\u002Fparam-transform\u002F\">参数转换\u003C\u002Fa> 与 \u003Ca href=\"\u002Fdocs\u002Fmock\u002F\">Mock\u003C\u002Fa> 规则。接口 Body 仍是密文时，详情里照样能看到解密后的字段；在 Mock 里改了活动接口的返回，Network 里能看到页面收到的是篡改后的响应；要改参重发，切回抓包 Tab 对同一行开「调试 API」即可，不必复制到 Postman。\u003C\u002Fp>\n\u003Cp>三块面板加上方工具栏（后退 \u002F 前进 \u002F 重载、URL 跳转、弱网 Throttling），构成「对着镜像查」的闭环。边界细节见 \u003Ca href=\"\u002Fdocs\u002Fdebug-replay\u002F\">移动端网页调试\u003C\u002Fa> 文档——能注入、能镜像时用；对不上时在真机侧再验一轮。\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs\u002Ffigures\u002Fproxy_resend_popup.png\" alt=\"从抓包列表打开「调试 API」改参重发\">\u003C\u002Fp>\n\u003Cp>\u003Cem>切回抓包 Tab，对同一行开调试 API——改字段、重发，不必离开代理链路。\u003C\u002Fem>\u003C\u002Fp>\n\u003Ch2>和 Map Route、Mock 搭着用\u003C\u002Fh2>\n\u003Cp>H5 联调还常遇到：\u003Cstrong>页面脚本写死了 \u003Ccode>https:\u002F\u002Fapi.example.com\u003C\u002Fcode>，本地服务跑在 \u003Ccode>127.0.0.1:8080\u003C\u002Fcode>；或者后端还没部署，你想先看错误码下 UI 长什么样。\u003C\u002Fstrong>\u003C\u002Fp>\n\u003Cp>改 H5 发版不现实时，\u003Ca href=\"\u002Fdocs\u002Fmap-route\u002F\">Map Route（路由映射）\u003C\u002Fa> 把 Host 指到本机 stub，\u003Ca href=\"\u002Fdocs\u002Fmock\u002F\">Mock\u003C\u002Fa> 直接改响应体或状态码——都在代理链路上，WebView 里 \u003Cstrong>URL 不用改\u003C\u002Fstrong>。Mock 篡改弹窗\u003Cstrong>不受客户端 Tab 或主窗口页签限制\u003C\u002Fstrong>：你在调试 Tab 对着镜像点按钮，命中规则时照样会弹出篡改界面；Network 里看到的与抓包列表是同一数据源。调试 Tab 镜像的仍是 App 里那页；你在镜像里点按钮，验的就是这条链路上的真实效果，不用为了对 DOM 再开 Charles 或 Postman。\u003C\u002Fp>\n\u003Cp>\u003Cimg src=\"\u002Fdocs\u002Ffigures\u002Fmock_tamper_res.png\" alt=\"DevPeek Mock 篡改弹窗：响应阶段改包\">\u003C\u002Fp>\n\u003Cp>\u003Cem>同一条代理链路——镜像里点按钮触发请求，响应阶段在弹窗里改完继续，页面立刻收到篡改结果。\u003C\u002Fem>\u003C\u002Fp>\n\u003Ch2>那页活动按钮\u003C\u002Fh2>\n\u003Cp>回到开头那个按钮：镜像里用 Elements 选取模式点了一下，发现外层 \u003Ccode>div\u003C\u002Fcode> 的 \u003Ccode>padding-bottom\u003C\u002Fcode> 在 Android WebView 里被算短了一截——桌面 responsive 模式没复现，remote debug 那回还没连上。\u003C\u002Fp>\n\u003Cp>Console 里补了一行 \u003Ccode>getComputedStyle\u003C\u002Fcode> 对比，Network 里确认点击后 \u003Cstrong>\u003Ccode>POST \u002Fapi\u002Factivity\u002Fjoin\u003C\u002Fcode> 根本没发出去\u003C\u002Fstrong>——不是接口错，是 hit area 被挡了。改完样式下发到真机，测试在镜像上看着点了一轮，再回 App 里验收，不用我抱着手机蹲工位。\u003C\u002Fp>\n\u003Ch2>下一篇\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>《我们为什么做 DevPeek（三）：不改 H5 域名，把 API 指到本机》\u003C\u002Fstrong>——Map Route 与 Mock 怎么跟抓包、页面调试串成一条联调链，预发环境没部署也能验错误码。\u003C\u002Fp>\n\u003Chr>\n\u003Cp>若你也在 App WebView 里对着小屏硬啃 H5，欢迎 \u003Ca href=\"\u002F\">下载 DevPeek 试用\u003C\u002Fa>，或到 \u003Ca href=\"https:\u002F\u002Fgithub.com\u002FGYPengDev\u002Fdevpeek\u002Fdiscussions\">GitHub Discussions\u003C\u002Fa> 聊聊——上手步骤见 \u003Ca href=\"\u002Fdocs\u002Fdebug-replay\u002F\">移动端网页调试\u003C\u002Fa>，代理与证书见 \u003Ca href=\"\u002Fdocs\u002Fproxy-ssl\u002F\">代理与 SSL 证书\u003C\u002Fa>。\u003C\u002Fp>\n",{"items":12},[13,14],{"slug":4,"title":5,"summary":6,"date":7,"featured":8,"seoDescription":9},{"slug":15,"title":16,"summary":17,"date":18,"featured":8,"seoDescription":19},"why-we-built-devpeek","我们为什么做 DevPeek（一）：HTTPS 解密了，Body 还是天书","版本日前那晚，TLS 早就解开了，改请求里一个字段却还要翻脚本加解密。于是萌生做一个把业务加解密收进代理的工具——DevPeek 从这儿开始。","2026-07-09","DevPeek 起源系列第一篇：联调时请求体加解密的手工折腾，以及为什么先做一款把业务加解密收进代理的工具。",1783662156257]