@fulgurjs/federation 5.5.2 → 5.7.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 5.7.0
4
+
5
+ - **修复:Vite 8 同步协商门面的共享语义补修(strictVersion 拒绝 + resolveShare 契约)**——5.6.0 引入的同步门面(V8-SYNC-FACADE)存在两处语义缺陷,本轮以 runtime 新决策入口 `loadShareSync` 统一修复,绑定门面/命名空间门面/CJS 垫片三条同步路径全部改走该入口(各引擎一致):
6
+ - **strictVersion 冲突被吞**——5.6.0 门面用 `getLoadedShare`(readyOnly 过滤:只看已就绪实例)+ 空 catch 兜底:非 singleton(webpack 默认 strictVersion=true)下「已注册未加载的本地版本」被排除出候选集 → 误判「无满足版本」抛 MFU-003 → 被 catch 吞掉后静默使用本地副本,README「strictVersion 冲突抛 MFU-003」契约失效。现与异步 loadShare 共用同一选择器(**全部已注册版本**)——已注册未加载的本地版本是合法选中对象(其物理实例就是门面的本地 import,等价异步 `await get()`),strictVersion 冲突(singleton 收养不满足版本 / 真无满足版本)一律抛 MFU-003(保留 shareKey/requiredVersion/提供方细节),不再被本地 fallback 掩盖;拒绝后不 pin、不污染作用域。
7
+ - **resolveShare 首次静态导入被跳过**——现按契约参与:该消费条件的成功快照无条件复用;无快照时**同步调用 hook**(其决策写入快照供后续消费复用);hook 返回 Promise 或选中未就绪的他人条目 → 抛 MFU-004+`details.syncUnsupported`(明确诊断 + 修法,不静默忽略 hook);hook 抛出原样传播。**已知边界(如实)**:异步 resolveShare(返回 Promise)无法在 Vite 8 同步静态导入路径等待——诊断明确给出两条修法(同步返回 picked / 先经一次动态 loadShare 建立快照),不静默执行错误语义。
8
+ - **singleton 首个消费者接管语义**——作用域无任何已加载实例时(如 React 宿主声明 vue 单例但自身不消费),首个消费者(同步或异步)以本地版本接管该单例(MFU-010 告警版本漂移),后续消费者按已加载优先收敛同一实例——webpack「首个消费者定单例」语义;strictVersion 冲突仍拒绝。
9
+ - **新增运行时 API:`loadShareSync(key, opts)`**(内部同步路径专用,未进 `/runtime` 公开入口清单):返回 `{ kind: 'ready', value }`(已就绪实例)或 `{ kind: 'local' }`(使用本地副本,调用方负责 pin);「没有可用共享实例 / 版本冲突 / 尚未就绪 / 决策失败」四态以返回形态与错误码严格区分。
10
+ - **质量门禁**:单测 631 → 647(loadShareSync 决策树 9 例 + 同步门面×真实 runtime 执行级回归 4 例——strictVersion 传播/hook 遵循/静态与动态实例严格相等/B-2/B-8 本地交付);e2e dev 73/73 × vite 6.4.3/8.3.2、prod 33/33 × vite 6.4.3/8.3.2;Jeecg vite 8.3.2 生产五场景 5/5 零错误;gzip 阈值 9216→10240B(loadShareSync 为语义补修的必要增量)。
11
+
12
+ ## 5.6.0
13
+
14
+ - **修复:Vite 8(rolldown)生产链路五项(V8-SYNC-FACADE 配套)**
15
+ - **大型应用页面启动死锁**——根因(JeecgBoot 实测定位,运行时插桩实证):TLA 协商门面(`await loadShare`)使 rolldown 把「顶层 await」沿静态依赖传播进消费方模块的惰性初始化包装;应用代码/依赖库自身既有的循环依赖(ant-design-vue 的 useConfigInject ⇄ theme)随即变成两个 async init 互等,永不落定——页面零报错、应用引导永不执行(vite 8.1.4/8.3.2、rolldown 1.1.5/1.2.12 同现;5.5.x 的产物补 async 只修语法层,运行期挂起仍在)。修复:**rolldown 构建路径下,共享绑定门面与命名空间门面改为同步 pin 形态**(与 React 侧 CJS 垫片同构):`getLoadedShare` 命中已协商实例则复用;未命中(含 strictVersion 版本冲突——与 TLA 路径 loadShare→fallback 语义对齐,不抛 MFU-003)时 `pinLoadedShare` 登记本地副本(first-wins + 版本守卫),后续协商收敛同一实例。插件不再向应用图注入任何 TLA,循环依赖回到同步求值;rollup(vite 5–7)路径行为不变。验收:Jeecg A/B/React-C/React宿主 vite 8.3.2(rolldown 1.2.12)生产全场景 5/5(登录、A套B、三层深链刷新直达、A套C 中文 query 深链刷新直达、React宿主套B)零 console 错误;e2e vite8 dev 73/73 + prod 33/33。已知代价(仅 vite 8):门面本地副本静态入图,协商命中他方实例时本地物理 chunk 仍会被模块图拉取(B-2/B-8 双版本场景 vue 本体网络副本 ≤2,优于旧 TLA 形态实测的 3 份;运行时身份仍收敛单一实例)。
16
+ - **remoteEntry 失败重试在 rolldown 产物失效**——generateBundle 的 `__fgR` 包装正则只匹配单/双引号字面量,rolldown 以反引号渲染 `import(反引号字面量)`,包装从未生效:expose chunk 失败后被浏览器模块图负缓存,重试同 URL 直接拒绝("Failed to fetch dynamically imported module")。修复:三种引号都包装。
17
+ - **vite8 依赖预载负缓存阻断同页重试**——vite8 preload 助手的 `<link rel=modulepreload>` 会把 JS 依赖写入模块图,网络失败被负缓存后 `__fgR` 只变换入口 URL 无法恢复依赖 URL(实测:解除阻断后 retry=2 入口 200 而依赖 chunk 零请求、Promise 永不落定)。修复:rolldown 构建下 remoteEntry 各 loader 的 `__vite__mapDeps` 过滤为仅 CSS(保留样式注入语义),JS 依赖改由模块图按需拉取;rollup 保持原生预载。
18
+ - **vite8 manifest exposes 缺项**——expose 目标同时被应用自身静态引用时,rolldown 将其并入其他 chunk(无独立 facadeModuleId),generateBundle 的 expose→chunk 映射落空(manifest 缺 `./Button` 等,preloadRemote/MFU-006 断链)。修复:按 chunk.modules 索引反查兜底(rollup 恒走原路径零影响)。
19
+ - **optimizeDeps 弃用警告**——vite ≥ 8 只下发 `rolldownOptions`(遗留 `esbuildOptions` 键触发 deprecation warning);vite ≤ 7 保持原双键路径。
20
+ - **重设计:V8-ASYNC-FIX 产物补丁(esbuild 定位引导,2026-10-03)**——旧版阶段一为盲正则替换(可命中字符串/注释里的同形文本)、阶段二 AST 兜底实际不可达(标准 parser 对「await 位于非 async 函数」一律早期 SyntaxError,`this.parse` 必然先抛;旧实现另有 `collectBrokenFunctions` 从不填充数组的缺陷,即便可达也返回空)。新版由 esbuild 真实报错位置驱动(精确指向非法 await,字符串/注释内容永不误报):在代码区掩码(轻量 lexer 排除字符串/模板/注释/正则字面量)内回扫定位最内层包裹函数头,按箭头/function 声明/表达式/方法简写形态插入 `async`,每轮插入后立即 esbuild 复验;不支持的形态(getter/setter/生成器/计算键方法)明确失败并带上下文,不产出错误补丁。门面同步化后插件自身产物不再触发该缺陷,本修复保留为「用户自有 TLA 代码 × 循环依赖」触发 rolldown codegen 缺陷的安全网。回归 `tests/async-mark-repair.test.ts` 12 例:含以 rolldown 真实运行时访问器(逐字取自 rolldown-runtime chunk)执行修复产物的运行语义验证(初始化顺序/只初始化一次/循环依赖不永久挂起/rejection 传播/字符串注释正则零改动/不支持形态明确失败)。
21
+ - **质量门禁**:单测 623 → 631(async 补标重设计 12 + optimizeDeps rolldown 分支 1);e2e dev 73/73(vite 5.1.8/6.4.3/7.3.6/8.3.2 四档)+ prod 33/33(vite 6.4.3/8.3.2 两档);React 18.3.1+RR6+vite 8.3.2 dev 34/34 + prod-react 20/20;tarball smoke 通过;两套 TS 0 错误;gzip/错误码 48 三方一致。**已知边界(如实登记)**:React 18 子应用被「声明 react 19 singleton 的宿主」承载(host-bridge-vue × R18 remote-react × vite8 桥接)时,单例 loaded-first 跨大版本收养使 react-dom@18 配到 react@19(`__SECRET_INTERNALS` 不存在)——MF 单例语义使然(vite 5–7 同配置同样触发,此前未测过该组合),正确姿势是宿主/远程版本对齐或声明 requiredVersion+strictVersion。
22
+ ——根因(JeecgBoot 实测定位):TLA 协商门面(`await loadShare`)使 rolldown 把「顶层 await」沿静态依赖传播进消费方模块的惰性初始化包装;应用代码/依赖库自身既有的循环依赖(ant-design-vue 的 useConfigInject ⇄ theme,运行时插桩实证为两个 async init 互等)随即变成永不落定的互等——页面零报错、应用引导永不执行(vite 8.1.4/8.3.2、rolldown 1.1.5/1.2.12 同现;5.5.x 时代的产物补 async 只修了语法层,运行期挂起仍在)。修复:**rolldown 构建路径下,共享绑定门面与命名空间门面改为同步 pin 形态**(与 React 侧 CJS 垫片同构——该路径在 vite8 一直可用):`getLoadedShare` 命中已协商实例则复用;未命中 `pinLoadedShare` 登记本地副本(first-wins + 版本守卫),后续任何 `loadShare` 协商收敛到同一实例(单例不双份)。插件自身不再向应用图注入任何 TLA,循环依赖回到同步求值。rollup(vite 5/6/7)路径行为不变(保留 TLA 形态)。已知行为差异(仅 vite 8 构建路径):自定义 `resolveShare` hook 不再参与静态导入的首次解析(此前协商过的快照仍会被命中);`strictVersion` 版本冲突在静态导入处不再抛 MFU-012 而是回退本地副本。验收:Jeecg A/B/React-C/React宿主 vite 8.3.2(rolldown 1.2.12)生产全场景 5/5(登录、A套B、三层深链刷新、A套C 中文 query 深链刷新直达、React宿主套B),console/pageerror 零错误。
23
+ - **重设计:V8-ASYNC-FIX 产物补丁(esbuild 定位引导,2026-10-03)**——旧版阶段一为盲正则替换(可命中字符串/注释里的同形文本)、阶段二 AST 兜底实际不可达(标准 parser 对「await 位于非 async 函数」一律早期 SyntaxError,`this.parse` 必然先抛;旧实现另有 `collectBrokenFunctions` 从不填充数组的缺陷)。新版由 esbuild 真实报错位置驱动(精确指向非法 await,字符串/注释内容永不误报):在代码区掩码(轻量 lexer 排除字符串/模板/注释/正则字面量)内回扫定位最内层包裹函数头,按箭头/function 声明/表达式/方法简写形态插入 `async`,每轮插入后立即 esbuild 复验;不支持的形态(getter/setter/生成器/计算键方法)明确失败并带上下文,不产出错误补丁。门面同步化后插件自身产物不再触发该缺陷,本修复保留为「用户自有 TLA 代码 × 循环依赖」触发 rolldown codegen 缺陷的安全网。回归 `tests/async-mark-repair.test.ts` 12 例:含以 rolldown 真实运行时访问器(逐字取自 rolldown-runtime chunk)执行修复产物的运行语义验证(初始化顺序/只初始化一次/循环依赖不永久挂起/rejection 传播/字符串注释正则零改动/不支持形态明确失败)。
24
+
3
25
  ## 5.5.2
