@fulgurjs/federation 6.13.1 → 6.13.3

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.
@@ -27,6 +27,12 @@ module.exports = __toCommonJS(vue_adapter_exports);
27
27
  var import_vue = require("vue");
28
28
 
29
29
  // src/runtime/errors.ts
30
+ function diagnosticUrl(text) {
31
+ return text.replace(/(https?:\/\/)(?:[^\s/@]+@)?([^\s?#"'<>,。;))\]]+)(?:[?#][^\s"'<>,。;))\]]*)?/g, "$1$2");
32
+ }
33
+ function diagnosticMessage(error) {
34
+ return diagnosticUrl(String(error && typeof error === "object" && "message" in error ? error.message : error)).replace(/\b(token|password|cookie|authorization)["']?\s*[:=]\s*["']?(?:Bearer\s+)?[^\s,;"'}]+/gi, "$1=[redacted]");
35
+ }
30
36
  var ErrorCodes = {
31
37
  /** 远程容器加载失败(网络/超时/重试耗尽/熔断) */
32
38
  REMOTE_LOAD_FAILED: "MFU-001",
@@ -58,7 +64,7 @@ var ErrorCodes = {
58
64
  SETUP_RECURSION: "MFU-014",
59
65
  /** 远程模块在组件消费边界导出的不是可渲染组件(适配器实测导出形态后报出) */
60
66
  COMPONENT_EXPORT_INVALID: "MFU-018",
61
- /** Vue 组件直渲染的渲染器与共享作用域实际收敛的 Vue 实例不一致(身份证据已证实) */
67
+ /** 当前编译 SFC 的 Vue 导入引用与消费方渲染器不一致(组件证据已证实) */
62
68
  VUE_RUNTIME_IDENTITY_MISMATCH: "MFU-019",
63
69
  /** 远程组件子树内部渲染错误(插件边界观测:setup/render/嵌套异步组件拒绝;原始异常保留在 cause) */
64
70
  REMOTE_RENDER_ERROR: "MFU-020"
@@ -349,19 +355,28 @@ function isVueRenderableComponent(inner) {
349
355
  const c = inner;
350
356
  return typeof c.render === "function" || typeof c.setup === "function" || typeof c.template === "string";
351
357
  }
352
- function vueRuntimeIdentityError(spec) {
353
- const sharedVue = globalThis.__FULGURJS_RUNTIME__?.getLoadedShare?.("vue");
354
- if (!sharedVue || typeof sharedVue.ref !== "function" || typeof sharedVue.version !== "string") return void 0;
355
- if (sharedVue.ref === import_vue.ref) return void 0;
358
+ function vueRuntimeIdentityError(spec, component) {
359
+ const bindings = { ref: import_vue.ref, openBlock: import_vue.openBlock, createVNode: import_vue.createVNode, createElementVNode: import_vue.createElementVNode, defineComponent: import_vue.defineComponent, h: import_vue.h };
360
+ const evidence = component[/* @__PURE__ */ Symbol.for("fulgurjs.vue-runtime")];
361
+ const key = evidence?.key;
362
+ if (!key || !Object.hasOwn(bindings, key) || typeof evidence?.value !== "function") return void 0;
363
+ if (bindings[key] === evidence.value) return void 0;
356
364
  return Object.assign(
357
365
  new Error(
358
- `\u73B0\u8C61\uFF1A\u6D88\u8D39\u65B9\u76F4\u6E32\u67D3\u8FDC\u7A0B\u7EC4\u4EF6 "${spec}" \u65F6\uFF0C\u68C0\u6D4B\u5230\u6E32\u67D3\u5668\u4F7F\u7528\u7684 Vue \u4E0E\u5171\u4EAB\u4F5C\u7528\u57DF\u5B9E\u9645\u6536\u655B\u7684 Vue \u4E0D\u662F\u540C\u4E00\u5B9E\u4F8B\uFF08\u6E32\u67D3\u94FE ${import_vue.version}\uFF0C\u5171\u4EAB\u5B9E\u4F8B ${sharedVue.version}\uFF1B\u7248\u672C\u53F7\u76F8\u540C\u4E5F\u4E0D\u4EE3\u8868\u5B9E\u4F8B\u76F8\u540C\uFF09\u3002
359
- \u6839\u56E0\uFF08\u5DF2\u8BC1\u5B9E\uFF09\uFF1A\u53CC\u65B9\u81F3\u5C11\u4E00\u65B9\u58F0\u660E\u4E86 shared.vue\uFF0C\u4F46\u6D88\u8D39\u65B9\u81EA\u8EAB\u7684 vue \u5BFC\u5165\u6CA1\u6709\u6536\u655B\u5230\u540C\u4E00\u5B9E\u4F8B\u2014\u2014\u5E38\u89C1\u4E8E\u6D88\u8D39\u65B9\u672A\u58F0\u660E shared.vue\u3001dev \u9884\u6784\u5EFA/optimizeDeps \u7ED5\u8FC7\u5171\u4EAB\u95E8\u9762\u3001\u6216 shareScope \u4E0D\u4E00\u81F4\u3002\u5B9E\u4F8B\u5206\u88C2\u65F6 inject/provide/Pinia/getCurrentInstance \u8DE8\u5B9E\u4F8B\u65AD\u94FE\uFF0C\u9875\u9762\u5E38\u8868\u73B0\u4E3A\u5916\u58F3\u5728\u3001\u5185\u90E8\u7A7A\u767D\u4E14\u65E0 pageerror\u3002
360
- \u4FEE\u6CD5\uFF1A\u2460 \u6D88\u8D39\u65B9\u4E0E\u8FDC\u7A0B\u90FD\u5728 federation({ shared }) \u58F0\u660E vue\uFF08singleton \u5EFA\u8BAE\u5F00\u542F\uFF09\u5E76\u4F7F\u7528\u540C\u4E00 shareScope\uFF1B\u2461 dev \u4E0B\u786E\u8BA4\u63D2\u4EF6\u7248\u672C\u4E00\u81F4\u3001\u672A\u7528 optimizeDeps \u628A vue \u9884\u6784\u5EFA\u6210\u7B2C\u4E8C\u4EFD\u526F\u672C\uFF1B\u2462 \u9700\u8981\u72EC\u7ACB Vue \u8FD0\u884C\u65F6\u7684\u5B8C\u6574\u5B50\u5E94\u7528\u4E0D\u8981\u7528 remoteComponent \u76F4\u6E32\u67D3\uFF0C\u6539\u7528\u5E94\u7528\u6865\u63A5\uFF08defineBridgeApp/createVueBridgeApp\uFF09\u3002\u6838\u5B9E\u624B\u6BB5\uFF1Awindow.__FULGURJS_SCOPE__.default.vue \u67E5\u770B\u5B9E\u9645\u6536\u655B\u6761\u76EE\u4E0E\u6765\u6E90\u3002`
366
+ `\u73B0\u8C61\uFF1A\u6D88\u8D39\u65B9\u76F4\u6E32\u67D3\u8FDC\u7A0B\u7EC4\u4EF6 "${spec}" \u65F6\uFF0C\u5F53\u524D\u7EC4\u4EF6\u5B9E\u9645\u5BFC\u5165\u7684 Vue ${key} \u4E0E\u6E32\u67D3\u5668\u4E0D\u662F\u540C\u4E00\u5F15\u7528\uFF08\u6E32\u67D3\u5668\u7248\u672C ${import_vue.version}\uFF09\u3002
367
+ \u6839\u56E0\uFF08\u5DF2\u8BC1\u5B9E\uFF09\uFF1A\u7F16\u8BD1\u540E\u7684\u5F53\u524D SFC \u5BFC\u5165\u5F15\u7528\u4E0E\u6D88\u8D39\u65B9\u6E32\u67D3\u5668\u4E0D\u4E00\u81F4\uFF1B\u6B64\u5224\u65AD\u4E0D\u4F7F\u7528\u9ED8\u8BA4\u5171\u4EAB\u4F5C\u7528\u57DF\uFF0C\u4E5F\u4E0D\u628A\u7248\u672C\u53F7\u76F8\u540C\u5F53\u4F5C\u5B9E\u4F8B\u76F8\u540C\u3002
368
+ \u4FEE\u6CD5\uFF1A\u6838\u5BF9\u8BE5\u7EC4\u4EF6\u4E0E\u6D88\u8D39\u65B9\u7684 shared.vue\u3001shareScope \u548C dev \u4F9D\u8D56\u89E3\u6790\uFF0C\u4F7F\u540C\u4E00\u6E32\u67D3\u94FE\u6536\u655B\u5230\u540C\u4E00 Vue\uFF1B\u9700\u8981\u72EC\u7ACB\u8FD0\u884C\u65F6\u7684\u5B8C\u6574\u5B50\u5E94\u7528\u5E94\u4F7F\u7528 defineBridgeApp/createVueBridgeApp\u3002\u7EC4\u4EF6\u8FD0\u884C\u65F6\u7684\u7248\u672C\u82E5\u672A\u53D6\u5F97\u53EF\u9760\u8BC1\u636E\uFF0C\u4E0D\u636E\u5171\u4EAB\u8868\u731C\u6D4B\u3002`
361
369
  ),
362
370
  {
363
371
  code: ErrorCodes.VUE_RUNTIME_IDENTITY_MISMATCH,
364
- details: { remote: spec.slice(0, spec.indexOf("/")) || spec, module: spec.slice(spec.indexOf("/") + 1) || void 0, rendererVueVersion: import_vue.version, sharedVueVersion: sharedVue.version }
372
+ details: {
373
+ remote: remoteNameOf(spec),
374
+ module: moduleNameOf(spec),
375
+ stage: "adapter",
376
+ rendererVueVersion: import_vue.version,
377
+ runtimeBinding: key,
378
+ evidenceSource: "compiled-sfc-import"
379
+ }
365
380
  }
366
381
  );
367
382
  }
@@ -407,7 +422,7 @@ var RemoteErrorPlaceholder = /* @__PURE__ */ (0, import_vue.defineComponent)({
407
422
  return () => {
408
423
  const err = props.error;
409
424
  const code = err?.code ?? "UNKNOWN";
410
- const message = err?.message ?? String(props.error ?? "unknown error");
425
+ const message = diagnosticMessage(err ?? props.error ?? "unknown error");
411
426
  const buttons = [
412
427
  props.retry ? (0, import_vue.h)("button", {
413
428
  key: "retry",
@@ -614,7 +629,7 @@ function createRemoteComponent(loadRemote) {
614
629
  reportRemoteObservation({ remote: remoteNameOf(spec), error: err });
615
630
  throw err;
616
631
  }
617
- const identity = vueRuntimeIdentityError(spec);
632
+ const identity = vueRuntimeIdentityError(spec, inner);
618
633
  if (identity) {
619
634
  reportRemoteObservation({ remote: remoteNameOf(spec), error: identity });
620
635
  throw identity;
@@ -664,7 +679,7 @@ function createHostPages(options, load) {
664
679
  reportRemoteObservation({ remote: remoteNameOf(spec), error: err });
665
680
  throw err;
666
681
  }
667
- const identity = vueRuntimeIdentityError(spec);
682
+ const identity = vueRuntimeIdentityError(spec, inner);
668
683
  if (identity) {
669
684
  reportRemoteObservation({ remote: remoteNameOf(spec), error: identity });
670
685
  throw identity;
@@ -9,14 +9,15 @@ import {
9
9
  reportRemoteObservation,
10
10
  resolvePageProviderEntries,
11
11
  shouldResetSessionCache
12
- } from "./chunk-2OHKAD6I.js";
12
+ } from "./chunk-7OOPFHL3.js";
13
13
  import "./chunk-TSXZ7TWA.js";
14
14
  import {
15
- ErrorCodes
16
- } from "./chunk-YHXQHZ3E.js";
15
+ ErrorCodes,
16
+ diagnosticMessage
17
+ } from "./chunk-5ZXA4FPA.js";
17
18
 
18
19
  // src/vue-adapter.ts
19
- import { defineAsyncComponent, defineComponent, getCurrentInstance, h, onErrorCaptured, ref, shallowRef, onActivated, onUnmounted, version as vueRuntimeVersion } from "vue";
20
+ import { defineAsyncComponent, defineComponent, getCurrentInstance, h, onErrorCaptured, ref, openBlock, createVNode, createElementVNode, shallowRef, onActivated, onUnmounted, version as vueRuntimeVersion } from "vue";
20
21
  function isVueRenderableComponent(inner) {
21
22
  if (!inner) return false;
22
23
  if (typeof inner === "function") return true;
@@ -24,19 +25,28 @@ function isVueRenderableComponent(inner) {
24
25
  const c = inner;
25
26
  return typeof c.render === "function" || typeof c.setup === "function" || typeof c.template === "string";
26
27
  }
27
- function vueRuntimeIdentityError(spec) {
28
- const sharedVue = globalThis.__FULGURJS_RUNTIME__?.getLoadedShare?.("vue");
29
- if (!sharedVue || typeof sharedVue.ref !== "function" || typeof sharedVue.version !== "string") return void 0;
30
- if (sharedVue.ref === ref) return void 0;
28
+ function vueRuntimeIdentityError(spec, component) {
29
+ const bindings = { ref, openBlock, createVNode, createElementVNode, defineComponent, h };
30
+ const evidence = component[/* @__PURE__ */ Symbol.for("fulgurjs.vue-runtime")];
31
+ const key = evidence?.key;
32
+ if (!key || !Object.hasOwn(bindings, key) || typeof evidence?.value !== "function") return void 0;
33
+ if (bindings[key] === evidence.value) return void 0;
31
34
  return Object.assign(
32
35
  new Error(
33
- `\u73B0\u8C61\uFF1A\u6D88\u8D39\u65B9\u76F4\u6E32\u67D3\u8FDC\u7A0B\u7EC4\u4EF6 "${spec}" \u65F6\uFF0C\u68C0\u6D4B\u5230\u6E32\u67D3\u5668\u4F7F\u7528\u7684 Vue \u4E0E\u5171\u4EAB\u4F5C\u7528\u57DF\u5B9E\u9645\u6536\u655B\u7684 Vue \u4E0D\u662F\u540C\u4E00\u5B9E\u4F8B\uFF08\u6E32\u67D3\u94FE ${vueRuntimeVersion}\uFF0C\u5171\u4EAB\u5B9E\u4F8B ${sharedVue.version}\uFF1B\u7248\u672C\u53F7\u76F8\u540C\u4E5F\u4E0D\u4EE3\u8868\u5B9E\u4F8B\u76F8\u540C\uFF09\u3002
34
- \u6839\u56E0\uFF08\u5DF2\u8BC1\u5B9E\uFF09\uFF1A\u53CC\u65B9\u81F3\u5C11\u4E00\u65B9\u58F0\u660E\u4E86 shared.vue\uFF0C\u4F46\u6D88\u8D39\u65B9\u81EA\u8EAB\u7684 vue \u5BFC\u5165\u6CA1\u6709\u6536\u655B\u5230\u540C\u4E00\u5B9E\u4F8B\u2014\u2014\u5E38\u89C1\u4E8E\u6D88\u8D39\u65B9\u672A\u58F0\u660E shared.vue\u3001dev \u9884\u6784\u5EFA/optimizeDeps \u7ED5\u8FC7\u5171\u4EAB\u95E8\u9762\u3001\u6216 shareScope \u4E0D\u4E00\u81F4\u3002\u5B9E\u4F8B\u5206\u88C2\u65F6 inject/provide/Pinia/getCurrentInstance \u8DE8\u5B9E\u4F8B\u65AD\u94FE\uFF0C\u9875\u9762\u5E38\u8868\u73B0\u4E3A\u5916\u58F3\u5728\u3001\u5185\u90E8\u7A7A\u767D\u4E14\u65E0 pageerror\u3002
35
- \u4FEE\u6CD5\uFF1A\u2460 \u6D88\u8D39\u65B9\u4E0E\u8FDC\u7A0B\u90FD\u5728 federation({ shared }) \u58F0\u660E vue\uFF08singleton \u5EFA\u8BAE\u5F00\u542F\uFF09\u5E76\u4F7F\u7528\u540C\u4E00 shareScope\uFF1B\u2461 dev \u4E0B\u786E\u8BA4\u63D2\u4EF6\u7248\u672C\u4E00\u81F4\u3001\u672A\u7528 optimizeDeps \u628A vue \u9884\u6784\u5EFA\u6210\u7B2C\u4E8C\u4EFD\u526F\u672C\uFF1B\u2462 \u9700\u8981\u72EC\u7ACB Vue \u8FD0\u884C\u65F6\u7684\u5B8C\u6574\u5B50\u5E94\u7528\u4E0D\u8981\u7528 remoteComponent \u76F4\u6E32\u67D3\uFF0C\u6539\u7528\u5E94\u7528\u6865\u63A5\uFF08defineBridgeApp/createVueBridgeApp\uFF09\u3002\u6838\u5B9E\u624B\u6BB5\uFF1Awindow.__FULGURJS_SCOPE__.default.vue \u67E5\u770B\u5B9E\u9645\u6536\u655B\u6761\u76EE\u4E0E\u6765\u6E90\u3002`
36
+ `\u73B0\u8C61\uFF1A\u6D88\u8D39\u65B9\u76F4\u6E32\u67D3\u8FDC\u7A0B\u7EC4\u4EF6 "${spec}" \u65F6\uFF0C\u5F53\u524D\u7EC4\u4EF6\u5B9E\u9645\u5BFC\u5165\u7684 Vue ${key} \u4E0E\u6E32\u67D3\u5668\u4E0D\u662F\u540C\u4E00\u5F15\u7528\uFF08\u6E32\u67D3\u5668\u7248\u672C ${vueRuntimeVersion}\uFF09\u3002
37
+ \u6839\u56E0\uFF08\u5DF2\u8BC1\u5B9E\uFF09\uFF1A\u7F16\u8BD1\u540E\u7684\u5F53\u524D SFC \u5BFC\u5165\u5F15\u7528\u4E0E\u6D88\u8D39\u65B9\u6E32\u67D3\u5668\u4E0D\u4E00\u81F4\uFF1B\u6B64\u5224\u65AD\u4E0D\u4F7F\u7528\u9ED8\u8BA4\u5171\u4EAB\u4F5C\u7528\u57DF\uFF0C\u4E5F\u4E0D\u628A\u7248\u672C\u53F7\u76F8\u540C\u5F53\u4F5C\u5B9E\u4F8B\u76F8\u540C\u3002
38
+ \u4FEE\u6CD5\uFF1A\u6838\u5BF9\u8BE5\u7EC4\u4EF6\u4E0E\u6D88\u8D39\u65B9\u7684 shared.vue\u3001shareScope \u548C dev \u4F9D\u8D56\u89E3\u6790\uFF0C\u4F7F\u540C\u4E00\u6E32\u67D3\u94FE\u6536\u655B\u5230\u540C\u4E00 Vue\uFF1B\u9700\u8981\u72EC\u7ACB\u8FD0\u884C\u65F6\u7684\u5B8C\u6574\u5B50\u5E94\u7528\u5E94\u4F7F\u7528 defineBridgeApp/createVueBridgeApp\u3002\u7EC4\u4EF6\u8FD0\u884C\u65F6\u7684\u7248\u672C\u82E5\u672A\u53D6\u5F97\u53EF\u9760\u8BC1\u636E\uFF0C\u4E0D\u636E\u5171\u4EAB\u8868\u731C\u6D4B\u3002`
36
39
  ),
37
40
  {
38
41
  code: ErrorCodes.VUE_RUNTIME_IDENTITY_MISMATCH,
39
- details: { remote: spec.slice(0, spec.indexOf("/")) || spec, module: spec.slice(spec.indexOf("/") + 1) || void 0, rendererVueVersion: vueRuntimeVersion, sharedVueVersion: sharedVue.version }
42
+ details: {
43
+ remote: remoteNameOf(spec),
44
+ module: moduleNameOf(spec),
45
+ stage: "adapter",
46
+ rendererVueVersion: vueRuntimeVersion,
47
+ runtimeBinding: key,
48
+ evidenceSource: "compiled-sfc-import"
49
+ }
40
50
  }
41
51
  );
42
52
  }
@@ -82,7 +92,7 @@ var RemoteErrorPlaceholder = /* @__PURE__ */ defineComponent({
82
92
  return () => {
83
93
  const err = props.error;
84
94
  const code = err?.code ?? "UNKNOWN";
85
- const message = err?.message ?? String(props.error ?? "unknown error");
95
+ const message = diagnosticMessage(err ?? props.error ?? "unknown error");
86
96
  const buttons = [
87
97
  props.retry ? h("button", {
88
98
  key: "retry",
@@ -289,7 +299,7 @@ function createRemoteComponent(loadRemote) {
289
299
  reportRemoteObservation({ remote: remoteNameOf(spec), error: err });
290
300
  throw err;
291
301
  }
292
- const identity = vueRuntimeIdentityError(spec);
302
+ const identity = vueRuntimeIdentityError(spec, inner);
293
303
  if (identity) {
294
304
  reportRemoteObservation({ remote: remoteNameOf(spec), error: identity });
295
305
  throw identity;
@@ -339,7 +349,7 @@ function createHostPages(options, load) {
339
349
  reportRemoteObservation({ remote: remoteNameOf(spec), error: err });
340
350
  throw err;
341
351
  }
342
- const identity = vueRuntimeIdentityError(spec);
352
+ const identity = vueRuntimeIdentityError(spec, inner);
343
353
  if (identity) {
344
354
  reportRemoteObservation({ remote: remoteNameOf(spec), error: identity });
345
355
  throw identity;
@@ -1,4 +1,4 @@
1
1
  /** Explicit ownership for Pinia-like store definitions; no Pinia dependency or global switching. */
2
- declare function bindStoreToApp<T extends (...args: never[]) => unknown>(useStore: T, pinia: Parameters<T>[0] | (() => Parameters<T>[0])): T;
2
+ declare function bindStoreToApp<T extends (...args: any[]) => any>(useStore: T, pinia: NoInfer<Parameters<T>[0]> | (() => NoInfer<Parameters<T>[0]>)): T;
3
3
 
4
4
  export { bindStoreToApp };
@@ -1,4 +1,4 @@
1
1
  /** Explicit ownership for Pinia-like store definitions; no Pinia dependency or global switching. */
2
- declare function bindStoreToApp<T extends (...args: never[]) => unknown>(useStore: T, pinia: Parameters<T>[0] | (() => Parameters<T>[0])): T;
2
+ declare function bindStoreToApp<T extends (...args: any[]) => any>(useStore: T, pinia: NoInfer<Parameters<T>[0]> | (() => NoInfer<Parameters<T>[0]>)): T;
3
3
 
4
4
  export { bindStoreToApp };
package/dist/vue.d.ts CHANGED
@@ -779,7 +779,7 @@ declare function createBridgeSession(options?: {
779
779
  }): BridgeSession;
780
780
 
781
781
  /** Explicit ownership for Pinia-like store definitions; no Pinia dependency or global switching. */
782
- declare function bindStoreToApp<T extends (...args: never[]) => unknown>(useStore: T, pinia: Parameters<T>[0] | (() => Parameters<T>[0])): T;
782
+ declare function bindStoreToApp<T extends (...args: any[]) => any>(useStore: T, pinia: NoInfer<Parameters<T>[0]> | (() => NoInfer<Parameters<T>[0]>)): T;
783
783
 
784
784
  declare const remoteComponent: <S extends string>(spec: S & FgComponentEntry<S>, opts?: RemoteComponentOptions) => FgRemoteVueComponent<S>;
785
785
  /** 宿主页面适配器(绑定本包运行时的 loadRemote;选项与返回值类型见 vue-adapter) */
@@ -72,7 +72,7 @@
72
72
  | `MFU-013` | Runtime reports the remote declares onSession but the host AppContext lacks sessionKey | The host did not provide a non-sensitive login generation ID (never use a token as one) | In the host login flow call `provideAppContext({ sessionKey })` — generate a new value on every successful login/re-login; token refreshes keep it |
73
73
  | `MFU-014` | Runtime reports a recursive loadRemote of the same remote inside setup/onSession's synchronous segment | Loading a module of the same remote inside the initialization's synchronous segment — the call waits on itself, deadlocking | Do not load same-remote modules inside initialization; put cross-remote loads in the async segment |
74
74
  | `MFU-018` | remoteComponent / host-pages component consumption reports "the export is not a renderable component" (with the actual export shape) | The exposes target exports a plain module/constant/non-renderable object — a successful module load does not mean a usable component | Point exposes at an `export default` component (Vue: defineComponent / `<script setup>` / functional; React: function component or memo/forwardRef); to consume a plain module use `loadRemote` instead |
75
- | `MFU-019` | Vue component direct rendering reports "the renderer and the Vue instance converged in the share scope are not the same instance" (with renderer/shared instance versions) | Proven instance split: at least one side declared shared.vue, but the consumer's vue import did not converge onto the same instance (shared.vue not declared, dev prebundling bypassing the facade, or mismatched shareScope). With split instances inject/Pinia/getCurrentInstance break across instances — typically "shell renders, inner blank, no pageerror" | Both sides declare vue in `shared` (singleton recommended) with the same shareScope; in dev verify vue was not prebundled into a second copy; full sub apps that need an independent Vue runtime must use app bridging instead of remoteComponent direct rendering. Verify via `window.__FULGURJS_SCOPE__.default.vue` |
75
+ | `MFU-019` | The current remote SFC imports a different Vue function identity from the consumer renderer | The compiler retains non-enumerable evidence from an actual Vue import in that SFC. The adapter compares the matching renderer export; it does not infer component identity from the default share scope. Equal versions do not prove equal instances | Check shared.vue, shareScope and dependency resolution; use app bridging for independent renderers. Older remotes, plain TS components, frozen components or unsupported import forms may have no evidence: they are not automatically rejected or declared converged. Use business signals and actual dependency evidence. Details identify the adapter stage, runtimeBinding and evidenceSource; unknown remote versions are not guessed |
76
76
  | `MFU-020` | The remote component subtree threw internally (its own setup/render/nested async components, including cases the region goes blank after a business errorHandler takes over) | The error originates from the remote component's own code, unrelated to federation module loading. Reported observably via `fulgurjs:error`/`onRemoteError`: the original exception is preserved in `cause`, `details.phase='render'` plus Vue's render-stage info (e.g. setup function / render function / async component loader) | Inspect the original stack on `cause` to locate the failing remote component code. To display and recover in place, pass `renderErrorComponent` to `remoteComponent`/`createHostPages` (it receives `error`/`retry` props, owns the display so the error stops propagating globally, and retry remounts the remote component); by default only observation reporting happens and business errorHandler behavior is unchanged |
77
77
  | `MFU-015` | Runtime reports an illegal bridge contract (the `./bridge` default export lacks mount/unmount or they are not functions) | The module exposed as `./bridge` was not built with `defineBridgeApp` | Build the child app entry's default export with `defineBridgeApp(...)` (see [sub app bridge](../guide/app-bridge.md)) |
78
78
  | `MFU-016` | Runtime reports bridge preparation or lifecycle failure (`details.phase` distinguishes getContext/mount/unmount; the root cause carries the child app's original error) | getContext returned a Promise/non-object, mount threw before the first commit, or unmount cleanup threw | Troubleshoot the child app code by phase: getContext must return a synchronous snapshot object; on mount failure clean up the app/root before throwing; fix unmount's cleanup logic — a container whose unmount threw is persistently locked out; recover with a full page refresh |
@@ -71,7 +71,7 @@
71
71
  | `MFU-013` | 运行时报远程声明 onSession 但宿主 AppContext 缺 sessionKey | 宿主未提供非敏感登录代次 ID(禁止用 token 充当) | 宿主登录流程 `provideAppContext({ sessionKey })`——每次成功登录/重登生成新值,token 刷新沿用 |
72
72
  | `MFU-014` | 运行时报 setup/onSession 同步段内递归 loadRemote 同一远程 | 初始化同步段内加载同远程模块——该调用会等待自身形成死锁 | 初始化内不要加载同远程模块;跨远程加载放异步段 |
73
73
  | `MFU-018` | remoteComponent/宿主页面组件消费时报「导出的不是可渲染组件」(附实际导出形态) | 该 exposes 指向的文件导出了普通模块/常量/不可渲染对象——模块加载成功不等于组件可用 | exposes 指向 `export default` 组件(Vue:defineComponent/`<script setup>`/函数式;React:函数组件或 memo/forwardRef);消费普通模块改用 `loadRemote` |
74
- | `MFU-019` | Vue 组件直渲染时报「渲染器与共享作用域收敛的 Vue 实例不一致」(附渲染链/共享实例双版本) | 已证实的实例分裂:至少一方声明 shared.vue,但消费方 vue 导入未收敛到同一实例(未声明 shared.vue、dev 预构建绕过门面、shareScope 不一致)。实例分裂时 inject/Pinia/getCurrentInstance 跨实例断链,常见「外壳在、内部空白且无 pageerror」 | 两侧 `shared` 均声明 vue(建议 singleton)且 shareScope 一致;dev 核对未把 vue 预构建成第二份;需独立 Vue 运行时的完整子应用改用应用桥接,不要 remoteComponent 直渲染。核实:`window.__FULGURJS_SCOPE__.default.vue` |
74
+ | `MFU-019` | 当前远程 SFC 的 Vue 导入引用与消费方渲染器不同 | 编译器从当前 SFC 实际导入的 Vue 函数保存非枚举身份依据,适配器与消费方同名函数比较;不从默认共享表推断当前组件身份。版本相同不等于实例相同 | 核对组件和消费方的 shared.vue、shareScope 与依赖解析;独立 renderer 用应用桥接。旧远程、普通 TS 组件、冻结组件或不支持的导入形态可能没有依据,此时不自动拒绝,也不宣称已确认收敛;结合业务信号与实际依赖取证。details 给出 adapter 阶段、runtimeBinding 与 evidenceSource;未知远程版本不猜测 |
75
75
  | `MFU-020` | 远程组件子树内部抛错(其 setup/render/嵌套异步组件;含错误被业务 errorHandler 接管后区域空白的场景) | 错误抛自远程组件代码本身,与联邦模块加载无关。经 `fulgurjs:error`/`onRemoteError` 观测上报:原始异常保留在 `cause`,`details.phase='render'` 并附 Vue 渲染阶段串(如 setup function / render function / async component loader) | 查看 `cause` 的原始调用栈定位远程组件内部代码。需要在该组件位置直接展示并提供恢复时,为 `remoteComponent`/`createHostPages` 传 `renderErrorComponent`(收到 `error`/`retry` props,接管展示后错误不再向全局传播,retry 重新挂载远程组件);默认仅观测上报,不改变业务 errorHandler 行为 |
76
76
  | `MFU-015` | 运行时报桥接契约非法(`./bridge` 默认导出缺 mount/unmount 或非函数) | expose `./bridge` 的模块没有用 `defineBridgeApp` 构造契约对象 | 子应用入口改用 `defineBridgeApp(...)` 默认导出(见[子应用桥接](../guide/app-bridge.md)) |
77
77
  | `MFU-016` | 运行时报桥接准备或生命周期失败(`details.phase` 区分 getContext/mount/unmount;根因含子应用原始错误) | getContext 返回 Promise/非对象、mount 首次提交前抛错、或 unmount 清理抛错 | 按 phase 排查子应用代码:getContext 返回同步快照对象;mount 失败先清理 app/root 再抛;unmount 修复清理逻辑——unmount 抛错的容器被持久封锁,整页刷新恢复 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fulgurjs/federation",
3
- "version": "6.13.1",
3
+ "version": "6.13.3",
4
4
  "type": "module",
5
5
  "description": "Vite Module Federation for Vue and React: remote modules, shared dependencies and app bridges.",
6
6
  "license": "MIT",