@skillbuilder/miniapp-simulator 0.0.0-beta-20261023084421
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +214 -0
- package/assets/phones/Nexus-5X.png +0 -0
- package/assets/phones/iPhone-14ProMax.png +0 -0
- package/assets/rednote-preview/cover/homebar-1439.jpg +0 -0
- package/assets/rednote-preview/cover/homebar-1679.jpg +0 -0
- package/assets/rednote-preview/cover/homebar-1919.jpg +0 -0
- package/assets/rednote-preview/cover/homebar-2284.jpg +0 -0
- package/assets/rednote-preview/cover/homebar-2285.jpg +0 -0
- package/assets/rednote-preview/cover/like.png +0 -0
- package/assets/rednote-preview/cover/play.png +0 -0
- package/assets/rednote-preview/cover/topbar-1439.jpg +0 -0
- package/assets/rednote-preview/cover/topbar-1679.jpg +0 -0
- package/assets/rednote-preview/cover/topbar-1919.jpg +0 -0
- package/assets/rednote-preview/cover/topbar-2284.jpg +0 -0
- package/assets/rednote-preview/cover/topbar-2285.jpg +0 -0
- package/assets/workbench/index.html +77 -0
- package/dist/sw/miniapp-simulator-service-worker.js +855 -0
- package/dist/sw/miniapp-simulator-service-worker.min.js +1 -0
- package/docs/consumer-guide.md +143 -0
- package/docs/electron-review.md +21 -0
- package/docs/external-cli-workbench.md +197 -0
- package/docs/file-system-design.md +334 -0
- package/docs/host-external-api.md +235 -0
- package/docs/iframe-service-worker.md +190 -0
- package/docs/local-dev.md +106 -0
- package/docs/npm-integration-verification.md +45 -0
- package/docs/remote-architecture.md +403 -0
- package/docs/remote-load-observability.md +268 -0
- package/docs/remote-usage.md +371 -0
- package/docs/request-design.md +247 -0
- package/docs/sdk-usage.md +260 -0
- package/docs/server-playground-https-debugging.md +150 -0
- package/docs/storage-api-design.md +275 -0
- package/docs/tracker.md +339 -0
- package/lib/business-line-CMb3ehRn.mjs +15 -0
- package/lib/client-BZtD2VtP.mjs +772 -0
- package/lib/index-BW85h7kT.mjs +505 -0
- package/lib/index.js +10686 -0
- package/lib/preload/webview-preload.js +37 -0
- package/lib/remote-client.js +11 -0
- package/lib/types/business-line.d.ts +7 -0
- package/lib/types/capabilities/constants.d.ts +28 -0
- package/lib/types/capabilities/csp-snippet.d.ts +32 -0
- package/lib/types/capabilities/launch-options.d.ts +7 -0
- package/lib/types/capabilities/performance-policy.d.ts +5 -0
- package/lib/types/capabilities/security-head-snippet.d.ts +20 -0
- package/lib/types/capabilities/security.d.ts +25 -0
- package/lib/types/capabilities/style-snippet.d.ts +2 -0
- package/lib/types/core/controllers/game-playtest.d.ts +9 -0
- package/lib/types/core/controllers/gesture.d.ts +8 -0
- package/lib/types/core/controllers/host-api.d.ts +19 -0
- package/lib/types/core/controllers/index.d.ts +11 -0
- package/lib/types/core/controllers/inspector.d.ts +20 -0
- package/lib/types/core/controllers/note-preview.d.ts +9 -0
- package/lib/types/core/controllers/permission-sheet.d.ts +7 -0
- package/lib/types/core/controllers/widget-cover.d.ts +12 -0
- package/lib/types/core/lifecycle.d.ts +7 -0
- package/lib/types/core/options.d.ts +33 -0
- package/lib/types/core/simulator.d.ts +9 -0
- package/lib/types/errors.d.ts +11 -0
- package/lib/types/event-bus.d.ts +15 -0
- package/lib/types/gesture/host-bus.d.ts +113 -0
- package/lib/types/gesture/index.d.ts +27 -0
- package/lib/types/gesture/plugins/double-tap.d.ts +10 -0
- package/lib/types/gesture/plugins/index.d.ts +27 -0
- package/lib/types/gesture/plugins/long-press.d.ts +13 -0
- package/lib/types/gesture/plugins/multi-touch-hint.d.ts +11 -0
- package/lib/types/gesture/plugins/multi-touch-switch.d.ts +18 -0
- package/lib/types/gesture/plugins/selection-disabler.d.ts +11 -0
- package/lib/types/gesture/plugins/tap.d.ts +11 -0
- package/lib/types/gesture/plugins/touch-emitter.d.ts +11 -0
- package/lib/types/gesture/plugins/wheel-scroll.d.ts +11 -0
- package/lib/types/gesture/receiver-runtime.d.ts +10 -0
- package/lib/types/gesture/receiver-runtime.impl.d.ts +6 -0
- package/lib/types/gesture/touch-cursor.d.ts +78 -0
- package/lib/types/gesture/touch-dot.d.ts +12 -0
- package/lib/types/gesture/types.d.ts +206 -0
- package/lib/types/host/shadow-host.d.ts +40 -0
- package/lib/types/index.d.ts +49 -0
- package/lib/types/injection/guest-log-mark.d.ts +7 -0
- package/lib/types/injection/head-builder.d.ts +4 -0
- package/lib/types/injection/index.d.ts +19 -0
- package/lib/types/injection/modules/console-forward.d.ts +2 -0
- package/lib/types/injection/modules/gesture.d.ts +6 -0
- package/lib/types/injection/modules/inspector-guest-runtime.d.ts +5 -0
- package/lib/types/injection/modules/inspector-pause-runtime.d.ts +6 -0
- package/lib/types/injection/modules/inspector.d.ts +8 -0
- package/lib/types/injection/modules/jsapi-channel.d.ts +9 -0
- package/lib/types/injection/modules/jsapi.d.ts +22 -0
- package/lib/types/injection/modules/render-done.d.ts +2 -0
- package/lib/types/injection/modules/resource-guard.d.ts +7 -0
- package/lib/types/injection/modules/scroll-containment.d.ts +3 -0
- package/lib/types/injection/modules/security.d.ts +3 -0
- package/lib/types/injection/modules/widget-snapshot.d.ts +13 -0
- package/lib/types/injection/preload-builder.d.ts +41 -0
- package/lib/types/injection/registry.d.ts +20 -0
- package/lib/types/injection/types.d.ts +43 -0
- package/lib/types/inspector/host-inspector.d.ts +108 -0
- package/lib/types/inspector/index.d.ts +8 -0
- package/lib/types/inspector/selector.d.ts +18 -0
- package/lib/types/native-ui/devtools/CapabilitiesView.d.ts +18 -0
- package/lib/types/native-ui/devtools/DevtoolsPanel.d.ts +24 -0
- package/lib/types/native-ui/devtools/LogsView.d.ts +17 -0
- package/lib/types/native-ui/devtools/dom.d.ts +40 -0
- package/lib/types/native-ui/devtools/index.d.ts +19 -0
- package/lib/types/native-ui/devtools/log-entry.d.ts +8 -0
- package/lib/types/native-ui/devtools/shortcut.d.ts +12 -0
- package/lib/types/native-ui/devtools/tokens.d.ts +14 -0
- package/lib/types/native-ui/devtools/types.d.ts +51 -0
- package/lib/types/native-ui/index.d.ts +17 -0
- package/lib/types/native-ui/note-publish/defaults.d.ts +40 -0
- package/lib/types/native-ui/note-publish/index.d.ts +2 -0
- package/lib/types/native-ui/note-publish/miniapp-note-publish.d.ts +15 -0
- package/lib/types/native-ui/note-publish/note-publish-host.d.ts +15 -0
- package/lib/types/native-ui/note-publish/view-data.d.ts +21 -0
- package/lib/types/native-ui/permission-sheet/defaults.d.ts +12 -0
- package/lib/types/native-ui/permission-sheet/index.d.ts +4 -0
- package/lib/types/native-ui/permission-sheet/miniapp-permission-sheet.d.ts +19 -0
- package/lib/types/native-ui/permission-sheet/permission-sheet-host.d.ts +23 -0
- package/lib/types/native-ui/permission-sheet/types.d.ts +8 -0
- package/lib/types/native-ui/rednote-preview/chrome-tone.d.ts +44 -0
- package/lib/types/native-ui/rednote-preview/defaults.d.ts +30 -0
- package/lib/types/native-ui/rednote-preview/half-sheet-drag.d.ts +61 -0
- package/lib/types/native-ui/rednote-preview/index.d.ts +2 -0
- package/lib/types/native-ui/rednote-preview/register.d.ts +7 -0
- package/lib/types/native-ui/rednote-preview/styles.d.ts +4 -0
- package/lib/types/native-ui/rednote-preview/xhs-note-detail-shell.d.ts +70 -0
- package/lib/types/native-ui/rednote-preview/xhs-note-half-sheet.d.ts +100 -0
- package/lib/types/native-ui/rednote-preview/xhs-profile-shell.d.ts +31 -0
- package/lib/types/native-ui/toast/frame-toast-host.d.ts +18 -0
- package/lib/types/native-ui/toast/index.d.ts +19 -0
- package/lib/types/presets.d.ts +11 -0
- package/lib/types/remote/client.d.ts +89 -0
- package/lib/types/remote/jsapi-config.d.ts +9 -0
- package/lib/types/remote/load-timing.d.ts +46 -0
- package/lib/types/remote/protocol.d.ts +160 -0
- package/lib/types/remote/review-launch.d.ts +6 -0
- package/lib/types/remote/runtime-entry.d.ts +1 -0
- package/lib/types/remote/runtime.d.ts +14 -0
- package/lib/types/remote/simulator-prompt.d.ts +9 -0
- package/lib/types/remote/widget-snapshot-guest-runtime.d.ts +1 -0
- package/lib/types/remote-client.d.ts +5 -0
- package/lib/types/renderer/base.d.ts +8 -0
- package/lib/types/renderer/content-host/iframe-content-host.d.ts +83 -0
- package/lib/types/renderer/content-host/index.d.ts +3 -0
- package/lib/types/renderer/content-host/types.d.ts +89 -0
- package/lib/types/renderer/content-host/webview-content-host.d.ts +53 -0
- package/lib/types/renderer/iframe.d.ts +93 -0
- package/lib/types/renderer/index.d.ts +2 -0
- package/lib/types/renderer/rednote-shell.d.ts +73 -0
- package/lib/types/renderer/webview.d.ts +59 -0
- package/lib/types/runtime/context.d.ts +31 -0
- package/lib/types/runtime/jsapi-modules/context.d.ts +19 -0
- package/lib/types/runtime/jsapi-modules/filesystem.d.ts +19 -0
- package/lib/types/runtime/jsapi-modules/index.d.ts +9 -0
- package/lib/types/runtime/jsapi-modules/interaction.d.ts +4 -0
- package/lib/types/runtime/jsapi-modules/location.d.ts +3 -0
- package/lib/types/runtime/jsapi-modules/media.d.ts +13 -0
- package/lib/types/runtime/jsapi-modules/network.d.ts +3 -0
- package/lib/types/runtime/jsapi-modules/storage.d.ts +26 -0
- package/lib/types/runtime/jsapi-modules/system.d.ts +4 -0
- package/lib/types/runtime/jsapi-modules/types.d.ts +21 -0
- package/lib/types/runtime/jsapi-modules/window-info.d.ts +43 -0
- package/lib/types/runtime/request/host-request.d.ts +13 -0
- package/lib/types/runtime/request/request-manager-frame.d.ts +29 -0
- package/lib/types/runtime/request/request-runtime.d.ts +26 -0
- package/lib/types/runtime/request/request-types.d.ts +26 -0
- package/lib/types/runtime/request/sse-text-framer.d.ts +16 -0
- package/lib/types/seal-config.d.ts +134 -0
- package/lib/types/sw/index.d.ts +9 -0
- package/lib/types/sw/parse-raw.d.ts +34 -0
- package/lib/types/sw/protocol.d.ts +17 -0
- package/lib/types/sw/served-entry.d.ts +9 -0
- package/lib/types/sw/service-worker-content-host.d.ts +11 -0
- package/lib/types/sw/service-worker-host.d.ts +73 -0
- package/lib/types/sw/service-worker-renderer.d.ts +10 -0
- package/lib/types/sw/worker/fs-codec.d.ts +23 -0
- package/lib/types/sw/worker/fs-ops.d.ts +22 -0
- package/lib/types/sw/worker/fs-store.d.ts +29 -0
- package/lib/types/sw/worker/globals.d.ts +49 -0
- package/lib/types/sw/worker/main.d.ts +6 -0
- package/lib/types/sw/worker/mime.d.ts +2 -0
- package/lib/types/sw/worker/mount-store.d.ts +43 -0
- package/lib/types/sw/worker/paths.d.ts +4 -0
- package/lib/types/sw/worker/serve.d.ts +13 -0
- package/lib/types/tracker/constants.d.ts +14 -0
- package/lib/types/tracker/default-tracker.d.ts +19 -0
- package/lib/types/tracker/index.d.ts +70 -0
- package/lib/types/transport/bridge-protocol.d.ts +78 -0
- package/lib/types/transport/iframe-transport.d.ts +39 -0
- package/lib/types/transport/index.d.ts +14 -0
- package/lib/types/transport/jsapi-bridge-messages.d.ts +36 -0
- package/lib/types/transport/types.d.ts +48 -0
- package/lib/types/transport/webview-transport.d.ts +52 -0
- package/lib/types/types/events.d.ts +130 -0
- package/lib/types/types/index.d.ts +11 -0
- package/lib/types/types/inspector.d.ts +172 -0
- package/lib/types/types/jsapi.d.ts +18 -0
- package/lib/types/types/options.d.ts +844 -0
- package/lib/types/types/renderer.d.ts +145 -0
- package/lib/types/utils/ancestor-scroll.d.ts +11 -0
- package/lib/types/utils/error-svg.d.ts +12 -0
- package/lib/types/utils/frameless-shell.d.ts +114 -0
- package/lib/types/utils/miniapp-chrome-svg.d.ts +47 -0
- package/lib/types/utils/package-constants.d.ts +8 -0
- package/lib/types/utils/screenshot.d.ts +14 -0
- package/lib/types/utils/simulator-pc-guard.d.ts +10 -0
- package/lib/types/utils/stage-fit.d.ts +6 -0
- package/lib/types/utils/touch-emulate.d.ts +26 -0
- package/lib/types/utils/zip-entry.d.ts +13 -0
- package/lib/types/workbench/index.d.ts +63 -0
- package/lib/types/workbench/preview-transition.d.ts +8 -0
- package/lib/types/workbench/server/artifact.d.ts +8 -0
- package/lib/types/workbench/server/index.d.ts +19 -0
- package/lib/types/workbench/server/watch.d.ts +6 -0
- package/lib/types/workbench/view.d.ts +36 -0
- package/lib/workbench-server.mjs +183 -0
- package/lib/workbench.js +1404 -0
- package/package.json +63 -0
- package/scripts/mock-cli-dev.mjs +52 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
# Miniapp Simulator 远程模式架构
|
|
2
|
+
|
|
3
|
+
## 1. 结论
|
|
4
|
+
|
|
5
|
+
远程模式把模拟器拆成四个独立层次:
|
|
6
|
+
|
|
7
|
+
1. **宿主侧薄 SDK**:创建跨域 iframe,解析兼容版本,维护 MessageChannel、宿主 Host API 和异常恢复。
|
|
8
|
+
2. **Simulator Server**:提供版本选择、Bootstrap HTML、同源 Service Worker 入口以及 Apollo 动态策略。
|
|
9
|
+
3. **CDN Runtime / Service Worker**:承载可热更新的模拟器实现和虚拟文件系统实现。
|
|
10
|
+
4. **小应用运行 iframe**:从 Service Worker 提供的同源虚拟 URL 加载 ZIP 内的原始文件。
|
|
11
|
+
|
|
12
|
+
Node 服务是控制面,不负责 SSR、不上传 ZIP、不解压业务包,也不转发大体积静态资源。Runtime 和
|
|
13
|
+
Service Worker 使用内容 Hash 发布到 CDN;Node 服务只负责把一个确定的 release 组装成可加载页面。
|
|
14
|
+
|
|
15
|
+
## 2. 为什么采用远程模式
|
|
16
|
+
|
|
17
|
+
### 2.1 Web Service Worker 必须与运行页面同源
|
|
18
|
+
|
|
19
|
+
离线 ZIP 需要保留真实 URL 语义,才能正确支持:
|
|
20
|
+
|
|
21
|
+
- 相对路径和 `<base>`;
|
|
22
|
+
- ESM 静态、动态 `import()`;
|
|
23
|
+
- `fetch()`、`import.meta.url`、Worker;
|
|
24
|
+
- 图片、字体、音视频等子资源;
|
|
25
|
+
- 模拟文件系统 URL。
|
|
26
|
+
|
|
27
|
+
Service Worker 适合把 ZIP 文件表映射成一个虚拟 HTTP 文件系统,但浏览器不允许从任意 CDN URL
|
|
28
|
+
直接注册跨域 Worker。远程 Runtime 页面和 `/releases/:buildId/sw.js` 都位于 Simulator origin,
|
|
29
|
+
因此可以注册同源、版本化 scope 的 Service Worker。
|
|
30
|
+
|
|
31
|
+
### 2.2 模拟器不能依赖每个宿主自行部署资源
|
|
32
|
+
|
|
33
|
+
如果 Runtime、HTML 和 Service Worker 都由接入平台复制部署,会产生以下问题:
|
|
34
|
+
|
|
35
|
+
- 每个平台都要配置并维护 SW 路径和 scope;
|
|
36
|
+
- 模拟器升级要求所有平台同步升级 npm 包和静态文件;
|
|
37
|
+
- HTML、Runtime、SW 分批发布时容易出现版本错配;
|
|
38
|
+
- CSP、安全脚本、JSAPI 和 UI 修复无法统一生效。
|
|
39
|
+
|
|
40
|
+
远程模式只要求宿主保留一个薄 SDK 和 Simulator 服务地址。大部分模拟器能力通过切换远端 release
|
|
41
|
+
更新,接入平台无需重新发版。
|
|
42
|
+
|
|
43
|
+
### 2.3 小应用应与宿主形成独立 origin 边界
|
|
44
|
+
|
|
45
|
+
宿主只加载 Simulator origin 的外层 iframe,小应用代码在该 origin 下的内层 iframe 运行,不会获得
|
|
46
|
+
宿主页面 DOM、Storage 和 JS Realm。Simulator origin 必须是专属、无敏感 Cookie、无敏感业务接口的
|
|
47
|
+
运行域名。
|
|
48
|
+
|
|
49
|
+
跨 origin 不等于一定跨进程。Chromium 主要按 site 执行 Site Isolation;
|
|
50
|
+
`creator.xiaohongshu.com` 和 `miniapp-sandbox.xiaohongshu.com` 属于同一个 site。
|
|
51
|
+
`Origin-Agent-Cluster: ?1` 可以申请 origin-keyed agent cluster,但不能承诺独立 Renderer 进程。
|
|
52
|
+
需要确定的逐实例进程隔离、完整内存统计和崩溃回收时,应使用 Electron 独立 `webContents`;Web 模式
|
|
53
|
+
若要获得更强的 OOPIF 进程隔离,应使用不同可注册域名的 Simulator origin。
|
|
54
|
+
|
|
55
|
+
### 2.4 ZIP 不应经过 Node 服务
|
|
56
|
+
|
|
57
|
+
ZIP 已经在宿主浏览器中。将其上传给 Node 再下载回来会引入额外带宽、存储、鉴权、隐私和清理成本。
|
|
58
|
+
当前实现通过 MessageChannel 把 ArrayBuffer 直接传给远端 Runtime,由 Runtime 在浏览器内解压并挂载
|
|
59
|
+
给 Service Worker。Node 不接触小应用包内容。
|
|
60
|
+
|
|
61
|
+
## 3. 总体架构
|
|
62
|
+
|
|
63
|
+
```mermaid
|
|
64
|
+
flowchart LR
|
|
65
|
+
Host[业务宿主页面] -->|createRemoteMiniAppSimulator| SDK[薄 SDK]
|
|
66
|
+
SDK -->|GET /simulator/runtime-manifest| Server[Simulator Server]
|
|
67
|
+
Server --> Apollo[Apollo 配置]
|
|
68
|
+
SDK -->|跨域 iframe documentUrl| Bootstrap[版本化 Bootstrap HTML]
|
|
69
|
+
Bootstrap -->|ES Module + CORS| Runtime[CDN Runtime]
|
|
70
|
+
Runtime <-->|MessageChannel RPC| SDK
|
|
71
|
+
Runtime -->|POST /simulator/runtime-config| Server
|
|
72
|
+
Runtime --> Core[模拟器 Core]
|
|
73
|
+
Runtime -->|注册同源 bootstrap| SWBootstrap["/releases/:buildId/sw.js"]
|
|
74
|
+
SWBootstrap -->|ES Module + CORS| SW[CDN Service Worker]
|
|
75
|
+
SDK -->|ZIP ArrayBuffer| Runtime
|
|
76
|
+
Runtime -->|解压文件表 MOUNT| SW
|
|
77
|
+
SW -->|虚拟 URL 响应| Guest[小应用 iframe]
|
|
78
|
+
Guest -->|JSAPI / 手势 / 心跳 / 事件| Runtime
|
|
79
|
+
Runtime -->|事件与 Host API RPC| SDK
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 各层职责
|
|
83
|
+
|
|
84
|
+
| 层 | 主要职责 | 发布方式 |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| 业务宿主 | 提供 mount、appId、businessLine、用户身份和自定义 Host API | 业务平台发布 |
|
|
87
|
+
| 薄 SDK | 服务发现、协议握手、外层 iframe、MessageChannel、宿主 RPC、心跳判断与恢复 UI | npm 包 |
|
|
88
|
+
| Simulator Server | release 选择、Bootstrap HTML、同源 SW bootstrap、Apollo 策略 | Node 镜像 |
|
|
89
|
+
| Runtime | 模拟器 UI/Core、ZIP 解压、JSAPI、安全注入、CSP 应用、打点、Inspector | CDN Hash 资源 |
|
|
90
|
+
| Service Worker | ZIP 文件挂载、虚拟 URL、HTML head 注入、CSP 响应头、FS 能力 | CDN Hash 资源 |
|
|
91
|
+
| 小应用 iframe | 执行用户代码并使用真实 URL 加载包内资源 | ZIP 内容 |
|
|
92
|
+
|
|
93
|
+
## 4. 完整加载链路
|
|
94
|
+
|
|
95
|
+
```mermaid
|
|
96
|
+
sequenceDiagram
|
|
97
|
+
participant H as 宿主薄 SDK
|
|
98
|
+
participant S as Simulator Server
|
|
99
|
+
participant R as 远端 Runtime iframe
|
|
100
|
+
participant W as Service Worker
|
|
101
|
+
participant A as 小应用 iframe
|
|
102
|
+
|
|
103
|
+
H->>S: GET /simulator/runtime-manifest?protocolVersion=6
|
|
104
|
+
S-->>H: buildId + documentUrl + protocolVersion
|
|
105
|
+
H->>R: 加载 /simulator/releases/:buildId
|
|
106
|
+
R->>R: 从 CDN import runtime.[hash].js
|
|
107
|
+
H->>R: postMessage CONNECT + MessagePort
|
|
108
|
+
R->>S: POST /simulator/runtime-config
|
|
109
|
+
S-->>R: CSP + runtime limits + feature config
|
|
110
|
+
R->>W: 注册 /releases/:buildId/sw.js
|
|
111
|
+
W->>W: 从 CDN import sw.[hash].js
|
|
112
|
+
R-->>H: READY + protocolVersion + capabilities
|
|
113
|
+
H->>R: loadZip(ArrayBuffer)
|
|
114
|
+
R->>R: JSZip 解压并校验文件
|
|
115
|
+
R->>W: MOUNT(mountId, files, injectHead, CSP)
|
|
116
|
+
W-->>R: MOUNT_ACK
|
|
117
|
+
R->>A: 加载 /releases/:buildId/app/:mountId/index.html
|
|
118
|
+
A->>W: 请求 HTML / JS / CSS / 图片等资源
|
|
119
|
+
W-->>A: 返回 ZIP 内资源
|
|
120
|
+
A-->>R: renderDone / JSAPI / console
|
|
121
|
+
R-->>H: Event / Response / Host API Request
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
关键点:
|
|
125
|
+
|
|
126
|
+
- 薄 SDK 请求 `/runtime-manifest` 时固定携带自身的 `protocolVersion`。
|
|
127
|
+
- 外层 iframe 加载的是版本化 `documentUrl`,一次会话固定到一个 buildId,不会在运行中漂移。
|
|
128
|
+
- 初始 `window.postMessage` 只用于传递专属 MessagePort;后续业务 RPC 走 MessageChannel。
|
|
129
|
+
- `loadZip` 的 ArrayBuffer 和文件 ArrayBuffer 使用 transferable 传输,避免无意义复制。
|
|
130
|
+
- 每次挂载使用随机 mountId;虚拟路径和 SW 存储按 mountId 隔离。
|
|
131
|
+
|
|
132
|
+
## 5. 发布和版本选择
|
|
133
|
+
|
|
134
|
+
### 5.1 Release 结构
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{
|
|
138
|
+
"activeRuntimeByProtocol": {
|
|
139
|
+
"2": "v0.1.7-<runtime-hash>-<sw-hash>"
|
|
140
|
+
},
|
|
141
|
+
"releases": {
|
|
142
|
+
"v0.1.7-<runtime-hash>-<sw-hash>": {
|
|
143
|
+
"protocolVersion": 2,
|
|
144
|
+
"runtimeUrl": "https://cdn.example.com/runtime.<sha256>.js",
|
|
145
|
+
"serviceWorkerUrl": "https://cdn.example.com/sw.<sha256>.js"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
发布顺序:
|
|
152
|
+
|
|
153
|
+
1. 构建 `runtime.min.js` 和 `miniapp-simulator-service-worker.min.js`。
|
|
154
|
+
2. 计算 SHA-256,以内容 Hash 文件名上传 CDN,并设置一年 `immutable`。
|
|
155
|
+
3. 生成仅描述本次构建的 `dist/release.json`,通知发布群。客户端不请求该文件。
|
|
156
|
+
4. 在 Apollo 当前完整配置中新增 `releases[buildId]`,保留其他 release 和协议映射。
|
|
157
|
+
5. 确认资源可访问后,更新对应协议的 `activeRuntimeByProtocol[protocolVersion]`。
|
|
158
|
+
|
|
159
|
+
回滚只需要把对应协议映射指回仍在 `releases` 中的旧 release。buildId、Runtime URL 和 SW URL 都
|
|
160
|
+
不可复用或覆盖。
|
|
161
|
+
|
|
162
|
+
### 5.2 协议兼容
|
|
163
|
+
|
|
164
|
+
Server 使用 `activeRuntimeByProtocol[protocolVersion]` 精确选择 release;没有对应映射时返回 HTTP
|
|
165
|
+
426,不推断兼容关系,也不依赖 `releases` 的排列顺序。
|
|
166
|
+
|
|
167
|
+
协议版本不隐式向前兼容。发布新协议时,需要在 `list` 中保留旧协议 release,直到所有接入方完成
|
|
168
|
+
薄 SDK 升级。
|
|
169
|
+
|
|
170
|
+
### 5.3 缓存策略
|
|
171
|
+
|
|
172
|
+
| 资源 | 策略 |
|
|
173
|
+
| --- | --- |
|
|
174
|
+
| `/simulator/runtime-manifest` | `no-store` |
|
|
175
|
+
| `/simulator/releases/:buildId` Bootstrap HTML | 一年 `immutable`;内联配置使用 CSP SHA-256 hash |
|
|
176
|
+
| `/simulator/runtime-config`、`/simulator/csp`、`/simulator/performance-policy` | `no-store` |
|
|
177
|
+
| `/simulator/releases/:buildId/sw.js` | 一年 `immutable` |
|
|
178
|
+
| CDN `runtime.<hash>.js`、`sw.<hash>.js` | 一年 `immutable` |
|
|
179
|
+
|
|
180
|
+
Server 启动时先使用代码内置的默认 release catalog,再订阅 Apollo。Apollo 获取失败、配置缺失或配置
|
|
181
|
+
非法时保留默认值或 last-known-good,避免 `/runtime-manifest` 因配置中心短暂不可用而整体失效。
|
|
182
|
+
|
|
183
|
+
## 6. Service Worker 和虚拟文件系统
|
|
184
|
+
|
|
185
|
+
每个 release 使用独立 scope:
|
|
186
|
+
|
|
187
|
+
```text
|
|
188
|
+
/simulator/releases/:buildId/app/
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
同一 release 的多个模拟器共享该 Service Worker,但使用不同 mountId:
|
|
192
|
+
|
|
193
|
+
```text
|
|
194
|
+
/simulator/releases/:buildId/app/:mountId/index.html
|
|
195
|
+
/simulator/releases/:buildId/app/:mountId/assets/app.js
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Service Worker 内存中保存 `mountId -> files` 映射,并负责:
|
|
199
|
+
|
|
200
|
+
- 按原始路径和 MIME 返回 ZIP 文件;
|
|
201
|
+
- 对入口 HTML 注入 JSAPI、安全、手势、Inspector、心跳等脚本;
|
|
202
|
+
- 在 HTML 响应上设置小应用 CSP;
|
|
203
|
+
- 未命中的离线包文件返回 404,避免穿透读取 Simulator 服务真实路径;
|
|
204
|
+
- 提供临时文件等受控 FS 操作;
|
|
205
|
+
- 在 UNMOUNT、页面退出或 Client 消失后回收挂载。
|
|
206
|
+
|
|
207
|
+
单个 release scope 最多并发挂载 16 个实例;达到上限时拒绝新实例,不驱逐正在运行的实例。
|
|
208
|
+
|
|
209
|
+
### 6.1 文件型 JSAPI 的实现约束
|
|
210
|
+
|
|
211
|
+
`writeTempFile` 以及后续保存、读取、删除文件等返回文件路径的 JSAPI,必须通过 Service Worker
|
|
212
|
+
文件系统实现。端上的 `file://` 或 `xhsfile://` 路径不能直接作为浏览器 iframe 的资源地址;远程
|
|
213
|
+
模拟器需要把它们映射为同源 HTTP(S) 虚拟路径:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
/simulator/releases/:buildId/app/_xhsfile_/:fsScope/:path
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
实现新文件能力时必须同时完成:
|
|
220
|
+
|
|
221
|
+
1. 在 `src/sw/protocol.ts` 增加明确的 `fs*` operation;
|
|
222
|
+
2. 在 `src/sw/worker/` 完成数据存取、路径校验和 `fetch` 拦截;
|
|
223
|
+
3. 在 `ServiceWorkerHost` 通过 `fsInvoke` 调用,不在 Runtime 主线程生成不可访问的伪文件 URL;
|
|
224
|
+
4. 返回可直接用于 `<img src>`、`<video src>` 或 `fetch()` 的同源虚拟 URL;
|
|
225
|
+
5. 补充 Worker 重启后的恢复测试、路径越权测试和 MIME 测试。
|
|
226
|
+
|
|
227
|
+
SW 的 mount 表属于内存状态,浏览器可能随时回收 Worker。`fsInvoke` 收到
|
|
228
|
+
`ERR_NOT_MOUNTED` 时会使用 Host 保存的文件快照恢复 mount,并且只重试一次;持久文件仍由
|
|
229
|
+
IndexedDB 保存,虚拟 URL 在 Worker 重启后可以继续读取。
|
|
230
|
+
|
|
231
|
+
## 7. Apollo 动态配置
|
|
232
|
+
|
|
233
|
+
Runtime 在每次建立连接时使用以下上下文请求一次聚合配置:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"appId": "miniapp-id",
|
|
238
|
+
"userId": "current-user-id",
|
|
239
|
+
"businessLine": "creator"
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`businessLine` 是薄 SDK 必填参数,没有默认值。Server 返回 `csp`、`performance`、`jsapi` 三个独立
|
|
244
|
+
配置块;聚合只减少请求数量,不会把不同配置项合并成一个 Apollo Key:
|
|
245
|
+
|
|
246
|
+
| Apollo Key | 聚合响应字段 | 解释方 |
|
|
247
|
+
| --- | --- | --- |
|
|
248
|
+
| `miniappSimulatorCspPolicies` | `csp` | Runtime CSP 转换逻辑 |
|
|
249
|
+
| `miniappSimulatorPerformancePolicies` | `performance` | Runtime 资源保护逻辑 |
|
|
250
|
+
| `miniappSimulatorJsApiPolicies` | `jsapi` | Runtime JSAPI 路由逻辑 |
|
|
251
|
+
|
|
252
|
+
三个 Apollo Key 都采用相同的规则数组结构:
|
|
253
|
+
|
|
254
|
+
```json
|
|
255
|
+
[
|
|
256
|
+
{
|
|
257
|
+
"scope": {
|
|
258
|
+
"appIds": [],
|
|
259
|
+
"userIds": [],
|
|
260
|
+
"businessLines": ["creator"]
|
|
261
|
+
},
|
|
262
|
+
"strategy": {}
|
|
263
|
+
}
|
|
264
|
+
]
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
- `appIds`、`userIds`、`businessLines` 中任一非空维度命中即命中该规则。
|
|
268
|
+
- 三个数组都为空时规则不生效。
|
|
269
|
+
- 多条规则命中时按数组顺序深合并;对象递归合并,数组和标量由后面的规则替换。
|
|
270
|
+
- Server 只校验 scope、JSON 值和合并规则,不识别 directive、阈值、JSAPI 名称等业务字段。
|
|
271
|
+
- 配置在新建 Runtime 连接时读取;已连接实例不会因 Apollo 推送自动改变行为。
|
|
272
|
+
|
|
273
|
+
### Release
|
|
274
|
+
|
|
275
|
+
`miniappSimulatorRuntimeManifest` 通过 `activeRuntimeByProtocol + releases` 控制新版薄层 SDK 的发布、
|
|
276
|
+
回滚和协议隔离。`miniappSimulatorReleases` 仅服务废弃的 `/version` 接口。
|
|
277
|
+
|
|
278
|
+
### 小应用 CSP
|
|
279
|
+
|
|
280
|
+
`miniappSimulatorCspPolicies` 按 `appIds`、`userIds`、`businessLines` 匹配小应用 CSP。三个维度采用 OR
|
|
281
|
+
匹配;空 scope 不生效;多条命中规则按顺序覆盖。配置只影响用户代码能力,不控制 Runtime 自身 CSP。
|
|
282
|
+
|
|
283
|
+
### 性能保护
|
|
284
|
+
|
|
285
|
+
`miniappSimulatorPerformancePolicies` 按相同 scope 规则下发:
|
|
286
|
+
|
|
287
|
+
- `maxHeapUsedBytes`:`performance.memory.usedJSHeapSize` 绝对阈值;
|
|
288
|
+
策略接口允许失败。缺失、超时、非法或未命中时使用 Runtime 代码默认值:JS Heap 1 GiB。
|
|
289
|
+
Web 页面无法稳定读取单个 iframe 的完整 Renderer/DOM/GPU 内存,因此该内存阈值只是 JS Heap
|
|
290
|
+
兜底;完整进程内存管控属于 Electron 能力。
|
|
291
|
+
|
|
292
|
+
### JSAPI 配置与聚合接口
|
|
293
|
+
|
|
294
|
+
`miniappSimulatorJsApiPolicies` 是独立配置项。CSP、性能和 JSAPI 配置共用 Server 的 scope 匹配与
|
|
295
|
+
JSON 合并逻辑;Server 不解析 directive、阈值、JSAPI 名称或返回契约,这些语义由远端 Runtime 解释。
|
|
296
|
+
`jsapi.unsupported` 配置明确不支持或没有 handler 的 JSAPI 的统一提示;它不会覆盖已有实现。同级 API
|
|
297
|
+
名称可精确覆盖任意 API,例如 `postNote: { alert: "审核员注意,他要发笔记了" }`。提示支持手机框内
|
|
298
|
+
Toast 和浏览器原生 Alert;同一项同时配置两者时 Alert 优先。精确覆盖只负责提示并成功返回空对象,
|
|
299
|
+
不会合成 API 专属返回字段。宿主显式提供的同名 `hostApi` 优先级最高。
|
|
300
|
+
|
|
301
|
+
Runtime 初始化只请求 `/simulator/runtime-config`,响应聚合各个独立配置项。旧 `/simulator/csp`、
|
|
302
|
+
`/simulator/performance-policy` 接口继续服务已发布 Runtime;新增配置聚合到同一接口,不新增请求。
|
|
303
|
+
|
|
304
|
+
JSAPI 行为优先级:宿主显式 `hostApi` → 单 API 远端配置 → `unsupported` 统一配置 → Runtime 默认行为。
|
|
305
|
+
|
|
306
|
+
## 8. 哪些能力可以远程更新
|
|
307
|
+
|
|
308
|
+
只要不改变薄 SDK 与 Runtime 的 wire protocol,以下能力都可以通过发布新 Runtime/SW 或修改 Apollo
|
|
309
|
+
更新:
|
|
310
|
+
|
|
311
|
+
- 模拟器 UI、手机壳、Permission Sheet、Note Preview;
|
|
312
|
+
- JSAPI、默认 Host API 行为、业务线默认行为;
|
|
313
|
+
- 手势、Inspector、截图和打点逻辑;
|
|
314
|
+
- ZIP 解析、文件限制、HTML 注入和虚拟文件系统;
|
|
315
|
+
- 小应用安全脚本和可配置 CSP;
|
|
316
|
+
- 性能阈值与心跳超时;
|
|
317
|
+
- Bug 修复和兼容性逻辑。
|
|
318
|
+
|
|
319
|
+
以下变化仍要求业务方升级薄 SDK:
|
|
320
|
+
|
|
321
|
+
- 新增或破坏性修改宿主公开 API;
|
|
322
|
+
- 修改 MessageChannel wire protocol;
|
|
323
|
+
- 修改外层 iframe 创建方式、`allow` 或宿主侧恢复 UI;
|
|
324
|
+
- 修改服务发现、备用服务和 `/runtime-manifest` 协议;
|
|
325
|
+
- 修改必须在宿主 JS Realm 执行的 Host API 适配逻辑。
|
|
326
|
+
|
|
327
|
+
因此薄 SDK 的目标是稳定,不是零代码。Runtime/SW 承载高频变化,薄 SDK 只承载宿主必须拥有的能力。
|
|
328
|
+
|
|
329
|
+
## 9. 多实例模型
|
|
330
|
+
|
|
331
|
+
同一宿主页面可以创建多个远程模拟器:
|
|
332
|
+
|
|
333
|
+
- 每次 `createRemoteMiniAppSimulator()` 创建独立外层 iframe;
|
|
334
|
+
- 每个实例拥有独立 sessionId、MessageChannel、RPC pending 表和 Host API Map;
|
|
335
|
+
- 每个小应用挂载使用独立 mountId;
|
|
336
|
+
- `destroy()` 关闭 Port、移除 iframe,并触发 SW UNMOUNT。
|
|
337
|
+
|
|
338
|
+
多实例的数据和协议状态相互隔离,但不代表操作系统进程和内存相互隔离。同 origin Runtime 可能共享
|
|
339
|
+
Renderer/V8 isolate,`performance.memory` 也可能是聚合值。要求逐实例硬内存配额时使用 Electron。
|
|
340
|
+
|
|
341
|
+
## 10. 安全与接入约束
|
|
342
|
+
|
|
343
|
+
### Simulator origin
|
|
344
|
+
|
|
345
|
+
- 必须使用 HTTPS。
|
|
346
|
+
- 必须是专属运行 origin,不承载敏感页面和敏感接口。
|
|
347
|
+
- 不应下发可被前端读取的登录 Cookie,尤其是 `.xiaohongshu.com` Domain Cookie。
|
|
348
|
+
- Runtime、SW CDN 资源需要正确 CORS。
|
|
349
|
+
- 网关不能附加 `X-Frame-Options: SAMEORIGIN`。
|
|
350
|
+
|
|
351
|
+
### 宿主页面
|
|
352
|
+
|
|
353
|
+
宿主 CSP 至少需要:
|
|
354
|
+
|
|
355
|
+
```text
|
|
356
|
+
connect-src ... https://<simulator-origin>
|
|
357
|
+
frame-src ... https://<simulator-origin>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
薄 SDK 支持任意 HTTPS 宿主,通过 `serviceUrl` 选择环境,不在 SDK 内写死宿主域名。
|
|
361
|
+
|
|
362
|
+
### 小应用执行边界
|
|
363
|
+
|
|
364
|
+
小应用 iframe 默认包含 `allow-scripts` 和 `allow-same-origin`,以支持 SW 虚拟 URL、Bridge 和浏览器
|
|
365
|
+
原生模块能力。因此不能把 Simulator origin 当成可信业务 origin。CSP、iframe sandbox 和能力封印是
|
|
366
|
+
模拟器约束用户代码的防线,不是服务端身份鉴权机制。
|
|
367
|
+
|
|
368
|
+
## 11. 故障与降级
|
|
369
|
+
|
|
370
|
+
| 故障 | 行为 |
|
|
371
|
+
| --- | --- |
|
|
372
|
+
| Simulator 服务 `/runtime-manifest` 短暂不可用 | 依次尝试主、备用服务;网络错误和最终非 2xx 响应等待 100ms 后重试一轮 |
|
|
373
|
+
| Apollo release 暂时不可用 | 使用内置默认 catalog 或 last-known-good |
|
|
374
|
+
| CSP/性能策略接口失败 | 使用 Runtime 内置默认配置,继续加载 |
|
|
375
|
+
| CDN Runtime/SW 不可用 | 当前 release 加载失败,宿主收到 error |
|
|
376
|
+
| 小应用 JS Heap 超限 | 终止内层 iframe并展示恢复提示 |
|
|
377
|
+
| 小应用长期无心跳 | 薄 SDK 展示恢复提示,由用户确认重新启动 |
|
|
378
|
+
| SW 被回收或外部注销 | Runtime 重新注册并按快照恢复 MOUNT |
|
|
379
|
+
| 协议不兼容 | `/runtime-manifest` 没有对应协议映射并返回 426 |
|
|
380
|
+
|
|
381
|
+
manifest 请求超时由网关控制,Client 不设置额外超时。Runtime 的整体 ready 超时从 manifest 成功后
|
|
382
|
+
开始计算,避免服务发现耗时挤占 Runtime HTML、脚本和握手时间。HTTP 最终非 2xx 响应统一重试一次;
|
|
383
|
+
2xx 响应中的协议不匹配、响应结构非法和 document origin 不匹配不重试同一地址,但仍会尝试
|
|
384
|
+
独立备用服务。
|
|
385
|
+
|
|
386
|
+
薄 SDK 不缓存 `documentUrl`。Simulator 页面、同源 SW bootstrap 和策略接口都依赖 Simulator Server;
|
|
387
|
+
仅缓存一个旧 URL不能解决服务整体不可用,还可能命中已移除 release。高可用通过独立部署的备用
|
|
388
|
+
Simulator 服务解决。
|
|
389
|
+
|
|
390
|
+
## 12. 关键代码入口
|
|
391
|
+
|
|
392
|
+
- 在线使用指南:[远程模拟器接入与使用指南](https://docs.xiaohongshu.com/doc/ab55a921fdd880f1876663c6db544d2a)
|
|
393
|
+
- 本地使用指南:`packages/miniapp-simulator/docs/remote-usage.md`
|
|
394
|
+
- 薄 SDK:`packages/miniapp-simulator/src/remote/client.ts`
|
|
395
|
+
- Wire protocol:`packages/miniapp-simulator/src/remote/protocol.ts`
|
|
396
|
+
- 远端 Runtime:`packages/miniapp-simulator/src/remote/runtime.ts`
|
|
397
|
+
- Service Worker Host:`packages/miniapp-simulator/src/sw/service-worker-host.ts`
|
|
398
|
+
- Service Worker 文件挂载:`packages/miniapp-simulator/src/sw/worker/mount-store.ts`
|
|
399
|
+
- CDN 发布脚本:`packages/miniapp-simulator/scripts/publish-assets.mjs`
|
|
400
|
+
- Server Controller:`apps/miniapp-simulator-server/src/app/controller/simulator.controller.ts`
|
|
401
|
+
- Apollo/Release Service:`apps/miniapp-simulator-server/src/app/services/simulator-release.service.ts`
|
|
402
|
+
- Bootstrap HTML:`apps/miniapp-simulator-server/src/app/presentation/simulator-runtime-document.ts`
|
|
403
|
+
- Server 部署与 Apollo 配置:`apps/miniapp-simulator-server/README.md`
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# 远程模拟器核心加载链路观测方案
|
|
2
|
+
|
|
3
|
+
## 1. 背景与目标
|
|
4
|
+
|
|
5
|
+
审核环境使用远程模拟器后出现加载变慢、页面不可交互等反馈。Beta 环境压测只能验证容量和趋势,
|
|
6
|
+
不能代表线上审核终端、网络、缓存、浏览器和资源命中情况。本方案以线上真实运行数据为准,建立
|
|
7
|
+
从薄层 SDK 创建实例到 ZIP/文件包完成渲染的端到端观测能力。
|
|
8
|
+
|
|
9
|
+
目标:
|
|
10
|
+
|
|
11
|
+
- 区分模拟器平台启动慢、网络慢、包处理慢、Service Worker 慢和 Guest 渲染慢。
|
|
12
|
+
- `loadZip` / `loadFiles` 作为核心业务加载入口,建立成功率、耗时分位和阶段漏斗。
|
|
13
|
+
- 其他远程方法保留通用调用耗时,用于诊断 Runtime 响应,但不计入核心加载指标。
|
|
14
|
+
- 使用同一个会话和请求标识串联 Client、Runtime、Core、Service Worker 与 Guest。
|
|
15
|
+
- 保持远程协议 v6 不变,新 Runtime 可继续接入线上旧 Client。
|
|
16
|
+
- 埋点采集、读取和上报失败时静默降级,不阻塞、不抛错、不改变加载结果。
|
|
17
|
+
|
|
18
|
+
页面不可交互问题先通过现有错误、加载和渲染数据分析,不增加点击行为埋点。
|
|
19
|
+
|
|
20
|
+
## 2. 两条独立链路
|
|
21
|
+
|
|
22
|
+
### 2.1 模拟器平台启动链路
|
|
23
|
+
|
|
24
|
+
这条链路衡量模拟器自身从 Client 创建到 Runtime 可调用的耗时:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
Client 创建
|
|
28
|
+
→ runtime manifest
|
|
29
|
+
→ Runtime Bootstrap HTML
|
|
30
|
+
→ Runtime JS 下载与执行
|
|
31
|
+
→ Runtime 动态配置
|
|
32
|
+
→ Core 实例创建
|
|
33
|
+
→ MessageChannel 握手
|
|
34
|
+
→ Client ready
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
当前 Runtime 和 Service Worker 均为单文件 bundle,不存在 Runtime 动态 chunk 或独立 CSS 请求。
|
|
38
|
+
模拟器自身关键资源包括:
|
|
39
|
+
|
|
40
|
+
- `runtime-manifest`:选择与协议 v6 匹配的 Runtime release。
|
|
41
|
+
- Bootstrap HTML:创建 Runtime 页面并注入版本化资源地址。
|
|
42
|
+
- Runtime JS:模拟器 Runtime、Core 及依赖的单文件 bundle。
|
|
43
|
+
- `runtime-config`:按 app、用户和业务线获取运行策略。
|
|
44
|
+
- SW bootstrap 与 CDN SW 模块:首次 `loadZip` / `loadFiles` 时注册、安装并激活。
|
|
45
|
+
- Request Manager:Guest 首次调用公共网络 API 时懒加载,不属于 Runtime 首次 ready 的固定路径。
|
|
46
|
+
|
|
47
|
+
### 2.2 应用包加载链路
|
|
48
|
+
|
|
49
|
+
这条链路衡量一次 `loadZip` 或 `loadFiles` 从 Client 输入到 Guest 可见的耗时:
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
Client Blob/File 物化
|
|
53
|
+
→ MessageChannel 请求
|
|
54
|
+
→ Runtime 请求处理
|
|
55
|
+
→ ZIP/文件表解析
|
|
56
|
+
→ SW 注册与激活
|
|
57
|
+
→ 注入内容与 CSP 构建
|
|
58
|
+
→ 文件表 MOUNT 与 ACK
|
|
59
|
+
→ Guest 文档导航
|
|
60
|
+
→ Guest 资源瀑布
|
|
61
|
+
→ DOM ready / first paint / render done
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
审核场景以“开始审核”作为系统加载边界:`review_wait` 记录 ZIP 解析完成到审核员开始审核的
|
|
65
|
+
人工等待,`review_app_load` 记录开始审核到 Core `loadFiles` 完成。二者不采集点击目标、坐标或
|
|
66
|
+
点击成功率,也不用于判断页面是否可点击。
|
|
67
|
+
|
|
68
|
+
## 3. 链路关联模型
|
|
69
|
+
|
|
70
|
+
统一事件名:
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
simulator_load_stage
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
关联字段:
|
|
77
|
+
|
|
78
|
+
| 字段 | 含义 | 使用范围 |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `session_id` | 一次 Client 与 Runtime 连接 | 平台启动、所有远程请求、Core 与 Guest |
|
|
81
|
+
| `request_id` | 一次远程请求 | `loadZip` / `loadFiles` 的 Client、Runtime、Core 与 Guest 阶段 |
|
|
82
|
+
| `type` | 方法或资源类型 | `loadZip`、`loadFiles`、其他远程方法、资源分类 |
|
|
83
|
+
| `stage` | 稳定的低基数阶段名 | 所有统一加载点位 |
|
|
84
|
+
|
|
85
|
+
`session_id` 和 `request_id` 直接复用协议 v6 已有的 `sessionId`、`requestId`,不增加协议字段。
|
|
86
|
+
新 Runtime 从旧 Client 的现有请求消息中也能获得这两个标识。
|
|
87
|
+
|
|
88
|
+
## 4. 阶段定义
|
|
89
|
+
|
|
90
|
+
### 4.1 平台启动
|
|
91
|
+
|
|
92
|
+
| stage | 生产者 | duration 口径 | 诊断目标 |
|
|
93
|
+
| --- | --- | --- | --- |
|
|
94
|
+
| `runtime_manifest` | Client | manifest 请求端到端 | 服务发现、主备服务、网络 |
|
|
95
|
+
| `runtime_manifest_download` | Client | responseStart 到 responseEnd | manifest 响应体下载 |
|
|
96
|
+
| `runtime_document` | Client | iframe 赋值到 load | HTML、Runtime JS 下载和执行的外层总耗时 |
|
|
97
|
+
| `runtime_document_download` | Client | responseStart 到 responseEnd | Bootstrap HTML 下载 |
|
|
98
|
+
| `runtime_bootstrap` | Runtime | navigationStart 到 Runtime 初始化 | 页面导航、模块执行和 DOM 初始化 |
|
|
99
|
+
| `runtime_script` | Runtime | Resource Timing duration | Runtime 单文件 bundle 网络耗时 |
|
|
100
|
+
| `runtime_script_download` | Runtime | responseStart 到 responseEnd | Runtime bundle 响应体下载 |
|
|
101
|
+
| `runtime_config` | Runtime | 配置请求端到端 | 动态策略服务与网络 |
|
|
102
|
+
| `runtime_config_download` | Runtime | responseStart 到 responseEnd | 配置响应体下载 |
|
|
103
|
+
| `simulator_create` | Runtime | Core 实例创建 | Runtime/Core 初始化 CPU 耗时 |
|
|
104
|
+
| `runtime_ready` | Runtime | 收到 connect 到发送 ready | Runtime 连接准备 |
|
|
105
|
+
| `runtime_handshake` | Client | 发送 connect 到收到 ready | 跨 iframe 握手 |
|
|
106
|
+
| `client_ready` | Client | 创建实例到 ready | 平台启动总耗时 |
|
|
107
|
+
|
|
108
|
+
网络阶段同时携带 `network_duration`、`dns_duration`、`connect_duration`、
|
|
109
|
+
`ttfb_duration` 和 `bytes`。响应体下载使用对应 `_download` stage 的通用 `duration`。
|
|
110
|
+
`runtime_manifest` 的 `count` 表示当前服务的第几次尝试:Client 先依次尝试主、备用服务,网络错误和
|
|
111
|
+
最终非 2xx 响应等待 100ms 后重试一轮。请求超时由网关控制;2xx 响应中的确定性协议和安全错误不重试
|
|
112
|
+
同一地址。
|
|
113
|
+
|
|
114
|
+
### 4.2 核心包加载
|
|
115
|
+
|
|
116
|
+
| stage / event | 生产者 | duration 口径 | 诊断目标 |
|
|
117
|
+
| --- | --- | --- | --- |
|
|
118
|
+
| `package_materialize` | Client | Blob/File 到可传输 ArrayBuffer | Client 文件读取与拷贝 |
|
|
119
|
+
| `remote_request` | Client | 发出请求到收到响应 | 所有远程方法的外层总耗时 |
|
|
120
|
+
| `runtime_request` | Runtime | 收到请求到返回响应 | `loadZip` / `loadFiles` 的 Runtime 处理耗时 |
|
|
121
|
+
| `zip_parse` | Runtime | ZIP 解压与文件清单解析 | 审核 ZIP 解析 |
|
|
122
|
+
| `simulator_parse_done` | Core | ZIP/文件表解析 | 通用包解析 |
|
|
123
|
+
| `simulator_sw_register` | Core | SW 注册、更新、安装与激活 | SW bootstrap、CDN SW 模块和浏览器 Runtime |
|
|
124
|
+
| `injection_build` | Core | 注入脚本与 CSP 构建 | CPU 与字符串处理 |
|
|
125
|
+
| `simulator_sw_mount` | Core | 文件表传输到 SW 并收到 ACK | 文件量、包体和 SW 通信 |
|
|
126
|
+
| `renderer_setup` | Core | Renderer 创建到开始 Guest 导航 | 渲染容器准备 |
|
|
127
|
+
| `guest_document` | Runtime | Guest 导航到 iframe load | Guest HTML 与阻塞资源 |
|
|
128
|
+
| `guest_resources` | Runtime | 首个资源开始到最后资源结束 | Guest 资源瀑布,并附资源数和传输体积 |
|
|
129
|
+
| `guest_dom_ready` | Runtime | Guest navigationStart 到 DOMContentLoaded | DOM 构建与阻塞脚本 |
|
|
130
|
+
| `guest_script_execution` | Runtime | responseEnd 到 DOMContentLoaded | Guest 同步脚本执行 |
|
|
131
|
+
| `guest_first_paint` | Runtime | Guest navigationStart 到首次绘制 | 首屏可见时间 |
|
|
132
|
+
| `guest_render` | Runtime | Guest 导航到业务 render-done | 业务渲染完成 |
|
|
133
|
+
| `guest_error` | Runtime | 不适用 | Guest 加载错误 |
|
|
134
|
+
|
|
135
|
+
`remote_request` 上报所有远程方法。核心看板固定过滤:
|
|
136
|
+
|
|
137
|
+
```text
|
|
138
|
+
type IN ("loadZip", "loadFiles")
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`load`、`loadApp`、`reload` 和交互类方法不进入核心包加载漏斗。
|
|
142
|
+
|
|
143
|
+
## 5. 时序
|
|
144
|
+
|
|
145
|
+
```mermaid
|
|
146
|
+
sequenceDiagram
|
|
147
|
+
participant C as Thin Client
|
|
148
|
+
participant S as Simulator Server/CDN
|
|
149
|
+
participant R as Runtime
|
|
150
|
+
participant O as Core
|
|
151
|
+
participant W as Service Worker
|
|
152
|
+
participant G as Guest
|
|
153
|
+
participant A as APM
|
|
154
|
+
|
|
155
|
+
C->>S: GET runtime-manifest
|
|
156
|
+
C-->>A: runtime_manifest
|
|
157
|
+
C->>S: GET Bootstrap HTML
|
|
158
|
+
S-->>C: HTML + Runtime JS URL
|
|
159
|
+
C->>R: navigate iframe
|
|
160
|
+
R->>S: GET Runtime JS
|
|
161
|
+
R-->>A: runtime_document / runtime_script / runtime_bootstrap
|
|
162
|
+
C->>R: connect(sessionId, protocol v6)
|
|
163
|
+
R->>S: POST runtime-config
|
|
164
|
+
R-->>A: runtime_config / simulator_create / runtime_ready
|
|
165
|
+
R-->>C: ready(protocol v6)
|
|
166
|
+
C-->>A: runtime_handshake / client_ready
|
|
167
|
+
|
|
168
|
+
C->>C: materialize ZIP/files
|
|
169
|
+
C-->>A: package_materialize(requestId)
|
|
170
|
+
C->>R: loadZip/loadFiles(requestId)
|
|
171
|
+
R-->>A: runtime_request / zip_parse
|
|
172
|
+
Note over R: review_wait 隔离人工等待
|
|
173
|
+
R->>O: loadZip/loadFiles
|
|
174
|
+
O->>S: register and activate SW
|
|
175
|
+
O-->>A: simulator_sw_register(requestId)
|
|
176
|
+
O->>O: build injection and CSP
|
|
177
|
+
O-->>A: injection_build(requestId)
|
|
178
|
+
O->>W: MOUNT files
|
|
179
|
+
W-->>O: MOUNT_ACK
|
|
180
|
+
O-->>A: simulator_sw_mount(requestId)
|
|
181
|
+
O->>G: navigate virtual entry
|
|
182
|
+
G-->>R: load / performance / renderDone
|
|
183
|
+
R-->>A: guest_document / guest_resources / guest_* / guest_render
|
|
184
|
+
R-->>C: response(requestId)
|
|
185
|
+
C-->>A: remote_request(requestId)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## 6. 线上诊断方法
|
|
189
|
+
|
|
190
|
+
按 `session_id` 查看平台启动,按 `session_id + request_id` 查看一次包加载。
|
|
191
|
+
|
|
192
|
+
| 现象 | 主要判断 |
|
|
193
|
+
| --- | --- |
|
|
194
|
+
| `runtime_manifest` 高 | Simulator 服务、DNS、建连、TTFB 或跨域网络慢 |
|
|
195
|
+
| `runtime_document` 高且 `runtime_script` 高 | Runtime 静态资源网络慢 |
|
|
196
|
+
| `runtime_document` 高但网络阶段低 | Runtime JS 执行、主线程阻塞或浏览器 Runtime 慢 |
|
|
197
|
+
| `runtime_config` 高 | 动态配置服务或网络慢 |
|
|
198
|
+
| `simulator_create` 高 | Core 初始化 CPU、DOM 或设备性能问题 |
|
|
199
|
+
| `package_materialize` 高 | Client 文件读取、Blob 转换或包体过大 |
|
|
200
|
+
| `remote_request - runtime_request` 高 | Client 调度、MessageChannel 排队或主线程阻塞 |
|
|
201
|
+
| `zip_parse` / `simulator_parse_done` 高 | ZIP 解压、文件数、包大小或低性能设备问题 |
|
|
202
|
+
| `simulator_sw_register` 高 | SW 下载、更新检查、安装、激活或浏览器 SW 状态问题 |
|
|
203
|
+
| `injection_build` 高 | 注入脚本/CSP 构建 CPU 耗时 |
|
|
204
|
+
| `simulator_sw_mount` 高 | 文件表传输、结构化克隆、SW ACK 或大包问题 |
|
|
205
|
+
| `guest_document` 高且 `guest_resources` 高 | Guest 资源瀑布慢 |
|
|
206
|
+
| `guest_script_execution` 高 | Guest 同步 JS 执行慢 |
|
|
207
|
+
| `guest_render` 高但前置阶段低 | Guest 业务渲染慢或 render-done 未及时触发 |
|
|
208
|
+
|
|
209
|
+
页面不可交互问题优先结合 `guest_error`、`guest_document`、`guest_render`、资源限制错误和页面层级
|
|
210
|
+
检查,重点排查透明遮罩、`pointer-events`、审核启动层未关闭、iframe 未完成加载、Guest 主线程长任务和
|
|
211
|
+
异常后遗留的 loading 状态。该问题不采集用户点击行为。
|
|
212
|
+
|
|
213
|
+
## 7. 字段登记
|
|
214
|
+
|
|
215
|
+
需要登记的字段:
|
|
216
|
+
|
|
217
|
+
| 字段 | 类型 |
|
|
218
|
+
| --- | --- |
|
|
219
|
+
| `app_id` | STRING |
|
|
220
|
+
| `session_id` | STRING |
|
|
221
|
+
| `runtime_version` | STRING |
|
|
222
|
+
| `stage` | STRING |
|
|
223
|
+
| `bytes` | INT64 |
|
|
224
|
+
| `network_duration` | INT64 |
|
|
225
|
+
| `dns_duration` | INT64 |
|
|
226
|
+
| `connect_duration` | INT64 |
|
|
227
|
+
| `ttfb_duration` | INT64 |
|
|
228
|
+
| `code` | INT64 |
|
|
229
|
+
|
|
230
|
+
复用已有字段:`duration`、`type`、`result`、`count`、`error_name`、`message`、`request_id`。
|
|
231
|
+
不登记或上报布尔字段。
|
|
232
|
+
|
|
233
|
+
## 8. APM 环境选择与安全约束
|
|
234
|
+
|
|
235
|
+
- 当前页面 hostname 为 `localhost`、`127.0.0.1`、`0.0.0.0`,或包含 `.sit.`、以 `local.`
|
|
236
|
+
开头时,上报测试 APM。
|
|
237
|
+
- `.beta.` 和其他 hostname 上报正式 APM。
|
|
238
|
+
- 不使用 `process.env` 判断上报环境。
|
|
239
|
+
- Resource Timing 读取失败、浏览器不支持、跨域资源缺少 TAO 或 APM 请求失败时,直接丢弃增强
|
|
240
|
+
数据,主加载流程继续执行。
|
|
241
|
+
- `Timing-Allow-Origin` 只用于允许浏览器读取跨域 Resource Timing,不提供访问授权,也不改变
|
|
242
|
+
CORS、CSP 或 iframe 嵌入权限。
|
|
243
|
+
|
|
244
|
+
## 9. 兼容性
|
|
245
|
+
|
|
246
|
+
| 组合 | 运行 | 可观测范围 |
|
|
247
|
+
| --- | --- | --- |
|
|
248
|
+
| 旧 Client + 新 Runtime | 支持 | Runtime 自身、Core、SW、Guest;使用 v6 现有 sessionId/requestId |
|
|
249
|
+
| 新 Client + 新 Runtime | 支持 | Client、Runtime、Core、SW、Guest 全链路 |
|
|
250
|
+
| 新 Client + v6 旧 Runtime | 支持 | Client 外层阶段与旧 Runtime 已有能力 |
|
|
251
|
+
|
|
252
|
+
兼容性约束:
|
|
253
|
+
|
|
254
|
+
- `REMOTE_SIMULATOR_PROTOCOL_VERSION` 保持为 6。
|
|
255
|
+
- connect、request、response 消息结构不增加字段。
|
|
256
|
+
- Runtime 不要求 Client 发送新的 capability 或配置。
|
|
257
|
+
- APM 逻辑不参与业务 Promise 的成功或失败判定。
|
|
258
|
+
|
|
259
|
+
## 10. 验收
|
|
260
|
+
|
|
261
|
+
- 新 Runtime 能与线上 v6 旧 Client 完成 ready、`loadZip`、`loadFiles` 和渲染。
|
|
262
|
+
- 新 Client + 新 Runtime 能按 `session_id + request_id` 查询一条完整包加载链路。
|
|
263
|
+
- `loadZip` 与 `loadFiles` 可由 `type` 直接区分。
|
|
264
|
+
- 模拟器平台启动和应用包加载使用独立指标与看板。
|
|
265
|
+
- `review_wait` 从系统加载耗时中剔除,`review_app_load` 只统计开始审核后的真实加载。
|
|
266
|
+
- 网络、解压、SW、注入、MOUNT、Guest 资源和脚本执行均有独立判断依据。
|
|
267
|
+
- 任一性能 API 或上报请求失败不影响模拟器加载。
|
|
268
|
+
- 协议文件无变更,字段中不包含布尔值。
|