4
26
 
5
27
  - **修复:多远程宿主 react-refresh 发布脚本的错源网络噪声**——发布脚本动态 import「首个 http 远程」的 `/@react-refresh`,多远程(Vue 远程 + React 远程并存)时猜错 origin:JS 层 5.4.2 已容错,但浏览器仍记录一条 404 网络错误(JeecgBoot-A 实测:B(5372,Vue)+C(5373,React) 双远程,A 页控制台恒有一条 5372/@react-refresh 404)。现改为:仅单一 http 远程时才跨源导入(origin 无歧义);多远程时只同步设置 preamble 标志(硬检查语义不变),真实 react-refresh 实例由各 React 远程自带 origin 的 shim 自举并发布页面级单例——A 页 404 噪声归零,React 远程挂载与 HMR 实测不受影响。
package/README.en.md CHANGED
@@ -53,7 +53,7 @@ pnpm add -D @fulgurjs/federation
53
53
  - Vue ≥ 3.2.0 and/or React `>=18.0.0 <20` — all three are **optional peers**; install only the framework you use
54
54
  - Chrome 108+ (native top-level await)
55
55
 
56
- > Vite 8 (rolldown): as of 5.3.3, dev, production builds and production page mounting all pass full acceptance (bidirectional bridge 11-step interaction matrix, see the acceptance report). **5.4.2 boundary note**: in production builds of large apps (e.g. JeecgBoot v3.9.5), the plugin's TLA share facades joining chunk merging can trigger a rolldown codegen bug that merges the app's own async initialization into a sync lazy init and drops the `async` marker (`SyntaxError: Unexpected reserved word`; minify/target/manualChunks variants and a bare-baseline comparison have ruled out other variables) — build such apps for production with Vite 5–7; dev is unaffected. The first page open on a cold dev cache still falls inside the dependency pre-bundling window (DEV-010; it self-recovers via reload). Warm up before acceptance runs or manual judgement, as documented.
56
+ > Vite 8 (rolldown): **fully usable in production as of 5.6.0** — the synchronous negotiation facade (V8-SYNC-FACADE) eliminates the startup mutual-await deadlock between top-level await propagation and application circular dependencies (full JeecgBoot v3.9.5 acceptance: login, A-hosts-B, three-layer deep-link refresh, cross-framework deep links, React host; vite 8.3.2 + rolldown 1.2.12), plus three vite8-specific fixes (remoteEntry failure retry, manifest exposes mapping, dependency-preload negative caching); e2e dev 73/73 + prod 33/33 as a standing CI matrix. The first page open on a cold dev cache still falls inside the dependency pre-bundling window (DEV-010; it self-recovers via reload). Warm up before acceptance runs or manual judgement, as documented. Known cost (vite 8 only): the synchronous facade keeps the local copy chunk reachable by the module graph even when negotiation picks another app's instance (dual-version scenarios fetch the shared library at most twice; runtime identity still converges to a single instance).
57
57
 
