
小程序体验版调试这件事我一开始也觉得“不至于专门搞个工具”。微信开发者工具里Console、Network、Storage都摆在那真机预览也能看个大概为什么还要引入PageSpy直到我遇到“开发者工具里一切正常体验版一点开就报‘获取登录后的微信用户失败’而且用户手机离我八百公里”这种场景才意识到体验版运行环境跟开发版完全是两码事。PageSpy刚好能把小程序端运行时的Console日志、网络请求、缓存数据同步到电脑浏览器里等于给体验版装了一个远程DevTools。这篇文章就把我接入PageSpy调试小程序体验版的完整过程、踩坑点和排查思路整理出来给同样被真机问题折磨的前端同学一个可复现的参考。1. 小程序体验版调试为什么非得上PageSpy1.1 体验版不是“能扫码打开”就够了小程序开发到中后期最常见的协作方式就是开发者工具里本地跑一遍功能OK然后点“上传”在微信公众平台把某个开发版本“选为体验版”把体验版二维码发给测试同学。问题来了——你作为开发者手上并没有一个真正的“体验版调试通道”。微信开发者工具确实有“预览”和“真机调试”但这两个入口生成的是临时调试二维码跟真正分发出去的“体验版”并不是同一个运行载体。体验版运行在测试同学手机里由微信客户端加载背后代码包可能是你三天前上传的基础库版本跟本地也可能有差异。这些差异很容易让一些偶现问题只出现在体验版里本地怎么跑都复现不了。更麻烦的是出问题后能拿到的信息非常有限。测试同学说“页面白屏了”你只能看到一张截图。让他打开右上角胶囊菜单里的“调试”开关vConsole确实能浮出来但那个面板在手机屏幕上又小又遮挡操作微信版本不同、浮窗能力也不一样日志一多很难翻。而且vConsole是本地日志你没法远程实时看测试同学描述操作路径又往往漏掉关键一步。这个局面下项目里最缺的其实是一个能远程观察运行现场的工具PageSpy就是往这个方向补位的。1.2 PageSpy能解决什么问题一个远程版DevToolsPageSpy是一个开源的调试工具核心思路是把被调试端H5、小程序、React Native等的运行时信息收集起来通过WebSocket传给服务端开发者在电脑浏览器打开管理面板就能查看和分析。它覆盖的能力大致包括能力能看什么对应小程序体验版的常见痛点Consoleconsole.log / warn / error包括未捕获异常用户说“报错了”你能直接看到报错堆栈Network页面发出的请求URL、参数、返回结果、耗时判断接口到底有没有被调用、返回了什么Storage本地缓存、Storage、Token等关键数据快速判断是不是登录态过期、缓存了脏数据Page信息当前页面路径、入参、系统信息复现“从哪个页面进入触发的bug”这类场景系统/环境信息小程序基础库版本、平台等排除基础库差异导致的显示异常这里想强调一点PageSpy不是拿来替代微信开发者工具的。本地开发阶段开发者工具的调试体验已经很完整它的价值在于开发者工具够不着的地方——包上传之后、运行在别人手机里的那个小程序实例。尤其是体验版它既有真实代码包、又能分发给多个成员测试如果PageSpy能把体验版的运行日志实时同步回来大多数“真机必现、本地不现”的问题就变成了一场远程观看式排查。当然PageSpy引入后数据会先经过自己部署的调试服务端所以要控制好使用范围别把所有用户、所有版本的线上包都挂进去。我个人习惯是只对体验版或灰度包开调试能力正式包默认关闭后面第5部分会细说。2. 前期的两个准备服务端部署与小程序SDK接入2.1 部署PageSpy服务端拿到可访问的socket地址PageSpy的服务端是一个独立服务自己部署完全可行也可以用官方提供的Docker镜像直接跑。我习惯用Docker启动命令大致是这个形态docker run -d \ --name pagespy-server \ -p 6752:6752 \ [PageSpy官方仓库提供的服务端镜像名]:latest端口6752是PageSpy默认的服务端口启动后可以先用电脑浏览器访问http://服务器IP:6752验证服务是否正常。正常的话应该能看到一个Web管理界面或者接口响应页面说明服务已经起来了。这里有个容易被忽略的点小程序端SDK连接服务端用的是WebSocket协议如果你的服务端只部署在内网、没有公网可访问地址那测试同学的小程序在4G网络下根本连不上你的调试服务。早期我犯过这个错服务跑在办公室电脑的localhost上自己手机连WiFi能连上测试同学一出门就完全失联。所以部署时要考虑清楚PageSpy服务端需要能被“被调试手机”访问到。对小程序体验版来说最省事的方式是部署到一台有公网地址的服务器上并且配置好HTTPS/WSS证书。如果没有现成服务器也可以用内网穿透工具临时暴露一个地址但一定确保连接稳定、权限可控别图省事把调试服务裸奔在公网上。2.2 小程序接入SDK的正确姿势环境开关和初始化参数接入PageSpy需要在小程序工程里安装对应的小程序SDK。具体包名不同版本会有出入以PageSpy官方文档为准但初始化的写法基本一致形式类似这样import PageSpy from huolala-tech/page-spy-mp; PageSpy.init({ server: wss://your-pagespy-server.example.com:6752, project: mall-mini-app });这里有几个关键点第一个是server地址要写对。小程序端要求能通过WebSocket连接服务端地址里协议一般用wss://不要在正式测试里用没有证书的ws://裸连微信小程序在非开发环境下对明文WebSocket限制很严。端口如果域名走默认443可以省略否则要显式写出来。第二个是初始化位置。我建议在App的入口文件顶部、App()之前完成初始化尽量早这样后续页面执行逻辑时PageSpy已经在收集日志了。不要在多个页面里重复初始化它是全局的只需要做一次。第三点、也是最重要的一点一定要加环境开关不要在任何环境都无条件启动PageSpy。我是这样处理的// config/index.js 里维护一份环境配置 const config { // 体验版和灰度包打开调试正式版关闭 enablePageSpy: [trial, gray].includes(process.env.NODE_ENV) }; // app.js 入口 if (config.enablePageSpy) { PageSpy.init({ server: wss://your-pagespy-server.example.com:6752, }); }你可以用微信小程序的自定义编译条件、或者通过读取版本号来控制开关。这个开关既是性能考虑也是信息安全考虑——体验版面向的是内部测试成员实时同步日志存储数据不会影响真实用户正式版如果也开着调试上报等于把所有线上用户前端的token、请求数据都转发到你自己的服务器上一旦服务端被攻击或者面包权限漏配后果很严重。2.3 别漏了微信公众平台的socket合法域名这部分是PageSpy接入里最容易翻车的地方。微信小程序有一个安全机制在非开发环境下网络请求和WebSocket连接只能访问在微信公众平台配置过的合法域名。开发者工具本地调试时可以在“详情-本地设置”里关闭域名校验但体验版、正式版一定会校验。PageSpy走的是WebSocket长连接所以需要在微信公众平台配置 socket 合法域名而不是request合法域名。操作路径大致是登录微信公众平台进入小程序后台找到“开发管理-开发设置-服务器域名”在“socket合法域名”里填上你部署PageSpy服务端的域名。注意必须填域名不能带协议头比如your-pagespy-server.example.com这样。配置完成后不是立刻全局生效小程序会有一个缓存周期。如果你想尽快验证可以在微信开发者工具里重新编译并让测试同学把微信小程序从最近使用列表中删除再重新打开确保拉到最新的域名配置。这里我还想提醒一个运维细节socket合法域名要求域名能通过WSS连接所以服务器上的TLS证书必须有效并且证书域名跟填写的域名一致。我之前遇到过用IP地址或者自签名证书调试的情况本地开发者工具把域名校验关掉没事传到体验版后被微信一校验就连接失败面板里什么都看不到。所以如果要让PageSpy在体验版稳定工作域名、证书、端口这三件套一个都不能含糊。3. 实操全流程把体验版接到PageSpy并定位真机问题3.1 从上传代码到扫码打开体验版二维码从哪里找把PageSpy接好之后就到了体验版的常规操作。整套链路可以拆成五步在微信开发者工具中确认右下角版本号点击“上传”按钮把当前代码上传为开发版本。上传时最好填一个可读性强的版本号比如1.4.0-debug方便在后台区分。登录微信公众平台进入“管理-版本管理”能看到刚上传的开发版本记录。在开发版本右侧点击“选为体验版”或者如果已有体验版会提示是否替换。替换完成后体验版卡片上会显示一个“体验版二维码”这就是测试同学扫码打开的入口。如果测试同学不在体验成员名单里扫码会提示无权限。这时候需要在小程序后台“成员管理-体验成员”里添加他的微信号添加后他就有权限打开体验版了。这里回答一个高频问题微信小程序体验版有链接吗严格意义上没有公开的“点击链接直达”方式常见做法是让测试同学用微信扫体验版二维码或者在小程序后台把体验版二维码图片发到群里。团队成员第一次扫过之后微信里“最近使用的小程序”也会留下记录后面再打开会方便一些。体验版打开后PageSpy面板里应该能发现一个新的连接。如果你在电脑浏览器已经打开了PageSpy管理端会看到一个小程序端实例上线点进去就能看到这台手机小程序里的Console、Network和Storage信息了。3.2 实战场景体验版“获取登录后的微信用户失败”排查把原理说完我用一个真实场景展示PageSpy排查体验版问题的思路。这个场景很有代表性测试同学打开体验版小程序首页需要登录结果弹窗提示“获取登录后的微信用户失败:wx1cb4398e1413dce7”。看到这种报错第一反应是“登录流程挂了”。但问题在哪里接口没通签名校验失败还是微信登录code换session失败如果没有PageSpy只能让测试同学把报错截图发过来然后猜。有PageSpy之后我一般是按下面顺序看第一步看PageSpy的Console面板。登录失败时通常会有异常日志或者未捕获错误报错信息里经常带出是哪个接口、哪个环节出了问题。console.error如果没打日志就继续下一步看网络面板。第二步打开Network面板找到登录相关的请求。PageSpy网络面板能看到这个请求实际发出的URL、请求参数、响应结果。我那次排查发现请求确实发出去了后端也返回了但返回内容里缺少code字段。对比正常版本后发现是前后端对登录接口的返回结构约定不一致导致的。第三步看Storage面板里的登录态。如果请求本身没报错但业务一直认为自己没登录那很可能本地缓存里有脏数据。PageSpy能直接看到Storage里的key和value比如是否存了残缺的token、旧的unionId之类的字段清理后再重新触发登录问题定位就快了。这个小程序报错里还经常涉及到“签名”相关的逻辑。很多团队会在登录接口里加签名校验防止接口被模拟调用。问题往往不是签名算法错了而是体验版用的AppID跟后端配置的AppSecret不一致签名结果对不上后端就拒绝返回用户信息。这种错误在PageSpy的Network面板里很难一眼看出来但配合Console里打印的开发环境标识和后端错误码基本就能锁定方向。3.3 PageSpy面板怎么看信息对应什么问题PageSpy接入之后如果只会看Console那就只用了它十分之一的能力。我把自己常用面板和排查思路总结成一张速查表现象优先看哪个面板定位思路进入页面白屏Console Page信息看页面路径和参数再找是否有JS异常接口偶现失败Network看请求耗时和返回状态码对比偶现规律登录状态异常Storage检查token、用户信息缓存是否过期或被写脏分享/跳转后参数丢了Page信息看当前页面实际接收的query参数对不对版本更新后行为异常系统/环境信息确认基础库版本怀疑缓存旧代码导致注意PageSpy的小程序端不会像开发工具那样直接“注入”一个可视调试框它更多是后台静默采集。你需要在电脑上开着PageSpy管理界面手机上操作小程序操作引发的问题事件实时出现在面板里。搭配起来就是手机点一点电脑上看着日志滚动问题出现的一瞬间就能截获现场。我还有一个实用技巧在关键业务代码里多打一些上下文日志比如进入某个页面时把场景值、页面参数、用户ID放到一条console.info里。PageSpy能按日志级别和内容筛选后台看起来会非常直观远比你只打印一个debugger或者error好用。4. 常见问题排查速查能救命的几条经验4.1 服务端连接不上先查这四步接入PageSpy后最常遇到的状况是手机小程序已经打开PageSpy管理界面却没有出现设备。我每次遇到这种问题都按下面的顺序排查基本能覆盖90%的原因确认socket合法域名配置了没体验版里微信会强制校验域名如果没配置或配置错了小程序连接WebSocket会直接失败。检查后台域名是否填成了request域名PageSpy需要是socket域名。确认服务端能不能被手机访问把PageSpy服务端地址放到手机浏览器里访问一下如果打不开说明端口没放通或者服务绑定地址不对。确认WSS证书是否有效看PageSpy服务端启动日志和手机端Console有没有TLS相关的报错证书过期或域名不匹配会导致连接被微信拦截。确认初始化开关状态检查当前体验版的代码里PageSpy初始化逻辑是否真的执行了别代码上传错了版本。这一步做完还没有设备列表我才会去怀疑SDK版本和服务端版本不兼容的问题。这类问题往往出现在团队刚接入的时候客户端SDK和服务端镜像都随手拉的最新版结果两边大版本不一致导致协议对不上。建议客户端和服务端都锁定一个经测试过的版本统一升级不要一个追新一个停留老版本。4.2 关于体验版二维码和微信公众平台的几个高频疑问实际项目里大家问得最多的还真不是PageSpy本身而是体验版基础操作。这里集中整理几个高频问题“开发版、体验版、正式版到底啥区别”简单理解开发版是开发者工具“上传”之前的本地运行版本体验版是上传到微信后台、可以分发给体验成员的版本正式版是发版后所有用户都能访问的版本。PageSpy调试主要配合体验版用因为体验版的权限范围相对可控。“体验版二维码在哪”上传代码后登录小程序后台在“版本管理”里把对应开发版本设为体验版然后看体验版卡片上的二维码即可直接用手机微信扫码就能打开。“为什么测试同事扫了体验版二维码没反应或提示无权访问”很多情况是这位同事没有被添加到体验成员列表。请在后台成员管理里添加对方微信号确认添加成功后重新扫一次。“体验版能直接更新PageSpy服务端地址吗”不能只改前端代码需要重新上传一个新开发版本并替换体验版。所以PageSpy服务端地址如果变了记得重新构建和上传体验版不要指望线上动态改配置。“开发者工具里关掉域名校验就能在体验版生效吗”不能。体验版不受开发者工具本地设置影响开发者工具的“关闭域名校验”只对本地运行起作用。这也是为什么PageSpy需要配置真实可用的wss域名。4.3 哪些情况PageSpy也帮不上忙PageSpy不是万能的我列一下它覆盖半径之外的问题免得大家接入后期待过高。第一小程序原生层面的崩溃比如WebView崩溃、内存暴涨导致的闪退PageSpy能看到的有限。它收集的是JS运行时信息原生层crash不一定能落到Console里。第二如果问题出在微信客户端缓存了旧版本代码PageSpy上报的日志其实也来自旧代码会有一段时间的“信息滞后期”。这种情况需要先从PageSpy的系统信息面板确认当前小程序版本判断是不是缓存问题。第三PageSpy能看到网络请求结果但不能替代服务端日志。接口返回的数据到底在服务端是怎么组装的还是得回后端看日志。页面上看到的只是最终返回体。所以我的经验是PageSpy负责把“前端现场”快速暴露出来但定位跨端问题的时候还是要结合后端日志、网关日志一起看。PageSpy的价值是显著缩小排查范围而不是让其他工具都退役。5. PageSpy体验版调试的几条避坑心得5.1 发布前一定要做开关与剔除接PageSpy容易忘关PageSpy上线也有可能发生。我们后来内部规定PageSpy的初始化开关默认关闭只有显式设置成体验版或者灰度环境时才允许启动。上线前还要在CI脚本或发布检查清单里加一项“确认产物里没有PageSpy核心代码”防止把调试SDK带进正式包。为什么这么在意一方面是启动性能PageSpy初始化要建立WebSocket连接、做日志队列缓存多少有点开销另一方面是安全问题PageSpy面板能看到用户的本地缓存和请求数据如果一个线上用户也触发了PageSpy上报或者调试服务端被无关人员访问用户隐私数据就会暴露在调试平台上。这种安全隐患在真实项目里不是危言耸听早做开关早省心。5.2 强烈建议给日志加上前后缀和编号PageSpy面板能把日志展示出来但如果你的项目里console.log满天飞日志多到根本没法过滤。我后来推动团队做了一个很小的统一日志封装要求每条关键日志都带上模块前缀和场景标记比如console.info([login] steponLoad scene1001 userId9527); console.error([cart] fetchCart fail, code4003, msggoods not found);这样在PageSpy的Console面板里可以按前缀搜索[login]或者[cart]直接把问题模块的日志拉出来不用在一堆无关日志里翻。PageSpy本身也支持日志过滤但前提是你前面把日志打规整了不然什么过滤工具都救不了你。5.3 一套适合团队内部的工作流最后分享一个我们适配后的工作流也许可以直接复制到你的团队里开发阶段本地跑不用PageSpy开发者工具足够。提测阶段上传标记为debug的体验版打开PageSpy开关。测试反馈bug测试同学打开体验版复现一遍开发同学在PageSpy面板看Console和Network大概率能当场截获问题。定位后开发同学用开发者工具修复再上传新体验版覆盖如此循环。发正式版关闭PageSpy开关走正常发布流程。如果团队里测试同学比较多可以把PageSpy管理端地址、体验版二维码、一份“怎么看日志”的简版说明放在同一个文档里。我实际用下来最明显的收益是“用户反馈一个报错开发不用再反复问‘你点哪里了’、‘有没有截图’、‘能复现吗’”页面一打开日志自己就传过来了沟通成本低了不止一个量级。这个方案你搭一次之后基本是长期受益的尤其适合业务逻辑复杂、真机偶发问题多的小程序项目。推荐你也给体验版配上PageSpy调试体验会有一个非常直观的提升。