@rxdrag/astro-sandbox
npm install @rxdrag/astro-sandbox@rxdrag/astro-sandbox
┌─────────────────────────────────────────────────────────────┐
│ 宿主窗口 │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ ModuleLoader │ │
│ │ - 编译 Astro 组件 → 代码字符串 │ │
│ │ - 编译 React 组件 → 代码字符串(React import 改为 CDN) │ │
│ │ - 缓存编译结果,多 iframe 共享 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ 代码字符串(通过 srcdoc 注入) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ MultiIframeSandboxSession │ │
│ │ - moduleCodeRegistry: 编译后的代码字符串 │ │
│ │ - 多个 iframe 共享同一份 moduleCodeRegistry │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ iframe 1 │ │ iframe 2 │ │ iframe 3 │
│ │ │ │ │ │
│ 1. 从 CDN 加载 │ │ 1. 从 CDN 加载 │ │ 1. 从 CDN 加载 │
│ React │ │ React │ │ React │
│ │ │ │ │ │
│ 2. 创建 blob │ │ 2. 创建 blob │ │ 2. 创建 blob │
│ URL 并 │ │ URL 并 │ │ URL 并 │
│ import │ │ import │ │ import │
│ │ │ │ │ │
│ 3. SSR 渲染 │ │ 3. SSR 渲染 │ │ 3. SSR 渲染 │
│ HTML │ │ HTML │ │ HTML │
│ │ │ │ │ │
│ 4. hydration │ │ 4. hydration │ │ 4. hydration │
│ 激活交互 │ │ 激活交互 │ │ 激活交互 │
└───────────────┘ └───────────────┘ └───────────────┘
关键点
编译在宿主完成:避免每个 iframe 都要加载 esbuild-wasm
编译结果共享:moduleCodeRegistry 存储编译后的代码字符串,多 iframe 共享
React import 重写为 CDN:编译时把 import React from 'react' 改为 import React from 'https://esm.sh/react@18.3.1'
iframe 内部执行:
从 CDN 加载 React
创建 blob URL 并 import 编译后的代码
执行 SSR(renderToString)
执行 hydration(hydrateRoot)