58
58
  `@fulgurjs/federation/runtime` and `@fulgurjs/federation/react` are **ESM-only** browser entries (no `require()`). The build-time main entry supports both ESM and CJS.
59
59
 
package/README.md CHANGED
@@ -51,7 +51,7 @@ pnpm add -D @fulgurjs/federation
51
51
 
52
52
  要求:Vite ≥ 5.1(实测至 8.x)、Node ≥ 18、Vue 3 和/或 React 18–19(均为可选 peer——按所用框架安装)、浏览器 Chrome 108+(TLA 原生支持)。
53
53
 
54
- > Vite 8(rolldown):5.3.3 起 dev 与生产构建、生产页面挂载均已通过完整验收(双向桥接 11 步交互矩阵,见验收报告)。**5.4.2 补充边界**:大型应用(如 JeecgBoot v3.9.5)生产构建下,插件的 TLA 共享门面参与 chunk 合并时可触发 rolldown 将应用 async 初始化语句合并丢 `async` 标记(`SyntaxError: Unexpected reserved word`,minify/target/manualChunks 变体与裸基线对照已排除其他变量)——此类应用生产构建请用 Vite 5–7,开发态不受影响。dev 冷启动首开仍受依赖预构建窗口影响(DEV-010,首轮打开自动恢复),验收与人工判断请按文档先预热。
54
+ > Vite 8(rolldown):**5.6.0 起生产链路完整可用**——同步协商门面(V8-SYNC-FACADE)根除了「TLA 顶层 await × 应用循环依赖」的启动互等死锁(JeecgBoot v3.9.5 全场景验收:登录/A套B/三层深链刷新直达/跨框架深链/React 宿主,vite 8.3.2 + rolldown 1.2.12),并修复 remoteEntry 失败重试、manifest exposes 缺项、依赖预载负缓存三项 vite8 专属缺陷;e2e dev 73/73 + prod 33/33(CI 常驻矩阵)。dev 冷启动首开仍受依赖预构建窗口影响(DEV-010,首轮打开自动恢复),验收与人工判断请按文档先预热。已知代价(仅 vite 8):同步门面使协商命中他方实例时本地副本 chunk 仍会被模块图拉取(双版本场景共享库网络副本 ≤2,运行时身份仍收敛单一实例)。
55
55
 
