收紧宿主壳结构文档门禁
新增三端桥接层文件清单的文档反查 同步宿主壳方案与协议文档的当前结构 记录桥接层结构文档反查决策
This commit is contained in:
@@ -103,7 +103,7 @@
|
||||
- 2026-06-18 移动壳 WebView 安全开关:Expo 移动壳 WebView 必须显式禁用 JS 自动开窗、多窗口、文件访问、file URL 跨源访问、HTTPS 混合内容、第三方 Cookie、共享 Cookie 和 WebView 远程调试;同源主站页面才能留在带 HostBridge 的 WebView 内,外链只通过受控协议离开容器交给系统。配置检查和移动壳导航测试会拒绝这些边界被放宽。
|
||||
- 2026-06-18 移动壳 WebView 默认下载边界:Expo WebView 内网页自动下载和 `<a download>` 直接落盘默认关闭;壳层注入脚本阻断 download 链接,iOS `onFileDownload` 只丢弃不落盘,Android 包配置通过 `blockedPermissions` 移除外部存储读写、管理外部存储和请求安装包权限。移动端文本、图片、音频保存只能通过 `file.exportText`、`file.exportImage`、`file.exportAudio` 等 HostBridge 受控导出能力进入系统分享 / 保存面板。
|
||||
- 2026-06-18 移动壳 HostBridge 消息来源校验:Expo 移动壳 `onMessage` 必须根据 `event.nativeEvent.url` 校验消息来源,只有同源主站页面能进入 `handleMobileHostBridgeMessage`;`about:blank`、外域、协议降级和危险协议页面消息直接丢弃,不返回宿主能力错误细节。该规则与 WebView 导航留壳规则共用同源判断,配置检查和移动壳导航测试会拒绝移除。
|
||||
- 2026-06-18 三端桥接层目录同构:微信小程序、Expo 移动壳和 Tauri 桌面壳都按 `host-bridge / shell` 两层管理宿主桥接代码。微信 `miniprogram/host-bridge/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js` 只放协议归一、支付 / 订阅 / 分享结果编解码和可测试桥接函数,`miniprogram/shell/` 下同名职责文件承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂;页面目录只保留 `Page(createWechat...Page())` 装配。Expo `protocol.ts`、`files.ts`、`share.ts` 和 facade `bridge.ts` 分别对齐 Tauri `host_bridge/protocol.rs`、`files.rs`、`share.rs`、`mod.rs`,根 `App.tsx` 只装配 `src/shell/ShellApp.tsx`,不直接进口 HostBridge。Tauri `shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面。`npm run check:native-shells` 会校验微信、移动和桌面三端目录清单,新增宿主能力必须按同一边界落文件和测试。
|
||||
- 2026-06-18 三端桥接层目录同构:微信小程序、Expo 移动壳和 Tauri 桌面壳都按 `host-bridge / shell` 两层管理宿主桥接代码。微信 `miniprogram/host-bridge/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js` 只放协议归一、支付 / 订阅 / 分享结果编解码和可测试桥接函数,`miniprogram/shell/` 下同名职责文件承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂;页面目录只保留 `Page(createWechat...Page())` 装配。Expo `protocol.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`scanner.ts`、`share.ts` 和 facade `bridge.ts` 分别对齐 Tauri `host_bridge/protocol.rs`、`capabilities.rs`、`dispatch.rs`、`files.rs`、`share.rs`、`mod.rs`,根 `App.tsx` 只装配 `src/shell/ShellApp.tsx`,不直接进口 HostBridge。Tauri `shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面。`npm run check:native-shells` 会校验微信、移动和桌面三端目录清单,新增宿主能力必须按同一边界落文件和测试。
|
||||
- 影响范围:`src/services/host-bridge/`、未来 `apps/mobile-shell/`、未来 `apps/desktop-shell/`、移动端支付 / 分享 / 深链 / 推送、桌面端系统能力、AI H5 sandbox 的 GameBridge 边界。
|
||||
- 验证方式:普通浏览器、小程序、Expo 壳、Tauri 壳都能返回正确 `getHostRuntime()`;未支持能力能回退 H5;固定玩法在各宿主中读取同一作品数据和运行态 snapshot;AI sandbox 无法直接调用 HostBridge;Tauri release 不允许任意远端页面调用桌面命令。
|
||||
- 关联文档:`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`、`docs/【前端架构】宿主壳能力统一协议-2026-06-17.md`。
|
||||
@@ -2515,10 +2515,17 @@
|
||||
## 2026-06-18 三端宿主桥接层文件结构对齐
|
||||
|
||||
- 背景:微信小程序壳、Expo 移动壳和 Tauri 桌面壳都在承接宿主能力;如果微信页面继续散落 `index.shared.js`,桌面端继续把桥接分发堆在 `main.rs`,后续新增登录、支付、文件、通知或 sandbox 转发能力时会很难跨端对照 owner。
|
||||
- 决策:三端桥接层按职责对齐,但保留各宿主真实边界。微信小程序页面路由不改,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面目录只保留生命周期和装配,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Expo 移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`share.ts` 和 facade `bridge.ts`,分别负责 envelope / request 校验 / ok-failure 响应 / replay 基础类型、能力清单与 iOS 差异、method 分发、文件能力、分享能力和 WebView message 入口 / request id replay 编排;根 `App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,`apps/mobile-shell/src/shell/*.ts(x)` 负责 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policy;Tauri 桌面壳拆成 `apps/desktop-shell/src-tauri/src/app.rs`、`host_bridge/protocol.rs`、`capabilities.rs`、`dispatch.rs`、`files.rs`、`share.rs` 和 command facade `mod.rs`,分别负责 Tauri builder / plugin / window 装配、envelope / method 白名单 / request 校验 / replay 状态、能力清单、method 分发、文件能力、分享能力和 `host_bridge_request` command / replay 编排;`apps/desktop-shell/src-tauri/src/shell/*.rs` 承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面,`main.rs` 只做薄入口并调用 `app::run()`。`scripts/check-native-shells.mjs` 锁定三端桥接层目录清单,并拒绝移动根入口和桌面根入口重新承接宿主能力装配。
|
||||
- 决策:三端桥接层按职责对齐,但保留各宿主真实边界。微信小程序页面路由不改,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面目录只保留生命周期和装配,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Expo 移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`scanner.ts`、`share.ts` 和 facade `bridge.ts`,分别负责 envelope / request 校验 / ok-failure 响应 / replay 基础类型、能力清单与 iOS 差异、method 分发、文件能力、扫码能力、分享能力和 WebView message 入口 / request id replay 编排;根 `App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,`apps/mobile-shell/src/shell/*.ts(x)` 负责 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policy;Tauri 桌面壳拆成 `apps/desktop-shell/src-tauri/src/app.rs`、`host_bridge/protocol.rs`、`capabilities.rs`、`dispatch.rs`、`files.rs`、`share.rs` 和 command facade `mod.rs`,分别负责 Tauri builder / plugin / window 装配、envelope / method 白名单 / request 校验 / replay 状态、能力清单、method 分发、文件能力、分享能力和 `host_bridge_request` command / replay 编排;`apps/desktop-shell/src-tauri/src/shell/*.rs` 承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`main.rs` 只做薄入口并调用 `app::run()`。`scripts/check-native-shells.mjs` 锁定三端桥接层目录清单,并拒绝移动根入口和桌面根入口重新承接宿主能力装配。
|
||||
- 影响范围:`miniprogram/host-bridge/`、`miniprogram/pages/*/index.js`、`apps/mobile-shell/src/`、`apps/desktop-shell/src-tauri/src/`、`scripts/check-native-shells.mjs`、宿主壳方案文档。
|
||||
- 验证方式:`npm run test -- miniprogram/host-bridge/webView.test.js miniprogram/host-bridge/payment.test.js miniprogram/host-bridge/shareGrid.test.js miniprogram/host-bridge/subscribeMessage.test.js miniprogram/pages/web-view/index.style.test.js`、`npm run check:native-shells`、`npm run typecheck`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-19 三端宿主桥接层结构文档反查
|
||||
|
||||
- 背景:三端桥接层已经拆出移动 `scanner.ts`、桌面 `menu.rs`、`window_state.rs` 等职责文件,但如果只更新代码和目录门禁,`宿主壳能力统一协议` 与 `ExpoReactNative与Tauri宿主壳方案` 可能继续保留旧清单,后续开发者按文档扩展时仍会把能力放回错误 owner。
|
||||
- 决策:`scripts/check-native-shells.mjs` 的三端桥接层目录清单同时作为文档反查来源。根级门禁会确认两份前端架构文档都显式列出微信桥接层、微信 shell、移动桥接层、移动 shell、桌面入口、桌面桥接层和桌面 shell 的当前生产文件;新增、删除或改名这些职责文件时,必须同时更新脚本清单、两份架构文档和相关实现,不允许只改一端。
|
||||
- 影响范围:`scripts/check-native-shells.mjs`、`docs/【前端架构】宿主壳能力统一协议-2026-06-17.md`、`docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`、三端宿主壳源码布局。
|
||||
- 验证方式:`npm run check:native-shells`、`npm run check:encoding`、`git diff --check`。
|
||||
|
||||
## 2026-06-19 HostBridge 载荷边界单一来源
|
||||
|
||||
- 背景:文件导入导出、剪贴板、角标、本地通知和 request id 都已经在 Expo 与 Tauri 两套壳里有运行时校验;如果 MIME 清单、字节上限或文本长度只靠人工同步,新增文件类型或调整上限时会出现 H5 契约、移动壳和桌面壳互相漂移。
|
||||
|
||||
@@ -64,7 +64,9 @@ src/
|
||||
|
||||
已落地:`packages/shared/src/contracts/hostBridge.ts` 保存消息 envelope、method、payload 和错误码,H5、Expo 壳与 Tauri 壳共享同一份协议类型。
|
||||
|
||||
三端宿主桥接层按职责对齐命名:微信小程序页面路由仍保留在 `miniprogram/pages/*`,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂统一放在 `miniprogram/shell/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面入口只做 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` 分别承接文件和分享能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade;`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`。
|
||||
三端宿主桥接层按职责对齐命名:微信小程序页面路由仍保留在 `miniprogram/pages/*`,`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,不把微信小程序硬改成 Expo / Tauri 的 request 总线;Page 生命周期、`wx.*` 容器调用、WebView 容器行为和页面工厂统一放在 `miniprogram/shell/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面入口只做 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` / `scanner.ts` 分别承接文件、分享和扫码能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade;`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`。
|
||||
|
||||
当前 `npm run check:native-shells` 锁定的生产文件清单为:微信桥接层 `dispatch.js`、`payment.js`、`protocol.js`、`shareGrid.js`、`subscribeMessage.js`、`webView.js`;微信 shell 层 `payment.js`、`shareGrid.js`、`subscribeMessage.js`、`webView.js`;移动桥接层 `bridge.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`protocol.ts`、`scanner.ts`、`share.ts`;移动 shell 层 `QrScannerOverlay.tsx`、`ShellApp.tsx`、`deepLink.ts`、`lifecycle.ts`、`loadFailure.ts`、`navigation.ts`、`network.ts`、`runtime.ts`、`safeArea.ts`、`url.ts`、`webViewGlobals.d.ts`、`webViewHistory.ts`、`webViewPolicy.ts`;桌面入口 `app.rs`、`main.rs`;桌面桥接层 `capabilities.rs`、`dispatch.rs`、`files.rs`、`mod.rs`、`protocol.rs`、`share.rs`;桌面 shell 层 `deep_link.rs`、`events.rs`、`file_drop.rs`、`lifecycle.rs`、`menu.rs`、`mod.rs`、`navigation.rs`、`network.rs`、`runtime.rs`、`tray.rs`、`url.rs`、`webview.rs`、`window_state.rs`。
|
||||
|
||||
## HostBridge 消息协议
|
||||
|
||||
@@ -189,7 +191,7 @@ Tauri 壳同样只负责桌面宿主能力,不承接玩法业务。
|
||||
|
||||
- Release 包默认打包当前 H5 `dist`,保证桌面包版本可复现。
|
||||
- Dev 模式允许加载本地 Vite URL,方便调试。
|
||||
- H5 通过 `window.__TAURI__.core.invoke('host_bridge_request', request)` 或后续封装的 `nativeAppHostBridge` 调用桌面能力。
|
||||
- H5 通过 `nativeAppHostBridge` 超时封装调用 `window.__TAURI__.core.invoke('host_bridge_request', request)`,不直接调用其它 Tauri command。
|
||||
- Rust 侧只暴露一个受控 `host_bridge_request` command,再在 Rust 内部按 method 白名单分发。
|
||||
- Tauri capabilities 只授予主窗口所需命令;默认不开放文件系统、shell、全局剪贴板或任意插件能力。
|
||||
- 主窗口 capability 只授予 `allow-host-bridge-request`;不得使用 `core:default`、`core:*:default` 或插件 command 权限作为兜底。窗口、菜单、托盘、剪贴板、文件、通知和外链能力只能由 Rust 壳内部调用,再通过 `host_bridge_request` 的 HostBridge method 白名单分发给 H5。
|
||||
@@ -470,7 +472,7 @@ GameBridge 禁止:
|
||||
|
||||
2026-06-18 追加:`app.openExternalUrl` 的协议白名单以共享 HostBridge 契约 `HOST_BRIDGE_EXTERNAL_URL_PROTOCOLS` 为唯一来源,当前只允许 `http:`、`https:`、`mailto:`、`tel:`。Expo 壳直接复用共享归一化逻辑,Tauri 壳 Rust 侧用 URL parser 镜像同一清单;`npm run check:native-shells` 会反查共享契约与桌面壳协议清单,防止某一端单独放宽外链协议。
|
||||
|
||||
2026-06-18 追加:微信、移动端和桌面端桥接层文件结构按职责对齐。微信小程序的 `web-view`、支付、九宫切图和订阅消息桥接逻辑统一迁入 `miniprogram/host-bridge/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面目录只保留页面生命周期、WXML/WXSS 和装配;移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts`、`files.ts`、`share.ts` 和 facade `bridge.ts`,与桌面端 `host_bridge/protocol.rs`、`files.rs`、`share.rs`、`mod.rs` 对齐;移动壳根 `App.tsx` 也保持薄入口,只装配 `src/shell/ShellApp.tsx`,WebView 容器、深链、网络、生命周期和安全策略全部留在 `src/shell/`;桌面壳 Rust 源码拆成 `apps/desktop-shell/src-tauri/src/app.rs`、`host_bridge/*.rs` 与 `shell/*.rs`,其中 `app.rs` 承接 Tauri builder / plugin / window 装配,`runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,薄 `main.rs` 只声明模块并调用 `app::run()`。根级 `npm run check:native-shells` 会锁定三端桥接层目录清单,避免后续把能力逻辑重新散落到页面、移动入口或桌面入口。
|
||||
2026-06-18 追加:微信、移动端和桌面端桥接层文件结构按职责对齐。微信小程序的 `web-view`、支付、九宫切图和订阅消息桥接逻辑统一迁入 `miniprogram/host-bridge/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`,页面目录只保留页面生命周期、WXML/WXSS 和装配;移动壳拆成 `apps/mobile-shell/src/host-bridge/protocol.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`scanner.ts`、`share.ts` 和 facade `bridge.ts`,与桌面端 `host_bridge/protocol.rs`、`capabilities.rs`、`dispatch.rs`、`files.rs`、`share.rs`、`mod.rs` 对齐;移动壳根 `App.tsx` 也保持薄入口,只装配 `src/shell/ShellApp.tsx`,WebView 容器、深链、网络、生命周期、安全区、扫码 overlay 和安全策略全部留在 `src/shell/`;桌面壳 Rust 源码拆成 `apps/desktop-shell/src-tauri/src/app.rs`、`host_bridge/*.rs` 与 `shell/*.rs`,其中 `app.rs` 承接 Tauri builder / plugin / window 装配,`runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,薄 `main.rs` 只声明模块并调用 `app::run()`。根级 `npm run check:native-shells` 会锁定三端桥接层目录清单,避免后续把能力逻辑重新散落到页面、移动入口或桌面入口。
|
||||
|
||||
2026-06-19 追加:HostBridge 载荷边界以共享契约为单一声明来源。`packages/shared/src/contracts/hostBridge.ts` 导出文本 / 图片 / 音频 MIME 清单、导入 / 导出字节上限、导出文件名 fallback 与长度上限,以及 request id、角标、剪贴板和本地通知文本长度边界;Expo 移动壳必须直接导入这些共享常量,不再本地重声明文件大小或 MIME 清单,并且文本 / 音频导入必须在读取内容前通过 picker `size` 或 Expo `File.size` 完成大小门禁,无法拿到可信 byte count 时直接拒绝导入;Tauri 桌面壳的配置检查会反查 Rust 镜像实现,拒绝文件大小、MIME 清单、文件名、通知、剪贴板或 request id 边界与共享契约漂移。新增文件类型或调整体积上限必须先更新共享契约、壳实现和门禁,再进入玩法或 H5 facade。
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
- 不重写 React 主站和现有玩法 runtime。
|
||||
- 不把固定玩法迁成远程代码包。
|
||||
- 不在本阶段实现 React Native / Expo 壳。
|
||||
- 不在 HostBridge 层重写 React Native / Expo 或 Tauri 业务 UI。
|
||||
- 不改变支付到账、任务、排行榜、发布、统计等后端裁决口径。
|
||||
|
||||
## 分层
|
||||
@@ -37,7 +37,9 @@ AI H5 sandbox
|
||||
-> parent HostBridge adapter
|
||||
```
|
||||
|
||||
桥接层文件结构按宿主统一为“协议 / 能力清单 / 分发 / 宿主容器行为”四类职责。微信小程序不硬套 Expo / Tauri 的 request 总线:`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`;`miniprogram/shell/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js` 承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为、支付页和订阅页装配,页面目录只保留 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` 分别承接文件和分享能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade;`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`。`npm run check:native-shells` 会检查这些目录清单。
|
||||
桥接层文件结构按宿主统一为“协议 / 能力清单 / 分发 / 宿主容器行为”四类职责。微信小程序不硬套 Expo / Tauri 的 request 总线:`miniprogram/host-bridge/protocol.js` 只沉淀微信壳能力、页面 URL、结果 hash / storage key 和分享消息类型等常量,`dispatch.js` 只作为 `protocol`、`webView`、`payment`、`shareGrid`、`subscribeMessage` 的薄索引,真实协议归一、支付 / 订阅 / 分享结果编解码仍分别放在 `webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js`;`miniprogram/shell/webView.js`、`payment.js`、`shareGrid.js`、`subscribeMessage.js` 承接 Page 生命周期、`wx.*` 容器调用、WebView 容器行为、支付页和订阅页装配,页面目录只保留 `Page(createWechat...Page())` 装配。Expo 移动壳使用 `apps/mobile-shell/src/host-bridge/protocol.ts` 承接 envelope、request 校验、ok / failure 响应和 replay 基础类型,`capabilities.ts` 只引用共享 HostBridge capability profile 并选择 iOS 差异能力,`dispatch.ts` 承接 method 分发和宿主能力调用,`files.ts` / `share.ts` / `scanner.ts` 分别承接文件、分享和扫码能力,`bridge.ts` 只作为 WebView message 入口、request id replay 编排和对外 facade;`apps/mobile-shell/App.tsx` 只装配 `apps/mobile-shell/src/shell/ShellApp.tsx`,由 `apps/mobile-shell/src/shell/*.ts(x)` 承接 WebView 容器、URL、导航、网络、生命周期、安全区、扫码 overlay 和 WebView policy。Tauri 桌面壳使用 `apps/desktop-shell/src-tauri/src/host_bridge/protocol.rs` 承接 envelope、method 白名单、request 校验和 replay 状态,`capabilities.rs` 承接共享桌面 capability profile 的 Rust 运行时镜像,`dispatch.rs` 承接 method 分发和宿主能力调用,`files.rs` / `share.rs` 分别承接文件和分享能力,`mod.rs` 只保留模块声明、必要 re-export、`host_bridge_request` command facade 和 replay 编排;`apps/desktop-shell/src-tauri/src/shell/runtime.rs`、`url.rs`、`navigation.rs`、`network.rs`、`lifecycle.rs`、`file_drop.rs`、`events.rs`、`deep_link.rs`、`tray.rs`、`menu.rs`、`window_state.rs` 和 `webview.rs` 分别承接运行态、入口 URL、导航 / 下载、网络、生命周期、拖拽图片、HostBridge 事件注入、深链、托盘、应用菜单、窗口状态持久化和 WebView 门面,`apps/desktop-shell/src-tauri/src/app.rs` 承接 Tauri builder / plugin / window 装配,`main.rs` 只保留薄入口并调用 `app::run()`。`npm run check:native-shells` 会检查这些目录清单。
|
||||
|
||||
当前 `npm run check:native-shells` 锁定的生产文件清单为:微信桥接层 `dispatch.js`、`payment.js`、`protocol.js`、`shareGrid.js`、`subscribeMessage.js`、`webView.js`;微信 shell 层 `payment.js`、`shareGrid.js`、`subscribeMessage.js`、`webView.js`;移动桥接层 `bridge.ts`、`capabilities.ts`、`dispatch.ts`、`files.ts`、`protocol.ts`、`scanner.ts`、`share.ts`;移动 shell 层 `QrScannerOverlay.tsx`、`ShellApp.tsx`、`deepLink.ts`、`lifecycle.ts`、`loadFailure.ts`、`navigation.ts`、`network.ts`、`runtime.ts`、`safeArea.ts`、`url.ts`、`webViewGlobals.d.ts`、`webViewHistory.ts`、`webViewPolicy.ts`;桌面入口 `app.rs`、`main.rs`;桌面桥接层 `capabilities.rs`、`dispatch.rs`、`files.rs`、`mod.rs`、`protocol.rs`、`share.rs`;桌面 shell 层 `deep_link.rs`、`events.rs`、`file_drop.rs`、`lifecycle.rs`、`menu.rs`、`mod.rs`、`navigation.rs`、`network.rs`、`runtime.rs`、`tray.rs`、`url.rs`、`webview.rs`、`window_state.rs`。
|
||||
|
||||
## 首批能力
|
||||
|
||||
@@ -88,7 +90,6 @@ HostBridge 事件名以 `packages/shared/src/contracts/hostBridge.ts` 的 `HOST_
|
||||
|
||||
## 后续
|
||||
|
||||
- 设计 `native_app` 的 `postMessage` 消息格式和回包超时策略。
|
||||
- 原生 App 壳的移动端采用 `Expo + React Native`,桌面端采用 `Tauri`;壳层只作为 HostBridge adapter,不重写现有 H5 主站和固定玩法 runtime。详细方案见 `docs/【前端架构】ExpoReactNative与Tauri宿主壳方案-2026-06-17.md`。
|
||||
- 为 AI H5 sandbox 单独定义 GameBridge,禁止直接依赖 HostBridge。
|
||||
- 将宿主能力、支付渠道和分享策略补充进移动端发布检查清单。
|
||||
- 原生登录、渠道支付、远程推送、自动更新、崩溃上报和 analytics 等能力必须等真实 SDK、后端契约、发布流程和隐私口径确定后逐项接入。
|
||||
|
||||
@@ -171,6 +171,44 @@ const expectedDesktopShellRustFiles = [
|
||||
'webview.rs',
|
||||
'window_state.rs',
|
||||
];
|
||||
const documentedShellLayerGroups = [
|
||||
{
|
||||
label: 'wechat host bridge files',
|
||||
files: expectedWechatHostBridgeFiles.filter(
|
||||
(fileName) => !fileName.includes('.test.'),
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'wechat shell files',
|
||||
files: expectedWechatShellFiles.filter(
|
||||
(fileName) => !fileName.includes('.test.'),
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'mobile host bridge files',
|
||||
files: expectedMobileHostBridgeFiles.filter(
|
||||
(fileName) => !fileName.includes('.test.'),
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'mobile shell files',
|
||||
files: expectedMobileShellFiles.filter(
|
||||
(fileName) => !fileName.includes('.test.'),
|
||||
),
|
||||
},
|
||||
{
|
||||
label: 'desktop entrypoint files',
|
||||
files: ['app.rs', 'main.rs'],
|
||||
},
|
||||
{
|
||||
label: 'desktop host bridge files',
|
||||
files: expectedDesktopHostBridgeRustFiles,
|
||||
},
|
||||
{
|
||||
label: 'desktop shell files',
|
||||
files: expectedDesktopShellRustFiles,
|
||||
},
|
||||
];
|
||||
const capabilityListMarkers = {
|
||||
desktop: '桌面壳当前真实能力完整清单为',
|
||||
mobile: '移动壳当前通用真实能力完整清单为',
|
||||
@@ -539,6 +577,16 @@ function assertSameList(actual, expected, label) {
|
||||
}
|
||||
}
|
||||
|
||||
function assertShellLayerLayoutDocumented(source, label) {
|
||||
for (const group of documentedShellLayerGroups) {
|
||||
for (const fileName of group.files) {
|
||||
if (!source.includes(fileName)) {
|
||||
throw new Error(`${label} missing ${group.label}: ${fileName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extractTsStringArray(source, exportName, seen = new Set()) {
|
||||
if (seen.has(exportName)) {
|
||||
throw new Error(`cyclic string array export ${exportName}`);
|
||||
@@ -665,6 +713,11 @@ function assertNativeShellCapabilityPlan() {
|
||||
decisionLogDocSource,
|
||||
'decision log document',
|
||||
);
|
||||
assertShellLayerLayoutDocumented(planSource, 'native shell plan');
|
||||
assertShellLayerLayoutDocumented(
|
||||
hostBridgeProtocolDocSource,
|
||||
'HostBridge protocol document',
|
||||
);
|
||||
|
||||
const desktopCapabilitySource = fs.readFileSync(
|
||||
'apps/desktop-shell/src-tauri/src/host_bridge/capabilities.rs',
|
||||
|
||||
Reference in New Issue
Block a user