diff --git a/CLAUDE.md b/CLAUDE.md index 687b8f2..d9b47e1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -119,6 +119,7 @@ daoqi 仓库当前并存两条工作线: | `docs/Development-Plan.md` | 开发执行计划(Phase 0–10、依赖图、进度追踪) | 排期 / 进度更新必读 | | `docs/Verification-Checklist.md` | 功能验证清单(开发期累积、统一验收的操作手册) | 每完成 Phase 子项时补充 / 勾选;不要在 Phase 进行中频繁跑,等多个 Phase 累积后统一验证 | | `docs/SDK-Integration-Guide.md` | 微信 / 高德定位 / opencore-amr / 七牛 接入操作手册(凭证 / Vendor / Info.plist / 代码触点 / BackGameData 清理 / 验收)| 项目方发 SDK 凭证 + 二进制后,按对应章节落地;接完回 §5 清单核对 | +| `docs/H5-Debug-Guide.md` | H5 调试方法(Safari Web Inspector 看大厅 / 子游戏 / 弹层网页输出的操作手册) | 调试 H5 端 console / Network / DOM / 断点时;新增 WKWebView 时也按其 §2 补 `isInspectable` 守卫 | | `../daoqi/`(仓库同级目录) | 原项目 msext 工作参照实现 | 遇到 iOS 行为差异 / 渠道注入 / 桥接 / SDK 初始化等不确定问题时,**优先参考此处**而非凭推测,详见下文「原项目 daoqi:遇到问题时的参考来源」 | --- diff --git a/docs/H5-Debug-Guide.md b/docs/H5-Debug-Guide.md new file mode 100644 index 0000000..434620f --- /dev/null +++ b/docs/H5-Debug-Guide.md @@ -0,0 +1,212 @@ +# H5 调试指南(Safari Web Inspector) + +> **定位**:本文档面向开发者,描述开发期调试 H5(大厅 / 子游戏 / 弹层)网页输出的标准方法。 +> +> **适用范围**:仅 Debug 编译;Release 包不受影响(详见 §6 安全性说明)。 +> +> **不在本文档范围内**: +> - 桥接接口契约 → `H5-Native-Contract.md` +> - 业务功能验收清单 → `Verification-Checklist.md` +> - 原生 `os.log` 日志查看(直接看 Xcode 底部输出窗口即可) + +--- + +## 1. 原理与适用范围 + +WebKit 自 iOS 16.4 起把 `WKWebView` 的网页检查器开关收敛到了 `isInspectable` 属性,**默认关闭**。打开后,该 `WKWebView` 加载的页面会被 Mac Safari 的"开发"菜单识别为可调试目标,等价于在浏览器里按 F12 打开 DevTools,能力包括: + +- **Console**:`console.log/info/warn/error/trace` 全部可见;可在控制台中直接 `evaluate` JS 表达式 +- **Sources**:查看 H5 包内所有 .js / .html / .css 源码;下断点、单步、Watch 表达式 +- **Network**:所有 XHR / fetch / 图片 / 字体请求,请求头/响应/Timing 全可见(含 `file://` 本地资源) +- **Elements**:DOM 树、计算后样式、动画检视 +- **Storage**:localStorage / sessionStorage / Cookies / IndexedDB +- **Timelines**:CPU / 渲染 / 网络时间线 + +**与 Xcode 控制台关系**:Safari Web Inspector 看的是 H5 网页里的 console(JS 端运行结果);Xcode 控制台看的是原生 Swift `print` / `os.log` 输出。两者互补。 + +--- + +## 2. 工程内的代码改动(已落地,无需重做) + +代码侧已经在两处 `WKWebView` 创建点加好了 `#if DEBUG` 守卫的 inspectable 开关: + +- `ylgamehall/Source/WebView/BridgedWebView.swift` :大厅 / 子游戏共用的 `WKWebView` +- `ylgamehall/Source/WebView/OverlayViewController.swift` :弹层(msext `threeView` 等价容器)的 `WKWebView` + +补丁形态(两处一致): + +```swift +let webView = WKWebView(frame: .zero, configuration: configuration) +#if DEBUG +if #available(iOS 16.4, *) { + webView.isInspectable = true +} +#endif +``` + +**重要约束**: + +- **`#if DEBUG` 守卫不可去除** —— Release 包绝对不能让生产 IPA 暴露 Web Inspector,避免被外部审阅 JS 源码 / Storage / 注入表达式 +- **`@available(iOS 16.4, *)` 兼容守卫不可去除** —— 本项目最低 iOS 15.6,低于 16.4 的设备走 `else` 分支(即不开启 inspectable),新设备才走真路径 +- 新增任何第 4 个 `WKWebView` 创建点时,**同样补这 6 行**,否则该 WebView 在 Safari 里看不到 + +--- + +## 3. 前置准备 + +### 3.1 Xcode 端 + +确认 Scheme Run 配置是 Debug(默认就是): + +- 菜单 **Product → Scheme → Edit Scheme...**(`⌘<`)→ 左侧 **Run** → 右侧 **Info** 标签页 +- **Build Configuration = Debug** ✅ + +### 3.2 Mac Safari 端(一次性) + +1. Safari 顶部 → **Safari → 设置(`⌘,`)→ 高级** +2. 勾选最下方 **"在菜单栏中显示开发菜单"** +3. 关闭设置窗口,菜单栏出现"开发"项 + +### 3.3 真机端(一次性,仅真机需要;模拟器跳过) + +iPhone 上:**设置 → Safari → 高级 → 网页检查器 = 开**。 + +> ⚠️ 这个"网页检查器"开关与 Safari 浏览器自身的网页检查无关,是 iOS 18+ 起 Apple 把 `WKWebView` 的可检视性也纳入了这个开关。**如果不开,Mac Safari 的"开发"菜单里看不到该设备的 H5 页面。** + +--- + +## 4. 标准操作流程 + +### 4.1 启动 Debug build + +1. Xcode 顶部 device picker → 选择目标设备/模拟器 +2. `⌘R` 启动 +3. 等大厅 H5 加载完成(屏幕上看到大厅 UI) + +### 4.2 打开 Web Inspector + +Mac Safari 顶部菜单 → **开发 → [设备名] → [页面标题或 URL]** → Web Inspector 浮窗弹出。 + +- 模拟器:菜单层级类似 `开发 → Simulator – iPhone 16 Pro → file:///.../index.html` +- 真机:`开发 → 你的 iPhone 名字 → file:///.../index.html` + +### 4.3 看 console 输出 + +Web Inspector 顶部 tab → **Console** → 实时显示 H5 端的 `console.*` 输出 + JS 异常堆栈。 + +支持直接在底部输入框运行表达式,例如: + +```js +window.WebViewJavascriptBridge // 查看桥对象 +typeof app_gameid // 查看预注入变量 +bridge.callHandler('getphoneInfo', null, r => console.log(r)) // 触发桥调用 +``` + +### 4.4 关闭 Web Inspector + +直接关掉浮窗即可,不影响 app 运行。下次需要时重新打开。 + +--- + +## 5. 多 WebView 场景 + +本项目同时存在最多 3 个 `WKWebView` 实例: + +| 场景 | 创建位置 | 何时存在 | +|------|---------|---------| +| 大厅 | `WebContainerViewController` → `BridgedWebView` | App 全程 | +| 子游戏 | `SubGameViewController` → `BridgedWebView` | push 进子游戏后,pop 销毁 | +| 弹层 | `OverlayViewController` 自建 `WKWebView` | present 显示中,dismiss 销毁 | + +Safari "开发" 菜单会把每个**已加载页面**的 `WKWebView` 列为**独立一项**。 + +### 5.1 关键 gotcha:Develop 菜单不会自动刷新 ⭐ + +进入子游戏 / 打开弹层之后,**已经展开过的"开发"菜单不会自动刷新**,新出现的 WebView 不会冒出来。 + +**做法**: + +- 子游戏 push / 弹层 present 完成后 +- 回 Mac,**先点其它菜单**(如 文件、编辑),让"开发"菜单收起 +- 再展开 **开发 → [设备名]** → 此时新 WebView 才会列出来 + +### 5.2 多条目区分 + +如果列表里多个条目 `` 相同 / 都显示为 `file://...index.html`,分不清哪个是哪个: + +- **鼠标 hover 每个条目** → iPhone/模拟器屏幕上对应的 `WKWebView` 会**高亮蓝色边框** +- 用这个方法定位到目标 WebView,再点击进入 + +### 5.3 弹层 dismiss 后条目消失 + +弹层关闭后 `OverlayViewController` 释放,其 `WKWebView` 被回收,菜单条目随之消失。**必须在弹层显示着的时候调试**,关掉就来不及了。 + +--- + +## 6. 安全性 / Release 包说明 + +- `#if DEBUG` 守卫保证只有 Xcode 的 Debug 配置启用 `isInspectable = true` +- 渠道分发 / 企业签包都用 Release 配置 → 编译期就把 inspectable 那 5 行剔除 → 生产 IPA 没有任何"可检视性"信号 +- 即便用户的 iPhone 开了"网页检查器"开关、Mac Safari 也开了"开发"菜单,Release 包的 WebView **依然不会出现在"开发"菜单** +- 因此**生产环境无需任何额外清理动作**,提交前也不用手动关任何开关 + +--- + +## 7. 常见问题 FAQ + +### Q1:Mac Safari "开发"菜单里完全看不到我的设备 + +按概率排查: + +1. **菜单本身没开** → §3.2 把"在菜单栏中显示开发菜单"勾上 +2. **真机未开"网页检查器"** → §3.3 设置 → Safari → 高级 +3. **真机未连线 / 未信任电脑** → 数据线重插、iPhone 上重新点"信任" +4. **跑的不是 Debug build** → §3.1 Scheme → Run → Build Configuration = Debug +5. **iOS 版本 < 16.4** → 不支持,换个新设备 / 模拟器 +6. **Mac 与 iPhone 不在同一 Wi-Fi** → 仅无线调试需要;有线优先 +7. **`isInspectable` 补丁丢了** → grep `isInspectable` 应该有 2 处命中,否则被回滚了 + +### Q2:只看到大厅,子游戏 / 弹层看不到 + +→ §5.1 关闭"开发"菜单再重开。99% 是这个原因。 + +### Q3:能看到条目但 Console 是空的 + +可能原因: + +- H5 端确实没有 `console.*` 调用(业务在沉默运行,没问题就不输出) +- Web Inspector 打开前的旧日志没被记录 → 在 Web Inspector 已经打开的状态下**触发一次** H5 操作(点按钮、切 tab)再看 +- Console 顶部过滤器把日志级别过滤掉了 → 确认 All Levels 都选中 + +### Q4:Sources 里看不到 .js 源码 + +- 检查 H5 zip 是否在沙盒里正常解压(`AppDataWriter.swift` 写入的 `app_*.js` 也应出现) +- 如果某文件被打包成 minified / 不带 sourcemap,源码可读性差 —— 这是上游 H5 构建问题,原生侧无能为力 + +### Q5:Network 标签里看到一堆奇怪的 `wkbridge://__bridge_loaded__` 请求 + +这是 `WebViewJavascriptBridge` JS 端用 iframe + `src` 协议触发原生回调的机制,**正常行为,不要去掉**。详见 `Resources/JS/WebViewJavascriptBridge.js`。 + +### Q6:Safari 提示 "Web Inspector cannot connect" + +- 重连数据线 / 重启 Safari / 重启 Xcode +- iPhone 16+ 偶发协议握手失败,重启 iPhone 通常恢复 + +--- + +## 8. 何时本方法不够用 + +Safari Web Inspector 是开发期主力,但有它够不到的场景: + +- **真机 + 用户已在生产环境**:Release 包没有 inspectable;需要的是事后日志,参考原生侧的崩溃 / 错误上报(项目目前无 crash 监控,依赖用户反馈) +- **断网 / 弱网下的 H5 表现**:用 Mac 上的 Network Link Conditioner,或模拟器 Features → Network Link Conditioner +- **生产环境的 H5 console 输出**:原生侧已经装了 `H5ErrorRelay`(`Source/Bridge/H5ErrorRelay.swift`),会把 `console.error / window.onerror / unhandledrejection` 转发到原生 `print`,Debug build 可在 Xcode 控制台看到。要扩展到 `console.log` 全量转发,可参考其实现照葫芦画瓢 +- **断点调试原生 Swift 与 H5 同时跑**:Xcode + Safari Web Inspector 同时打开,两边各自下断点互不影响 + +--- + +## 9. 修订记录 + +| 日期 | 内容 | +|------|------| +| 2026-06-24 | 文档建立。落地 `BridgedWebView` / `OverlayViewController` 两处 `isInspectable` 补丁。 |