56
56
  ## 快速开始(React 应用)
57
57
 
@@ -10,7 +10,7 @@ import {
10
10
  releaseBridgeSession,
11
11
  resolveBridgeContext,
12
12
  withBridgeTimeout
13
- } from "./chunk-CI54BRPO.js";
13
+ } from "./chunk-OLQGJR2Z.js";
14
14
 
15
15
  // src/bridge-host-vue.ts
16
16
  import { defineComponent, h, onActivated, onBeforeUnmount, onDeactivated, onMounted, ref, shallowRef, toRaw, watch } from "vue";
@@ -546,9 +546,17 @@ function createRuntime() {
546
546
  if (byName && Object.keys(byName).length > 0) {
547
547
  try {
548
548
  const pick = selectShareEntry(name, opts);
549
- if (pick && pick.value === void 0 && pick.version === localVersion) {
550
- pick.value = instance;
551
- pick.loaded = true;
549
+ if (pick && pick.value === void 0) {
550
+ if (pick.version === localVersion) {
551
+ pick.value = instance;
552
+ pick.loaded = true;
553
+ } else if (opts.singleton) {
554
+ pick.value = instance;
555
+ pick.loaded = true;
556
+ console.warn(
557
+ `[fulgurjs:MFU-010] \u5171\u4EAB\u5355\u4F8B "${key}" \u7684\u9996\u6B21\u6D88\u8D39\u8005\u4EE5\u672C\u5730\u7248\u672C ${localVersion} \u63A5\u7BA1\u4E86 ${pick.from} \u58F0\u660E\u7684 ${pick.version} \u69FD\u4F4D\uFF08\u8BE5\u7248\u672C\u5C1A\u672A\u52A0\u8F7D\uFF09\u3002`
558
+ );
559
+ }
552
560
  }
553
561
  } catch {
554
562
  }
@@ -629,6 +637,72 @@ function createRuntime() {
629
637
  function pinLoadedShare2(name, opts, localVersion, instance) {
630
638
  registerFallbackInstance(name, { ...opts, localVersion }, instance);
631
639
  }
640
+ function loadShareSync2(name, opts) {
641
+ const scopeName = opts.shareScope || "default";
642
+ const shareKey = opts.shareKey || name;
643
+ if (hooks.resolveShare) {
644
+ const snapKey = shareRequestKey(name, opts);
645
+ const snap = resolvedShareSnapshots.get(snapKey);
646
+ if (snap && snap.value !== void 0) return { kind: "ready", value: snap.value };
647
+ const pickedRaw = hooks.resolveShare({
648
+ shareKey,
649
+ shareScope: scopeName,
650
+ requiredVersion: opts.requiredVersion,
651
+ picked: selectShareEntry(name, opts),
652
+ available: Object.values(getScope(scopeName)[shareKey] || {})
653
+ });
654
+ if (pickedRaw && typeof pickedRaw.then === "function") {
655
+ throw new FgError(
656
+ ErrorCodes.SHARE_NOT_AVAILABLE,
657
+ `\u73B0\u8C61\uFF1AresolveShare \u5BF9\u5171\u4EAB "${shareKey}" \u8FD4\u56DE\u4E86 Promise\uFF0C\u4F46\u8BE5\u5171\u4EAB\u6B63\u88AB\u540C\u6B65\u9759\u6001\u5BFC\u5165\u6D88\u8D39\uFF08Vite 8 \u540C\u6B65\u534F\u5546\u95E8\u9762\uFF09\u3002
658
+ \u539F\u56E0\uFF1A\u6A21\u5757\u6C42\u503C\u671F\u65E0\u6CD5\u7B49\u5F85\u5F02\u6B65\u51B3\u7B56\uFF1B\u9759\u6001\u5BFC\u5165\u4E0D\u80FD\u9759\u9ED8\u5FFD\u7565 hook \u51B3\u7B56\u3002
659
+ \u4FEE\u6CD5\uFF1A\u8BA9 resolveShare \u5BF9\u8BE5\u952E\u540C\u6B65\u8FD4\u56DE picked\uFF08\u4ECE available \u4E2D\u9009\u62E9\uFF09\uFF1B\u6216\u8BA9\u9996\u6B21\u6D88\u8D39\u5148\u7ECF\u4E00\u6B21\u52A8\u6001 loadShare \u5B8C\u6210\u534F\u5546\uFF08\u6210\u529F\u5FEB\u7167\u4F1A\u88AB\u9759\u6001\u5BFC\u5165\u590D\u7528\uFF09\u3002`,
660
+ { shareKey, requiredVersion: opts.requiredVersion, syncUnsupported: true }
661
+ );
662
+ }
663
+ const picked = pickedRaw;
664
+ if (picked) {
665
+ if (picked.value !== void 0) {
666
+ resolvedShareSnapshots.set(shareRequestKey(name, opts), picked);
667
+ return { kind: "ready", value: picked.value };
668
+ }
669
+ if (picked.version !== void 0 && picked.version === opts.localVersion) return { kind: "local" };
670
+ throw new FgError(
671
+ ErrorCodes.SHARE_NOT_AVAILABLE,
672
+ `\u73B0\u8C61\uFF1AresolveShare \u4E3A\u5171\u4EAB "${shareKey}" \u9009\u62E9\u4E86 ${picked.version ?? "\u672A\u5C31\u7EEA\u6761\u76EE"}\uFF08\u5C1A\u672A\u52A0\u8F7D\uFF09\uFF0C\u540C\u6B65\u9759\u6001\u5BFC\u5165\u65E0\u6CD5\u7B49\u5F85\u5176\u5B9E\u4F8B\u5C31\u7EEA\u3002
673
+ \u4FEE\u6CD5\uFF1A\u8BA9 hook \u4F18\u5148\u9009\u62E9\u5DF2\u5C31\u7EEA\u5B9E\u4F8B\u6216\u672C\u5E94\u7528\u672C\u5730\u7248\u672C\uFF08${opts.localVersion ?? "\u672A\u58F0\u660E"}\uFF09\uFF0C\u6216\u5148\u7ECF\u52A8\u6001 loadShare \u5B8C\u6210\u534F\u5546\u3002`,
674
+ { shareKey, requiredVersion: opts.requiredVersion, syncUnsupported: true }
675
+ );
676
+ }
677
+ }
678
+ const entry = selectShareEntry(name, opts);
679
+ if (!entry) return { kind: "local" };
680
+ if (entry.value !== void 0) return { kind: "ready", value: entry.value };
681
+ if (entry.version !== void 0 && entry.version === opts.localVersion) return { kind: "local" };
682
+ if (opts.singleton) {
683
+ if (opts.strictVersion) {
684
+ throw new FgError(
685
+ ErrorCodes.SHARE_NOT_AVAILABLE,
686
+ `\u73B0\u8C61\uFF1A\u5171\u4EAB\u5355\u4F8B "${shareKey}" \u9009\u4E2D\u4E86 ${entry.from} \u63D0\u4F9B\u7684 ${entry.version}\uFF08\u5C1A\u672A\u52A0\u8F7D\uFF09\uFF0C\u540C\u6B65\u9759\u6001\u5BFC\u5165\u65E0\u6CD5\u7B49\u5F85\u5176\u5B9E\u4F8B\u5C31\u7EEA\u3002
687
+ \u539F\u56E0\uFF1A\u5355\u4F8B\u5FC5\u987B\u5168\u9875\u4E00\u81F4\uFF0C\u4E0D\u80FD\u9759\u9ED8\u6539\u7528\u672C\u5730\u526F\u672C\u5206\u88C2\u5B9E\u4F8B\u3002
688
+ \u4FEE\u6CD5\uFF1A\u8BA9\u8BE5\u5171\u4EAB\u7684\u9996\u6B21\u6D88\u8D39\u5148\u7ECF\u4E00\u6B21\u52A8\u6001 loadShare \u5B8C\u6210\u52A0\u8F7D\uFF0C\u6216\u5C06\u672C\u5E94\u7528\u7248\u672C\u4E0E\u4F5C\u7528\u57DF\u63D0\u4F9B\u7248\u672C\u5BF9\u9F50\u3002`,
689
+ { shareKey, requiredVersion: opts.requiredVersion, syncUnsupported: true }
690
+ );
691
+ }
692
+ const warnKey = `${scopeName}|${shareKey}|${entry.version}|${opts.localVersion}`;
693
+ if (!reportedSingletonSkews.has(warnKey)) {
694
+ reportedSingletonSkews.add(warnKey);
695
+ console.warn(
696
+ `[fulgurjs:MFU-010] \u5171\u4EAB\u5355\u4F8B "${shareKey}"\uFF1A\u4F5C\u7528\u57DF\u4E2D ${entry.from} \u63D0\u4F9B\u7684 ${entry.version} \u5C1A\u672A\u52A0\u8F7D\uFF0C\u9996\u4E2A\u6D88\u8D39\u8005\u4EE5\u672C\u5730\u7248\u672C ${opts.localVersion ?? ""} \u63A5\u7BA1\uFF08\u540E\u7EED\u6D88\u8D39\u8005\u6309\u5DF2\u52A0\u8F7D\u4F18\u5148\u6536\u655B\u5230\u8BE5\u5B9E\u4F8B\uFF09\u3002`
697
+ );
698
+ }
699
+ return { kind: "local" };
700
+ }
701
+ console.warn(
702
+ `[fulgurjs] \u5171\u4EAB "${shareKey}" \u7684\u540C\u6B65\u9759\u6001\u6D88\u8D39\u4F7F\u7528\u672C\u5730\u526F\u672C ${opts.localVersion ?? ""}\uFF08\u4F5C\u7528\u57DF\u4E2D\u6EE1\u8DB3\u8981\u6C42\u7684\u53E6\u4E00\u7248\u672C ${entry.version} \u5C1A\u672A\u5C31\u7EEA\uFF0C\u65E0\u6CD5\u540C\u6B65\u7B49\u5F85\uFF09\uFF1B\u975E\u5355\u4F8B\u5141\u8BB8\u591A\u7248\u672C\u5171\u5B58\u3002`
703
+ );
704
+ return { kind: "local" };
705
+ }
632
706
  function sanitizeUrl(u) {
633
707
  try {
634
708
  const x = new URL(u, typeof location < "u" ? location.href : "http://f.invalid");
@@ -1063,6 +1137,7 @@ ${hints.join("\n")}`,
1063
1137
  registerRemote: registerRemote2,
1064
1138
  registerPlugins: registerPlugins2,
1065
1139
  loadShare: loadShare2,
1140
+ loadShareSync: loadShareSync2,
1066
1141
  getLoadedShare: getLoadedShare2,
1067
1142
  pinLoadedShare: pinLoadedShare2,
1068
1143
  loadRemote: loadRemote2,
@@ -1086,6 +1161,7 @@ var registerRemote = runtime.registerRemote;
1086
1161
  var registerPlugins = runtime.registerPlugins;
1087
1162
  var loadShare = runtime.loadShare;
1088
1163
  var getLoadedShare = runtime.getLoadedShare;
1164
+ var loadShareSync = runtime.loadShareSync;
1089
1165
  var pinLoadedShare = runtime.pinLoadedShare;
1090
1166
  var loadRemote = runtime.loadRemote;
1091
1167
  var getContainer = runtime.getContainer;
@@ -10,7 +10,7 @@ import {
10
10
  releaseBridgeSession,
11
11
  resolveBridgeContext,
12
12
  withBridgeTimeout
13
- } from "./chunk-CI54BRPO.js";
13
+ } from "./chunk-OLQGJR2Z.js";
14
14
 
15
15
  // src/bridge-host-react.ts
16
16
  import {