@fulgurjs/federation 6.0.0 → 6.1.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 +15 -0
- package/dist/bridge-router-react.d.ts +18 -1
- package/dist/bridge-router-react.js +14 -2
- package/dist/index.cjs +2 -2
- package/dist/index.js +2 -2
- package/dist/react-adapter.d.cts +7 -0
- package/dist/react-adapter.d.ts +7 -0
- package/dist/react.d.ts +36 -1
- package/dist/runtime-entry.d.ts +18 -0
- package/dist/runtime.js +19 -17
- package/dist/vue-adapter.cjs +13 -1
- package/dist/vue-adapter.d.cts +1 -0
- package/dist/vue-adapter.d.ts +1 -0
- package/dist/vue-adapter.js +14 -2
- package/dist/vue.d.ts +18 -0
- package/docs/en/reference/api.md +24 -3
- package/docs/zh/reference/api.md +21 -3
- package/examples/templates/react-host-vue-remote/pnpm-lock.yaml +7 -7
- package/examples/templates/react-react/pnpm-lock.yaml +7 -7
- package/examples/templates/showcase/pnpm-lock.yaml +11 -11
- package/examples/templates/vue-host-react-remote/pnpm-lock.yaml +7 -7
- package/examples/templates/vue-vue/pnpm-lock.yaml +7 -7
- package/package.json +1 -1
package/dist/runtime.js
CHANGED
|
@@ -1,28 +1,30 @@
|
|
|
1
|
-
var ve=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function
|
|
2
|
-
\u539F\u56E0\uFF1A${String(
|
|
3
|
-
\u4FEE\u6CD5\uFF1A\u68C0\u67E5\u5E76\u4FEE\u590D\u8BE5 ${o} \u51FD\u6570\u540E\u91CD\u65B0\u52A0\u8F7D\uFF1B\u5931\u8D25\u7F13\u5B58\u5DF2\u6E05\u9664\uFF0C\u53EF\u4EE5\u76F4\u63A5\u91CD\u8BD5\u3002`,{remote:e,phase:o},{cause:
|
|
1
|
+
var ve=/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-((?:[0-9A-Za-z-]+)(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/;function C(l){let f=ve.exec(String(l).trim());return f?{major:Number(f[1]),minor:Number(f[2]??0),patch:Number(f[3]??0),pre:f[4]?f[4].split("."):[]}:null}function $e(l,f){if(l.length===0&&f.length===0)return 0;if(l.length===0)return 1;if(f.length===0)return-1;let d=Math.max(l.length,f.length);for(let c=0;c<d;c++){let g=l[c],y=f[c];if(g===void 0)return-1;if(y===void 0)return 1;let b=/^\d+$/.test(g),v=/^\d+$/.test(y);if(b&&v){let A=Number(g)-Number(y);if(A!==0)return A}else{if(b!==v)return b?-1:1;if(g!==y)return g<y?-1:1}}return 0}function T(l,f){let d=C(l),c=C(f);return!d||!c?l<f?-1:l>f?1:0:d.major!==c.major?d.major-c.major:d.minor!==c.minor?d.minor-c.minor:d.patch!==c.patch?d.patch-c.patch:$e(d.pre,c.pre)}var Pe=/^[a-z]+[+:-]/i;function x(l,f){if(f===!1||f==null||f==="")return!0;let d=String(f).trim();return!d||d==="*"||d==="latest"||Pe.test(d)?!0:d.split("||").some(c=>_e(l,c.trim()))}function _e(l,f){if(!f||f==="*")return!C(l)?.pre.length;let d=f.split(/\s+-\s+/);if(d.length===2){let y=d[0].trim(),b=d[1].trim();return!(!x(l,`>=${y}`)||!x(l,`<=${b}`))}let c=C(l);if(!c)return!1;let g=ke(f);if(g===null)return!0;for(let y of g)if(!Ie(c,l,y))return!1;return!(c.pre.length>0&&!g.some(y=>y.ver.pre.length>0)&&!g.some(b=>b.ver.major===c.major&&b.ver.minor===c.minor&&b.ver.patch===c.patch))}function ke(l){let f=[],d=l.trim().split(/\s+/).filter(Boolean);if(d.length===0)return null;for(let c of d){let g=/^(>=|<=|>|<|=|\^|~)?(.*)$/.exec(c);if(!g)return null;let y=g[1],b=g[2],v=Le(y,b);if(v===null)return null;f.push(...v)}return f}function Le(l,f){let d=Me(f);if(!d)return null;let{ver:c,partial:g}=d;switch(l){case"^":{let y=Oe(c);return y?[{op:">=",ver:c},{op:"<",ver:y}]:null}case"~":{let y=g>=2?{major:c.major,minor:c.minor+1,patch:0,pre:[]}:{major:c.major+1,minor:0,patch:0,pre:[]};return[{op:">=",ver:c},{op:"<",ver:y}]}case">=":return[{op:">=",ver:c}];case">":return g===1?[{op:">=",ver:{major:c.major+1,minor:0,patch:0,pre:[]}}]:g===2?[{op:">=",ver:{major:c.major,minor:c.minor+1,patch:0,pre:[]}}]:[{op:">",ver:c}];case"<":return g===1?[{op:"<",ver:{major:c.major,minor:0,patch:0,pre:[]}}]:g===2?[{op:"<",ver:{major:c.major,minor:c.minor,patch:0,pre:[]}}]:[{op:"<",ver:c}];case"<=":return[{op:"<=",ver:c}];case"=":case void 0:return g===1?[{op:">=",ver:c},{op:"<",ver:{major:c.major+1,minor:0,patch:0,pre:[]}}]:g===2?[{op:">=",ver:c},{op:"<",ver:{major:c.major,minor:c.minor+1,patch:0,pre:[]}}]:[{op:"=",ver:c}];default:return null}}function Oe(l){return l.major>0?{major:l.major+1,minor:0,patch:0,pre:[]}:l.minor>0?{major:0,minor:l.minor+1,patch:0,pre:[]}:{major:0,minor:0,patch:l.patch+1,pre:[]}}function Me(l){let f=l.replace(/^v/,"").trim();if(!f||f==="*"||f==="x"||f==="X")return{ver:{major:0,minor:0,patch:0,pre:[]},partial:0};let d=f.split("."),c=[],g=0;for(let v of d.slice(0,3))if(/^\d+$/.test(v))c.push(Number(v)),g++;else{if(v==="x"||v==="X"||v==="*")break;break}let y=f.split("-"),b=y.length>1?y.slice(1).join("-").split("+")[0].split("."):[];return g===0&&b.length===0?{ver:{major:0,minor:0,patch:0,pre:[]},partial:0}:{ver:{major:c[0]??0,minor:c[1]??0,patch:c[2]??0,pre:b},partial:g}}function Ae(l,f){switch(f){case">=":return l>=0;case">":return l>0;case"<":return l<0;case"<=":return l<=0;case"=":return l===0}}function Ie(l,f,d){let c=`${l.major}.${l.minor}.${l.patch}`+(l.pre.length?`-${l.pre.join(".")}`:"");if(d.upper)return!(!(T(c,`${d.ver.major}.${d.ver.minor}.${d.ver.patch}`+(d.ver.pre.length?`-${d.ver.pre.join(".")}`:""))>=0)||!(T(c,`${d.upper.major}.${d.upper.minor}.${d.upper.patch}`)<0));let g=T(c,`${d.ver.major}.${d.ver.minor}.${d.ver.patch}`+(d.ver.pre.length?`-${d.ver.pre.join(".")}`:"")),y=Ae(g,d.op);return d.ver.pre.length>0&&l.pre.length===0&&(d.op===">"||d.op==="<")?!1:y}var w=class extends Error{code;details;constructor(f,d,c,g){super(`[fulgurjs:${f}] ${d}`,g),this.name="FgError",this.code=f,this.details=c}},E={REMOTE_LOAD_FAILED:"MFU-001",REMOTE_NAME_MISMATCH:"MFU-002",SHARE_STRICT_VERSION:"MFU-003",SHARE_NOT_AVAILABLE:"MFU-004",CONTAINER_REINIT_CONFLICT:"MFU-005",MODULE_NOT_EXPOSED:"MFU-006",PRELOAD_FAILED:"MFU-007",REMOTE_UNKNOWN:"MFU-008",EMPTY_EXPORTS:"MFU-009",SINGLETON_SKEW:"MFU-010",SETUP_INVALID_EXPORT:"MFU-011",SETUP_RUN_FAILED:"MFU-012",SETUP_SESSION_KEY_MISSING:"MFU-013",SETUP_RECURSION:"MFU-014"};var te="6.1.0";var Te="__fulgurjsSetup",xe="__FULGURJS_APP_CONFIG__",H=15e3,oe=2,je=5,Ce=3e4,Ne=4e3,Ue=.2;function Ve(){let l=Object.create(null),f=new Map,d=[],c=new Set,g=new Map,y=(e,r)=>JSON.stringify([r.shareScope||"default",r.shareKey||e,r.requiredVersion??null,!!r.singleton,!!r.strictVersion]),b=new Map,v=new Map,A=new WeakMap,N=new WeakMap,_={},ie=()=>{for(let e of d)try{e.init?.(_)}catch(r){console.warn("[fulgurjs] \u8FD0\u884C\u65F6\u6269\u5C55\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u8BE5\u6269\u5C55\u5C06\u4E0D\u53EF\u7528\uFF1A",e.name,r)}},U=new Map,V,G=e=>{let r=U.get(e);return r||U.set(e,r={}),r},B=()=>globalThis[xe]??{};async function J(e,r,n,o){let t=u=>u instanceof w?u:new w(E.SETUP_RUN_FAILED,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e}" \u7684 ${o} \u521D\u59CB\u5316\u5931\u8D25\u3002
|
|
2
|
+
\u539F\u56E0\uFF1A${String(u?.message??u)}
|
|
3
|
+
\u4FEE\u6CD5\uFF1A\u68C0\u67E5\u5E76\u4FEE\u590D\u8BE5 ${o} \u51FD\u6570\u540E\u91CD\u65B0\u52A0\u8F7D\uFF1B\u5931\u8D25\u7F13\u5B58\u5DF2\u6E05\u9664\uFF0C\u53EF\u4EE5\u76F4\u63A5\u91CD\u8BD5\u3002`,{remote:e,phase:o},{cause:u});V=e;let s;try{s=r(n)}catch(u){throw t(u)}finally{V=void 0}try{await s}catch(u){throw t(u)}}async function ae(e,r,n,o){e.debug.setup="pending";try{if(e.manifestUrl)try{await q(`${e.name}/${n}`)}catch{}let t=await r.get(n),s=t?.default;if(typeof s!="function")throw new w(E.SETUP_INVALID_EXPORT,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u7684 setup \u6A21\u5757 "${n}" \u65E0\u6CD5\u521D\u59CB\u5316\u3002
|
|
4
4
|
\u539F\u56E0\uFF1A\u9ED8\u8BA4\u5BFC\u51FA\u7C7B\u578B\u4E3A ${t==null?String(t):typeof s}\uFF0C\u5E94\u4E3A\u51FD\u6570\u3002
|
|
5
|
-
\u4FEE\u6CD5\uFF1A\u5728 setup \u6307\u5411\u7684\u6587\u4EF6\u4E2D\u9ED8\u8BA4\u5BFC\u51FA\u51FD\u6570\uFF0C\u4F8B\u5982 export default async function setup(context) { ... }\uFF1B\u5177\u540D onSession \u53EF\u9009\u3002`,{remote:e.name,module:n});if(t.onSession!==void 0&&typeof t.onSession!="function")throw new E
|
|
5
|
+
\u4FEE\u6CD5\uFF1A\u5728 setup \u6307\u5411\u7684\u6587\u4EF6\u4E2D\u9ED8\u8BA4\u5BFC\u51FA\u51FD\u6570\uFF0C\u4F8B\u5982 export default async function setup(context) { ... }\uFF1B\u5177\u540D onSession \u53EF\u9009\u3002`,{remote:e.name,module:n});if(t.onSession!==void 0&&typeof t.onSession!="function")throw new w(E.SETUP_INVALID_EXPORT,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u7684 setup \u6A21\u5757 "${n}" \u65E0\u6CD5\u521D\u59CB\u5316\u3002
|
|
6
6
|
\u539F\u56E0\uFF1AonSession \u5BFC\u51FA\u7C7B\u578B\u4E3A ${typeof t.onSession}\uFF0C\u5E94\u4E3A\u51FD\u6570\u3002
|
|
7
|
-
\u4FEE\u6CD5\uFF1A\u5C06 onSession \u6539\u4E3A\u5177\u540D\u5BFC\u51FA\u7684\u51FD\u6570\uFF0C\u6216\u5220\u9664\u8BE5\u5BFC\u51FA\u3002`,{remote:e.name,module:n});o.setupExports=t,
|
|
7
|
+
\u4FEE\u6CD5\uFF1A\u5C06 onSession \u6539\u4E3A\u5177\u540D\u5BFC\u51FA\u7684\u51FD\u6570\uFF0C\u6216\u5220\u9664\u8BE5\u5BFC\u51FA\u3002`,{remote:e.name,module:n});if(o.setupExports=t,t.globalComponents!==void 0){if(typeof t.globalComponents!="object"||t.globalComponents===null||Array.isArray(t.globalComponents))throw new w(E.SETUP_INVALID_EXPORT,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u7684 setup \u6A21\u5757 "${n}" \u65E0\u6CD5\u521D\u59CB\u5316\u3002
|
|
8
|
+
\u539F\u56E0\uFF1AglobalComponents \u5BFC\u51FA\u7C7B\u578B\u4E3A ${Array.isArray(t.globalComponents)?"array":typeof t.globalComponents}\uFF0C\u5E94\u4E3A\u5BF9\u8C61\uFF08\u952E=\u7EC4\u4EF6\u6CE8\u518C\u540D\uFF0C\u503C=\u7EC4\u4EF6\uFF09\u3002
|
|
9
|
+
\u4FEE\u6CD5\uFF1A\u6539\u4E3A export const globalComponents = { \u7EC4\u4EF6\u6CE8\u518C\u540D: \u7EC4\u4EF6 } \u5F62\u6001\uFF0C\u6216\u5220\u9664\u8BE5\u5BFC\u51FA\u3002`,{remote:e.name,module:n});o.globalComponents=t.globalComponents}await J(e.name,s,{appContext:B(),signal:(o.controller??=new AbortController).signal},"setup"),e.debug.setup="ready"}catch(t){throw e.debug.setup="failed",o.setupExports=void 0,o.globalComponents=void 0,t}}async function ce(e,r,n){let o=B(),t=o?.sessionKey;if(typeof t!="string"||t==="")throw new w(E.SETUP_SESSION_KEY_MISSING,`\u73B0\u8C61\uFF1A\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u58F0\u660E\u4E86 onSession\uFF0C\u4F46\u5BBF\u4E3B\u5C1A\u672A\u63D0\u4F9B\u6709\u6548\u7684 AppContext.sessionKey\u3002
|
|
8
10
|
\u539F\u56E0\uFF1A\u5F53\u524D\u503C\u4E3A ${t===void 0?"\u7F3A\u5931":JSON.stringify(t)}\u3002
|
|
9
|
-
\u4FEE\u6CD5\uFF1A\u5BBF\u4E3B\u6BCF\u6B21\u767B\u5F55\u6216\u91CD\u767B\u65F6\u751F\u6210\u65B0\u7684\u975E\u654F\u611F\u767B\u5F55\u4EE3\u6B21 ID\uFF0C\u5E76\u5728\u52A0\u8F7D\u8FDC\u7A0B\u9875\u9762\u524D\u8C03\u7528 provideAppContext({ ..., sessionKey: '\u767B\u5F55\u4EE3\u6B21 ID' })\uFF1B\u4E0D\u8981\u4F7F\u7528 token \u539F\u6587\u3002`,{remote:e.name});if(r.sessionPromise&&r.sessionKey===t)return r.sessionPromise;r.controller?.abort();let s=new AbortController;r.controller=s,r.sessionKey=t;let
|
|
10
|
-
\u539F\u56E0\uFF1A\u5E94\u7528\u8981\u6C42 ${
|
|
11
|
+
\u4FEE\u6CD5\uFF1A\u5BBF\u4E3B\u6BCF\u6B21\u767B\u5F55\u6216\u91CD\u767B\u65F6\u751F\u6210\u65B0\u7684\u975E\u654F\u611F\u767B\u5F55\u4EE3\u6B21 ID\uFF0C\u5E76\u5728\u52A0\u8F7D\u8FDC\u7A0B\u9875\u9762\u524D\u8C03\u7528 provideAppContext({ ..., sessionKey: '\u767B\u5F55\u4EE3\u6B21 ID' })\uFF1B\u4E0D\u8981\u4F7F\u7528 token \u539F\u6587\u3002`,{remote:e.name});if(r.sessionPromise&&r.sessionKey===t)return r.sessionPromise;r.controller?.abort();let s=new AbortController;r.controller=s,r.sessionKey=t;let u=r.sessionPromise?r.sessionPromise.catch(()=>{}):Promise.resolve(),i=(async()=>{await u,!s.signal.aborted&&await J(e.name,n,{appContext:o,sessionKey:t,signal:s.signal},"onSession")})();return r.sessionPromise=i,i.catch(()=>{r.sessionKey===t&&(r.sessionKey=void 0,r.sessionPromise=void 0)}),i}async function le(e,r){let n=r?.[Te];if(typeof n!="string"||n==="")return;let o=G(e.name);o.setupPromise||(o.setupPromise=ae(e,r,n,o).catch(s=>{throw o.setupPromise=void 0,s})),await o.setupPromise;let t=o.setupExports?.onSession;typeof t=="function"&&await ce(e,o,t)}function ue(){for(let e of U.values()){try{e.controller?.abort()}catch{}e.sessionKey=void 0,e.sessionPromise=void 0}}let M=e=>l[e]??=Object.create(null);function $(e){try{_.onRemoteError?.(e)}catch{}typeof window<"u"&&window.dispatchEvent(new CustomEvent("fulgurjs:error",{detail:e}))}function fe(e="default"){return M(e),l}function F(e,r,n,o,t={}){let s=M(e||"default"),u=Object.hasOwn(s,r)?s[r]:void 0,i=u&&typeof u=="object"?u:void 0;i||(i=Object.create(null),s[r]=i),!(Object.hasOwn(i,n)&&i[n])&&(i[n]={version:n,get:o,from:t.from??"unknown",eager:!!t.eager,loaded:!!t.loaded})}function de(e){let r=(n,o,t)=>{if(n===void 0)return;if(!(typeof n=="number"&&(t?Number.isInteger(n)&&n>=0&&n<=10:Number.isFinite(n)&&n>0)))throw new Error(`[fulgurjs] \u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u7684 ${o} \u914D\u7F6E\u65E0\u6548\uFF1A\u5F53\u524D\u4E3A ${String(n)}\uFF0C\u5E94\u4E3A${t?" 0 \u5230 10 \u7684\u6574\u6570":"\u5927\u4E8E 0 \u7684\u6709\u9650\u6570\u5B57"}\u3002\u8BF7\u4FEE\u6B63 registerRemote \u914D\u7F6E\u3002`)};r(e.timeout,"timeout"),r(e.retries,"retries",!0),e.breaker&&(r(e.breaker.threshold,"breaker.threshold"),r(e.breaker.resetMs,"breaker.resetMs"))}function X(e){for(let r of e){de(r);let n=f.get(r.name);f.set(r.name,{timeout:H,retries:oe,...n,...r,breakerThreshold:r.breaker?.threshold??n?.breakerThreshold??je,breakerResetMs:r.breaker?.resetMs??n?.breakerResetMs??Ce,state:n?.state??"idle",breakerState:n?.breakerState??{fails:0,openUntil:0},entryInflight:n?.entryInflight??new Map,entryFailCounts:n?.entryFailCounts??new Map,debug:n?.debug??{entry:r.entry,status:"idle",setup:"none"}})}}function me(e){X([e])}function pe(e){d.push(...e),g.clear(),ie()}function I(e,r,n=!1){let o=r.shareScope||"default",t=r.shareKey||e,u=M(o)[t]||{},i=Object.keys(u).filter(p=>!n||r.singleton||u[p].value!==void 0);if(n&&i.length===0)return;let S=r.requiredVersion,m=i.filter(p=>S===void 0||S===!1||x(p,S)),a;if(r.singleton&&i.length>0){let p=i.filter(h=>u[h].loaded);if(a=[...p.length?p:i].sort(T).pop(),!m.includes(a)){let h=u[a],L=`\u73B0\u8C61\uFF1A\u5171\u4EAB\u5355\u4F8B "${t}" \u7684\u5B9E\u9645\u7248\u672C\u4E0D\u6EE1\u8DB3\u5F53\u524D\u5E94\u7528\u8981\u6C42\u3002
|
|
12
|
+
\u539F\u56E0\uFF1A\u5E94\u7528\u8981\u6C42 ${S??"\u4EFB\u610F\u7248\u672C"}\uFF0C\u4F5C\u7528\u57DF\u4E2D\u6709 ${i.join("\u3001")}\uFF1B\u4E3A\u4FDD\u8BC1\u5168\u9875\u53EA\u4F7F\u7528\u4E00\u4E2A\u5B9E\u4F8B\uFF0C\u6700\u7EC8\u590D\u7528 ${h.from} \u63D0\u4F9B\u7684 ${a}\u3002
|
|
11
13
|
\u5F71\u54CD\uFF1A\u53EF\u80FD\u51FA\u73B0\u72B6\u6001\u4E0D\u4E00\u81F4\u6216\u8FD0\u884C\u9519\u8BEF\uFF0C\u5177\u4F53\u53D6\u51B3\u4E8E\u4E24\u7AEF API \u662F\u5426\u517C\u5BB9\u3002
|
|
12
|
-
\u4FEE\u6CD5\uFF1A\u7EDF\u4E00\u5BBF\u4E3B\u4E0E\u8FDC\u7A0B\u7684\u4F9D\u8D56\u7248\u672C\uFF0C\u6216\u6838\u5BF9\u540E\u8C03\u6574 shared.requiredVersion\uFF1B\u82E5\u5FC5\u987B\u62D2\u7EDD\u4E0D\u517C\u5BB9\u7248\u672C\uFF0C\u8BF7\u542F\u7528 strictVersion\u3002`;if(r.strictVersion){let
|
|
13
|
-
\u539F\u56E0\uFF1A\u8981\u6C42\u7248\u672C ${
|
|
14
|
-
\u4FEE\u6CD5\uFF1A\u7EDF\u4E00\u5BBF\u4E3B\u4E0E\u8FDC\u7A0B\u7684\u4F9D\u8D56\u7248\u672C\uFF0C\u6216\u4FEE\u6B63 shared.requiredVersion\u3002`);throw $({remote:t,error:
|
|
14
|
+
\u4FEE\u6CD5\uFF1A\u7EDF\u4E00\u5BBF\u4E3B\u4E0E\u8FDC\u7A0B\u7684\u4F9D\u8D56\u7248\u672C\uFF0C\u6216\u6838\u5BF9\u540E\u8C03\u6574 shared.requiredVersion\uFF1B\u82E5\u5FC5\u987B\u62D2\u7EDD\u4E0D\u517C\u5BB9\u7248\u672C\uFF0C\u8BF7\u542F\u7528 strictVersion\u3002`;if(r.strictVersion){let O=new w(E.SHARE_STRICT_VERSION,L,{shareKey:t,requiredVersion:S});throw $({remote:h.from,error:O}),O}let P=`${o}|${t}|${S??"*"}|${a}|${i.join(",")}`;c.has(P)||(c.add(P),console.warn(`[fulgurjs:MFU-010] ${L}`))}}else if(a=[...m].sort(T).pop(),!a){if(r.strictVersion){let p=new w(E.SHARE_STRICT_VERSION,`\u73B0\u8C61\uFF1A\u5171\u4EAB\u4F5C\u7528\u57DF "${o}" \u4E2D\u627E\u4E0D\u5230\u7B26\u5408\u8981\u6C42\u7684 "${t}"\u3002
|
|
15
|
+
\u539F\u56E0\uFF1A\u8981\u6C42\u7248\u672C ${S}\uFF0C\u5F53\u524D\u53EF\u7528\u7248\u672C\u4E3A ${i.join("\u3001")||"\u65E0"}\u3002
|
|
16
|
+
\u4FEE\u6CD5\uFF1A\u7EDF\u4E00\u5BBF\u4E3B\u4E0E\u8FDC\u7A0B\u7684\u4F9D\u8D56\u7248\u672C\uFF0C\u6216\u4FEE\u6B63 shared.requiredVersion\u3002`);throw $({remote:t,error:p}),p}return}return u[a]}function W(e,r,n){let o=r.localVersion;if(!o||n===void 0)return;let t=r.shareScope||"default",s=r.shareKey||e,u=M(t),i=Object.hasOwn(u,s)?u[s]:void 0;if(i&&Object.keys(i).length>0){try{let m=I(e,r);if(m&&m.value===void 0){if(m.version===o)m.value=n,m.loaded=!0;else if(r.singleton&&!m.pendingGet){F(t,s,o,()=>Promise.resolve(n),{from:"fulgurjs:local-fallback",loaded:!0});let a=u[s][o];a.value=n,a.loaded=!0}}}catch{}return}F(t,s,o,()=>Promise.resolve(n),{from:"fulgurjs:local-fallback",loaded:!0});let S=u[s]?.[o];S&&(S.value=n)}async function z(e,r={}){let n=r.shareScope||"default",o=r.shareKey||e,t=M(n)[o]||{},s=y(e,r),u=_.resolveShare?g.get(s):void 0,i=u||I(e,r);if(!i){if(r.fallback){let p=await r.fallback();return W(e,r,p),p}let a=new w(E.SHARE_NOT_AVAILABLE,`\u73B0\u8C61\uFF1A\u65E0\u6CD5\u52A0\u8F7D\u5171\u4EAB\u4F9D\u8D56 "${o}"\u3002
|
|
15
17
|
\u539F\u56E0\uFF1A\u4F5C\u7528\u57DF "${n}" \u4E2D\u6CA1\u6709\u7B26\u5408 ${r.requiredVersion??"\u4EFB\u610F\u7248\u672C"} \u8981\u6C42\u7684\u7248\u672C\uFF0C\u4E14\u672A\u914D\u7F6E\u672C\u5730\u526F\u672C\u3002
|
|
16
|
-
\u4FEE\u6CD5\uFF1A\u5728\u5BBF\u4E3B\u6216\u8FDC\u7A0B\u6CE8\u518C\u8BE5\u4F9D\u8D56\uFF0C\u6216\u4E3A shared \u914D\u7F6E\u53EF\u7528\u7684\u672C\u5730\u526F\u672C\u3002`,{shareKey:o,requiredVersion:r.requiredVersion});throw $({remote:o,error:
|
|
18
|
+
\u4FEE\u6CD5\uFF1A\u5728\u5BBF\u4E3B\u6216\u8FDC\u7A0B\u6CE8\u518C\u8BE5\u4F9D\u8D56\uFF0C\u6216\u4E3A shared \u914D\u7F6E\u53EF\u7528\u7684\u672C\u5730\u526F\u672C\u3002`,{shareKey:o,requiredVersion:r.requiredVersion});throw $({remote:o,error:a}),a}if(_.resolveShare&&!u){let a=await _.resolveShare({shareKey:o,shareScope:n,requiredVersion:r.requiredVersion,picked:i,available:Object.values(t)});a&&(i=a),g.set(s,i)}if(i.value!==void 0)return g.set(y(e,r),i),i.value;if(i.loaded=!0,!i.pendingGet)try{i.pendingGet=i.get()}catch(a){i.pendingGet=Promise.reject(a)}let S=i.pendingGet,m;try{m=await S}catch(a){if(i.value!==void 0)return g.set(y(e,r),i),i.value;throw i.loaded=!1,g.get(s)===i&&g.delete(s),a}finally{i.pendingGet===S&&(i.pendingGet=void 0)}return i.value===void 0&&(i.value=m),g.set(y(e,r),i),i.value}function ge(e,r={}){return _.resolveShare?g.get(y(e,r))?.value:I(e,r,!0)?.value}function he(e,r,n,o){W(e,{...r,localVersion:n},o)}function ye(e,r){let n=r.shareScope||"default",o=r.shareKey||e;if(_.resolveShare){let s=y(e,r),u=g.get(s);if(u&&u.value!==void 0)return{kind:"ready",value:u.value};let i=u||_.resolveShare({shareKey:o,shareScope:n,requiredVersion:r.requiredVersion,picked:I(e,r),available:Object.values(M(n)[o]||{})});if(i&&typeof i.then=="function")throw Promise.resolve(i).catch(()=>{}),new w(E.SHARE_NOT_AVAILABLE,`\u73B0\u8C61\uFF1AresolveShare \u5BF9\u5171\u4EAB "${o}" \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
|
|
17
19
|
\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
|
|
18
|
-
\u4FEE\u6CD5\uFF1AVite 8 HTML \u5165\u53E3\u4F1A\u5148\u5B8C\u6210\u5F02\u6B65\u534F\u5546\uFF1B\u5176\u4ED6\u5165\u53E3\u8BF7\u5148\u52A8\u6001 loadShare \u5EFA\u7ACB\u5FEB\u7167\uFF0C\u518D\u5BFC\u5165\u6D88\u8D39\u8005\uFF0C\u6216\u8BA9\u8BE5\u952E\u540C\u6B65\u8FD4\u56DE picked\u3002`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0});let
|
|
20
|
+
\u4FEE\u6CD5\uFF1AVite 8 HTML \u5165\u53E3\u4F1A\u5148\u5B8C\u6210\u5F02\u6B65\u534F\u5546\uFF1B\u5176\u4ED6\u5165\u53E3\u8BF7\u5148\u52A8\u6001 loadShare \u5EFA\u7ACB\u5FEB\u7167\uFF0C\u518D\u5BFC\u5165\u6D88\u8D39\u8005\uFF0C\u6216\u8BA9\u8BE5\u952E\u540C\u6B65\u8FD4\u56DE picked\u3002`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0});let S=i;if(S){if(S.value!==void 0)return g.set(y(e,r),S),{kind:"ready",value:S.value};if(S.version!==void 0&&S.version===r.localVersion)return{kind:"local"};throw new w(E.SHARE_NOT_AVAILABLE,`\u73B0\u8C61\uFF1AresolveShare \u4E3A "${o}" \u9009\u62E9\u4E86\u672A\u5C31\u7EEA\u7684 ${S.version??"\u6761\u76EE"}\u3002
|
|
19
21
|
\u539F\u56E0\uFF1A\u540C\u6B65\u6D88\u8D39\u4E0D\u80FD\u7B49\u5F85\u52A0\u8F7D\u3002
|
|
20
|
-
\u4FEE\u6CD5\uFF1A\u5148\u52A8\u6001 loadShare \u518D\u5BFC\u5165\u6D88\u8D39\u8005\uFF0C\u6216\u9009\u62E9\u5DF2\u5C31\u7EEA\u5B9E\u4F8B/\u672C\u5730\u7248\u672C ${r.localVersion??"\u672A\u58F0\u660E"}\u3002`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0})}}let t=
|
|
22
|
+
\u4FEE\u6CD5\uFF1A\u5148\u52A8\u6001 loadShare \u518D\u5BFC\u5165\u6D88\u8D39\u8005\uFF0C\u6216\u9009\u62E9\u5DF2\u5C31\u7EEA\u5B9E\u4F8B/\u672C\u5730\u7248\u672C ${r.localVersion??"\u672A\u58F0\u660E"}\u3002`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0})}}let t=I(e,r);if(!t)return{kind:"local"};if(t.value!==void 0)return{kind:"ready",value:t.value};if(t.version!==void 0&&t.version===r.localVersion)return{kind:"local"};if(r.singleton||r.strictVersion&&r.requiredVersion&&(!r.localVersion||!x(r.localVersion,r.requiredVersion))){if(r.strictVersion||t.pendingGet)throw new w(E.SHARE_NOT_AVAILABLE,`\u73B0\u8C61\uFF1A\u5171\u4EAB "${o}" \u9009\u4E2D\u4E86 ${t.from} \u63D0\u4F9B\u7684 ${t.version}\uFF08\u5C1A\u672A\u52A0\u8F7D\uFF09\uFF0C\u540C\u6B65\u9759\u6001\u5BFC\u5165\u65E0\u6CD5\u7B49\u5F85\u5176\u5B9E\u4F8B\u5C31\u7EEA\u3002
|
|
21
23
|
\u539F\u56E0\uFF1A\u4E0D\u80FD\u6539\u7528\u4E0D\u517C\u5BB9\u7684\u672C\u5730\u526F\u672C\u6216\u5206\u88C2\u5355\u4F8B\u3002
|
|
22
|
-
\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`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0});let s=`${n}|${o}|${t.version}|${r.localVersion}`;return
|
|
24
|
+
\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`,{shareKey:o,requiredVersion:r.requiredVersion,syncUnsupported:!0});let s=`${n}|${o}|${t.version}|${r.localVersion}`;return c.has(s)||(c.add(s),console.warn(`[fulgurjs:MFU-010] \u5171\u4EAB\u5355\u4F8B "${o}"\uFF1A\u4F5C\u7528\u57DF\u4E2D ${t.from} \u63D0\u4F9B\u7684 ${t.version} \u5C1A\u672A\u52A0\u8F7D\uFF0C\u9996\u4E2A\u6D88\u8D39\u8005\u4EE5\u672C\u5730\u7248\u672C ${r.localVersion??""} \u63A5\u7BA1\uFF08\u540E\u7EED\u6D88\u8D39\u8005\u6309\u5DF2\u52A0\u8F7D\u4F18\u5148\u6536\u655B\u5230\u8BE5\u5B9E\u4F8B\uFF09\u3002`)),{kind:"local"}}return console.warn(`[fulgurjs] \u5171\u4EAB "${o}"\uFF1A\u975E\u5355\u4F8B\u540C\u6B65\u6D88\u8D39\u4F7F\u7528\u672C\u5730 ${r.localVersion??""}\uFF0C\u8FDC\u7A0B ${t.version} \u5C1A\u672A\u5C31\u7EEA\u3002`),{kind:"local"}}async function Se(e){if(_.resolveShare){for(let{name:r,opts:n}of e){let o=y(r,n);if(g.has(o))continue;let t=I(r,n),s=await _.resolveShare({shareKey:n.shareKey||r,shareScope:n.shareScope||"default",requiredVersion:n.requiredVersion,picked:t,available:Object.values(M(n.shareScope||"default")[n.shareKey||r]||{})})||t;s&&g.set(o,s)}for(let{name:r,opts:n}of e)await z(r,n)}}function Y(e){try{let r=new URL(e,typeof location<"u"?location.href:"http://f.invalid");return r.protocol+"//"+r.host+r.pathname}catch{return String(e).replace(/[?#].*$/,"")}}function Z(e,r,n){return new Promise((o,t)=>{let s=setTimeout(()=>t(new Error(`\u7B49\u5F85\u8D85\u8FC7 ${r} \u6BEB\u79D2\uFF1A${n}`)),r);e.then(u=>{clearTimeout(s),o(u)},u=>{clearTimeout(s),t(u)})})}let we=e=>new Promise(r=>setTimeout(r,e)),Q=new Set;function D(e,r){if(!e||typeof e.get!="function")throw new Error(`\u8FDC\u7A0B\u5E94\u7528 "${r.name}" \u7684 remoteEntry \u672A\u5BFC\u51FA\u5BB9\u5668\u63A5\u53E3\u3002\u8BF7\u786E\u8BA4\u5165\u53E3\u5BFC\u51FA\u4E86 get()\uFF0C\u5E76\u68C0\u67E5\u8BE5\u5730\u5740\u662F\u5426\u8FD4\u56DE\u6B63\u786E\u7684\u8054\u90A6\u5165\u53E3 JS\u3002`);if(e.name&&r.name&&e.name!==r.name){let n=`\u8FDC\u7A0B\u5165\u53E3\u81EA\u62A5\u540D\u79F0 "${e.name}" \u4E0E\u5BBF\u4E3B\u914D\u7F6E\u540D\u79F0 "${r.name}" \u4E0D\u4E00\u81F4\u3002\u8BF7\u7EDF\u4E00\u4E24\u4FA7 federation({ name }) \u4E0E remotes \u7684\u540D\u79F0\u3002`;if(r.promise){let o=`${r.name}\u2194${e.name}`;Q.has(o)||(Q.add(o),console.warn(`[fulgurjs] ${n} \u5F53\u524D\u662F\u52A8\u6001 Promise \u8FDC\u7A0B\uFF0C\u7EE7\u7EED\u52A0\u8F7D\u3002`))}else throw Object.assign(new Error(n),{code:E.REMOTE_NAME_MISMATCH})}}async function ee(e,r){let n=r.entryFailCounts.get(e)??0,o=n>0?`${e}${e.includes("?")?"&":"?"}fulgurjs_retry=${n}`:e,t=r.entryInflight.get(e),s=t??import(o);return t||(r.entryInflight.set(e,s),s.catch(()=>{r.entryInflight.delete(e),r.entryFailCounts.set(e,(r.entryFailCounts.get(e)??0)+1)})),Z(s,r.timeout??H,`\u52A0\u8F7D\u8FDC\u7A0B\u5165\u53E3 ${Y(e)}`)}async function re(e,r){let n=e.shareScope||"default";if(e.container){let s=N.get(e.container);if(s&&s!==n)throw new w(E.CONTAINER_REINIT_CONFLICT,`\u8FDC\u7A0B\u5BB9\u5668 "${e.name}" \u5DF2\u4F7F\u7528\u5171\u4EAB\u4F5C\u7528\u57DF "${s}" \u521D\u59CB\u5316\uFF0C\u4E0D\u80FD\u518D\u4EE5 "${n}" \u521D\u59CB\u5316\u3002\u8BF7\u7EDF\u4E00 shareScope \u914D\u7F6E\u3002`);return e.container}if(e.containerPromise)return e.containerPromise;let o=e.breakerState;if(o.openUntil>Date.now()){let s=new w(E.REMOTE_LOAD_FAILED,`\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u8FDE\u7EED\u52A0\u8F7D\u5931\u8D25\uFF0C\u7194\u65AD\u5668\u5DF2\u5F00\u542F\uFF1B\u5C06\u5728 ${new Date(o.openUntil).toISOString()} \u540E\u5141\u8BB8\u91CD\u8BD5\u3002\u8BF7\u5148\u68C0\u67E5\u8FDC\u7A0B\u5165\u53E3\u670D\u52A1\u548C\u7F51\u7EDC\u3002`,{remote:e.name});throw $({remote:e.name,error:s}),s}e.state="loading",e.debug.status="loading";let t=(async()=>{let s=[];if(e.promise)s.push(async()=>{let p=await Z(e.promise(),e.timeout??H,`\u89E3\u6790\u52A8\u6001\u8FDC\u7A0B\u5E94\u7528 "${e.name}"`),h=typeof p=="string"?await ee(p,e):p;return D(h,e),h});else for(let p of[e.entry,...e.fallback??[]])s.push(async()=>{let h=await ee(p,e);return D(h,e),h});let u,i,S=!1,m=r?.retries??e.retries??oe;for(let p of s){for(let h=0;h<=m;h++){let L=performance.now();try{u=await p(),e.lastLoadMs=Math.round(performance.now()-L),e.debug.lastLoadMs=e.lastLoadMs,S=!0;break}catch(P){if(i=P,P?.code)throw P;h<m&&await we(Math.min(Ne,200*2**h)*(1-Ue*(1-2*Math.random())))}}if(S)break}if(!S||!u){let p=Y(e.entry),h=[];throw/^https?:\/\//.test(e.entry)&&typeof location<"u"?(h.push(`1. \u5728\u6D4F\u89C8\u5668\u6253\u5F00 ${p}\uFF0C\u786E\u8BA4\u8FDC\u7A0B\u5F00\u53D1\u670D\u52A1\u5DF2\u542F\u52A8\uFF0C\u5E76\u8FD4\u56DE JS \u800C\u975E HTML\u3002`),h.push("2. \u6838\u5BF9 federation({ remotes }) \u4E2D\u7684\u5730\u5740\uFF1B\u5F00\u53D1\u548C\u751F\u4EA7\u5730\u5740\u53EF\u4EE5\u4E0D\u540C\u3002"),h.push("3. \u82E5\u8DE8\u57DF\uFF0C\u68C0\u67E5\u8FDC\u7A0B\u5F00\u53D1\u670D\u52A1\u7684 server.cors \u914D\u7F6E\u3002")):(h.push(`1. \u5728\u6D4F\u89C8\u5668\u6253\u5F00 ${p}\uFF0C\u786E\u8BA4\u8FDC\u7A0B\u5E94\u7528\u5DF2\u90E8\u7F72\uFF0C\u4E14\u5165\u53E3\u8FD4\u56DE JS\u3002`),h.push("2. \u68C0\u67E5 Nginx/CDN \u7684\u5165\u53E3\u8DEF\u5F84\u6620\u5C04\uFF1B\u8BE5\u5730\u5740\u4E0D\u80FD\u56DE\u9000\u5230 index.html\u3002")),new w(E.REMOTE_LOAD_FAILED,`\u73B0\u8C61\uFF1A\u65E0\u6CD5\u4ECE ${p} \u52A0\u8F7D\u8FDC\u7A0B\u5E94\u7528 "${e.name}"\u3002
|
|
23
25
|
\u539F\u56E0\uFF1A${String(i?.message??i)}
|
|
24
26
|
\u4FEE\u6CD5\uFF1A
|
|
25
|
-
${
|
|
26
|
-
`)}`,{remote:e.name})}D(
|
|
27
|
+
${h.join(`
|
|
28
|
+
`)}`,{remote:e.name})}D(u,e);let a=N.get(u);if(a&&a!==n)throw new w(E.CONTAINER_REINIT_CONFLICT,`\u8FDC\u7A0B\u5BB9\u5668 "${e.name}" \u5DF2\u4F7F\u7528\u5171\u4EAB\u4F5C\u7528\u57DF "${a}" \u521D\u59CB\u5316\uFF0C\u4E0D\u80FD\u518D\u4EE5 "${n}" \u521D\u59CB\u5316\u3002\u8BF7\u7EDF\u4E00 shareScope \u914D\u7F6E\u3002`);return typeof u.init=="function"&&await u.init(l),N.set(u,n),e.container=u,e.state="loaded",e.debug.status="loaded",o.fails=0,u})();e.containerPromise=t;try{return await t}catch(s){if(e.containerPromise=void 0,e.state="failed",e.debug.status="failed",e.debug.error=String(s?.message??s),o.fails+=1,o.fails>=e.breakerThreshold&&(o.openUntil=Date.now()+e.breakerResetMs,o.fails=0),s instanceof w)throw $({remote:e.name,error:s}),s;if(s?.code)throw $({remote:e.name,error:s}),s;let u=new w(E.REMOTE_LOAD_FAILED,`\u8FDC\u7A0B\u5E94\u7528 "${e.name}" \u52A0\u8F7D\u5931\u8D25\u3002\u5E95\u5C42\u539F\u56E0\uFF1A${String(s?.message??s)}\u3002\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u5165\u53E3\u3001\u7F51\u7EDC\u53CA\u5171\u4EAB\u4F9D\u8D56\u3002`,{remote:e.name});throw $({remote:e.name,error:u}),u}}function K(e){let r=e.indexOf("/");return r===-1?{remote:e,module:""}:{remote:e.slice(0,r),module:ne(e.slice(r+1))}}function ne(e){return e?e.startsWith(".")?e:`./${e}`:""}async function Ee(e,r){let{remote:n,module:o}=K(e);if(o&&V===n)throw new w(E.SETUP_RECURSION,`\u73B0\u8C61\uFF1A\u52A0\u8F7D "${e}" \u65F6\uFF0C\u8FDC\u7A0B\u5E94\u7528 "${n}" \u7684 setup/onSession \u53C8\u540C\u6B65\u52A0\u8F7D\u4E86\u81EA\u8EAB\u6A21\u5757\uFF0C\u5F62\u6210\u5FAA\u73AF\u7B49\u5F85\u3002
|
|
27
29
|
\u539F\u56E0\uFF1A\u521D\u59CB\u5316\u5C1A\u672A\u5B8C\u6210\uFF0C\u4E0D\u80FD\u7B49\u5F85\u81EA\u8EAB\u7684\u521D\u59CB\u5316\u7ED3\u679C\u3002
|
|
28
|
-
\u4FEE\u6CD5\uFF1A\u4E0D\u8981\u5728 setup/onSession \u4E2D\u52A0\u8F7D\u540C\u4E00\u8FDC\u7A0B\u7684\u6A21\u5757\uFF1B\u8BF7\u5728\u9875\u9762\u7EC4\u4EF6\u4E2D\u52A0\u8F7D\uFF0C\u6216\u901A\u8FC7 context \u89E3\u8026\u3002`,{remote:n});try{_.beforeLoadRemote?.({remote:n,module:o})}catch(
|
|
30
|
+
\u4FEE\u6CD5\uFF1A\u4E0D\u8981\u5728 setup/onSession \u4E2D\u52A0\u8F7D\u540C\u4E00\u8FDC\u7A0B\u7684\u6A21\u5757\uFF1B\u8BF7\u5728\u9875\u9762\u7EC4\u4EF6\u4E2D\u52A0\u8F7D\uFF0C\u6216\u901A\u8FC7 context \u89E3\u8026\u3002`,{remote:n});try{_.beforeLoadRemote?.({remote:n,module:o})}catch(a){console.warn("[fulgurjs] beforeLoadRemote \u89C2\u6D4B\u94A9\u5B50\u6267\u884C\u5931\u8D25\uFF1B\u6A21\u5757\u52A0\u8F7D\u5C06\u7EE7\u7EED\u3002\u8BF7\u68C0\u67E5\u8BE5\u94A9\u5B50\uFF1A",a)}let t=f.get(n);if(!t)throw new w(E.REMOTE_UNKNOWN,`\u672A\u77E5\u8FDC\u7A0B\u5E94\u7528 "${n}"\u3002\u8BF7\u5728 federation({ remotes }) \u4E2D\u914D\u7F6E\uFF0C\u6216\u5728\u52A0\u8F7D\u524D\u8C03\u7528 registerRemote()\u3002`,{remote:n});let s;try{let a=o&&t.manifestUrl?q(e):Promise.resolve();[s]=await Promise.all([re(t,{retries:r?.retries}),a])}catch(a){if(r?.fallbackModule)return console.error(`[fulgurjs] \u8FDC\u7A0B\u6A21\u5757 "${e}" \u52A0\u8F7D\u5931\u8D25\uFF0C\u6B63\u5728\u4F7F\u7528\u663E\u5F0F\u914D\u7F6E\u7684 fallbackModule\uFF1B\u539F\u59CB\u9519\u8BEF\uFF1A`,a),$({remote:n,error:a}),await r.fallbackModule();throw a}if(!o)return s;await le(t,s);let u=G(n).globalComponents,i=r?.consumerApp;if(u&&i&&typeof i.component=="function")for(let a of Object.keys(u))i.component(a,u[a]);let S=`${n}@${t.shareScope||"default"}#${o}`;b.has(S)||b.set(S,s.get(o).catch(a=>{throw b.delete(S),a instanceof w||a?.code?a:new w(E.REMOTE_LOAD_FAILED,`\u65E0\u6CD5\u4ECE\u8FDC\u7A0B\u5E94\u7528 "${n}" \u52A0\u8F7D\u6A21\u5757 "${o}"\u3002\u5E95\u5C42\u539F\u56E0\uFF1A${String(a?.message??a)}\u3002\u8BF7\u6838\u5BF9 exposes \u952E\u548C\u8FDC\u7A0B\u6784\u5EFA\u4EA7\u7269\u3002`,{remote:n,module:o})}));let m;try{m=await b.get(S)}catch(a){if(r?.fallbackModule)return console.error(`[fulgurjs] \u8FDC\u7A0B\u6A21\u5757 "${e}" \u52A0\u8F7D\u5931\u8D25\uFF0C\u6B63\u5728\u4F7F\u7528\u663E\u5F0F\u914D\u7F6E\u7684 fallbackModule\uFF1B\u539F\u59CB\u9519\u8BEF\uFF1A`,a),$({remote:n,error:a}),await r.fallbackModule();throw a}try{_.afterLoadRemote?.({remote:n,module:o,module_ns:m})}catch(a){console.warn("[fulgurjs] afterLoadRemote \u89C2\u6D4B\u94A9\u5B50\u6267\u884C\u5931\u8D25\uFF1B\u5DF2\u52A0\u8F7D\u6A21\u5757\u4ECD\u53EF\u4F7F\u7528\u3002\u8BF7\u68C0\u67E5\u8BE5\u94A9\u5B50\uFF1A",a)}if(m&&typeof m=="object"&&Object.keys(m).length===0){let a=new w(E.EMPTY_EXPORTS,`\u8FDC\u7A0B\u5E94\u7528 "${n}" \u7684\u6A21\u5757 "${o}" \u6CA1\u6709\u4EFB\u4F55\u5BFC\u51FA\u3002\u8BF7\u68C0\u67E5 exposes \u6307\u5411\u7684\u6587\u4EF6\u53CA\u5176 export \u58F0\u660E\u3002`,{remote:n,module:o});$({remote:n,error:a}),console.error(a.message)}return m}function Re(e){let r=f.get(e);if(!r)throw new w(E.REMOTE_UNKNOWN,`\u672A\u77E5\u8FDC\u7A0B\u5E94\u7528 "${e}"\u3002\u8BF7\u5148\u6CE8\u518C\u8BE5\u8FDC\u7A0B\u5E94\u7528\u3002`,{remote:e});return re(r)}async function q(e,r={}){let{remote:n,module:o}=K(e),t=f.get(n);if(!t)throw new w(E.REMOTE_UNKNOWN,`\u672A\u77E5\u8FDC\u7A0B\u5E94\u7528 "${n}"\u3002\u8BF7\u5148\u6CE8\u518C\u8BE5\u8FDC\u7A0B\u5E94\u7528\u3002`,{remote:n});let s=r.mode??"preload",u=(m,a)=>{if(m.sheet)return Promise.resolve();let p=A.get(m);if(p)return p;let h=new Promise(L=>{let P=()=>{m.removeEventListener("load",P),m.removeEventListener("error",O),L()},O=()=>{$({remote:n,error:new w(E.PRELOAD_FAILED,`\u8FDC\u7A0B\u5E94\u7528 "${n}" \u7684\u6837\u5F0F\u8D44\u6E90\u52A0\u8F7D\u5931\u8D25\uFF1A${a}\u3002\u8BF7\u68C0\u67E5\u6587\u4EF6\u662F\u5426\u5B58\u5728\u4EE5\u53CA\u8DE8\u57DF\u548C\u7F13\u5B58\u914D\u7F6E\u3002`,{remote:n})}),P()};m.addEventListener("load",P,{once:!0}),m.addEventListener("error",O,{once:!0}),m.sheet&&P()});return A.set(m,h),h},i=(m,a)=>{if(typeof document>"u")return Promise.resolve();let p=document.querySelector(`link[href="${m}"]`);if(p)return a==="style"&&s==="preload"?A.get(p)??Promise.resolve():Promise.resolve();let h=document.createElement("link");h.rel=a==="style"?"stylesheet":"modulepreload",h.href=m,s==="prefetch"&&(h.fetchPriority="low");let L=a==="style"?u(h,m):Promise.resolve();return document.head.appendChild(h),a==="style"&&s==="preload"?L:Promise.resolve()},S=m=>{let a=typeof document<"u"?document.baseURI:void 0,p=new URL(t.entry,a||"http://fulgurjs.invalid/");return!p.pathname.endsWith("/")&&!p.pathname.split("/").pop().includes(".")&&(p.pathname+="/"),new URL(m,p).href};try{if(t.manifestUrl){let m=v.get(t.manifestUrl);m||(m=fetch(t.manifestUrl,{cache:"no-cache",signal:AbortSignal.timeout(8e3)}).then(p=>p.ok?p.json():void 0),v.set(t.manifestUrl,m),m.then(p=>{p||v.delete(t.manifestUrl)},()=>v.delete(t.manifestUrl)));let a=await m;if(a){let p=a.schemaVersion;if(typeof p=="number"&&(!Number.isInteger(p)||p>1)){$({remote:n,error:new w(E.PRELOAD_FAILED,`\u8FDC\u7A0B\u5E94\u7528 "${n}" \u7684 manifest \u534F\u8BAE\u7248\u672C\u4E3A ${String(p)}\uFF0C\u5F53\u524D\u4EC5\u652F\u6301\u7248\u672C 1\u3002\u8BF7\u7EDF\u4E00\u5BBF\u4E3B\u548C\u8FDC\u7A0B\u7684\u63D2\u4EF6\u7248\u672C\u3002`,{remote:n})}),await i(t.entry,"modulepreload");return}await i(t.entry,"modulepreload");let h=a.exposes,L=Array.isArray(h)?h.filter(k=>k&&typeof k=="object").map(k=>[String(k.name??""),k]):h&&typeof h=="object"?Object.entries(h):[],P=o?L.filter(([k,j])=>ne(String(j?.name??k))===o):L,O=[];for(let[,k]of P)if(typeof k?.file=="string"&&await i(S(k.file),"modulepreload"),Array.isArray(k?.css))for(let j of k.css){if(typeof j!="string")continue;let be=i(S(j),"style");s==="preload"&&O.push(be)}await Promise.all(O);return}}await i(t.entry,"modulepreload")}catch(m){$({remote:n,error:new w(E.PRELOAD_FAILED,`\u8FDC\u7A0B\u5E94\u7528 "${n}" \u9884\u52A0\u8F7D\u5931\u8D25\u3002\u5E95\u5C42\u539F\u56E0\uFF1A${String(m?.message??m)}\u3002\u8BF7\u68C0\u67E5 manifest \u548C\u8D44\u6E90\u5730\u5740\u3002`,{remote:n})})}}return typeof window>"u"||(window.__FULGURJS_SCOPE__=l,window.__FULGURJS_INFO__={get remotes(){let e={};for(let[r,n]of f)e[r]={...n.debug,entry:n.entry};return e},errors:[]}),{shareScopeMap:l,initSharing:fe,registerShare:F,registerRemotes:X,registerRemote:me,registerPlugins:pe,loadShare:z,loadShareSync:ye,prepareShares:Se,getLoadedShare:ge,pinLoadedShare:he,loadRemote:Ee,getContainer:Re,preloadRemote:q,parseSpec:K,clearSessionState:ue}}var se=globalThis,R=se.__FULGURJS_RUNTIME__??Ve();se.__FULGURJS_RUNTIME__=R;try{Object.freeze(R)}catch{}var Je=te;function Xe(){return R}var We=R.initSharing,ze=R.registerShare,Ye=R.registerRemotes,Ze=R.registerRemote,Qe=R.registerPlugins,er=R.loadShare,rr=R.getLoadedShare,nr=R.prepareShares||(async l=>{for(let{name:f,opts:d}of l)await R.loadShare(f,d)}),tr=R.loadShareSync,or=R.pinLoadedShare,sr=R.loadRemote,ir=R.getContainer,ar=R.preloadRemote,cr=R.parseSpec,lr=R.clearSessionState,ur=R.shareScopeMap;function fr(l){if(l&&typeof l=="object"&&"default"in l){let f=l.default;return f!==void 0?f:l}return l}var dr=R;export{lr as clearSessionState,dr as default,ir as getContainer,rr as getLoadedShare,Xe as getRuntime,We as initSharing,sr as loadRemote,er as loadShare,tr as loadShareSync,cr as parseSpec,or as pinLoadedShare,ar as preloadRemote,nr as prepareShares,Qe as registerPlugins,Ze as registerRemote,Ye as registerRemotes,ze as registerShare,R as runtime,ur as shareScopeMap,fr as unwrapDefault,Je as version};
|
package/dist/vue-adapter.cjs
CHANGED
|
@@ -349,7 +349,19 @@ function createRecoverableErrorPlaceholder(loader, spec, userErrorComponent) {
|
|
|
349
349
|
}
|
|
350
350
|
function createRemoteComponent(loadRemote) {
|
|
351
351
|
return function remoteComponent(spec, opts = {}) {
|
|
352
|
-
const loader = () =>
|
|
352
|
+
const loader = () => {
|
|
353
|
+
const app = (0, import_vue.getCurrentInstance)()?.appContext.app;
|
|
354
|
+
const consumerApp = app ? {
|
|
355
|
+
component: (name, comp) => {
|
|
356
|
+
const wrapped = typeof comp === "function" && comp.length === 0 ? (0, import_vue.defineAsyncComponent)(async () => {
|
|
357
|
+
const m = await comp();
|
|
358
|
+
return m && typeof m === "object" && "default" in m ? m.default : m;
|
|
359
|
+
}) : comp;
|
|
360
|
+
return app.component(name, wrapped);
|
|
361
|
+
}
|
|
362
|
+
} : void 0;
|
|
363
|
+
return loadRemote(spec, { retries: opts.retries, consumerApp }).then((m) => m.default ?? m);
|
|
364
|
+
};
|
|
353
365
|
return (0, import_vue.defineAsyncComponent)({
|
|
354
366
|
loader,
|
|
355
367
|
loadingComponent: opts.loadingComponent,
|
package/dist/vue-adapter.d.cts
CHANGED
|
@@ -13,6 +13,7 @@ interface RemoteComponentOptions {
|
|
|
13
13
|
}
|
|
14
14
|
declare function createRemoteComponent(loadRemote: (spec: string, opts?: {
|
|
15
15
|
retries?: number;
|
|
16
|
+
consumerApp?: unknown;
|
|
16
17
|
}) => Promise<any>): (spec: string, opts?: RemoteComponentOptions) => Component;
|
|
17
18
|
interface HostPagesOptions extends HostPagesCoreOptions {
|
|
18
19
|
/** 每次页面模块实际加载前执行(同步或异步);宿主在此提供最新 context */
|
package/dist/vue-adapter.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ interface RemoteComponentOptions {
|
|
|
13
13
|
}
|
|
14
14
|
declare function createRemoteComponent(loadRemote: (spec: string, opts?: {
|
|
15
15
|
retries?: number;
|
|
16
|
+
consumerApp?: unknown;
|
|
16
17
|
}) => Promise<any>): (spec: string, opts?: RemoteComponentOptions) => Component;
|
|
17
18
|
interface HostPagesOptions extends HostPagesCoreOptions {
|
|
18
19
|
/** 每次页面模块实际加载前执行(同步或异步);宿主在此提供最新 context */
|
package/dist/vue-adapter.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import "./chunk-TSXZ7TWA.js";
|
|
9
9
|
|
|
10
10
|
// src/vue-adapter.ts
|
|
11
|
-
import { defineAsyncComponent, defineComponent, h, ref } from "vue";
|
|
11
|
+
import { defineAsyncComponent, defineComponent, getCurrentInstance, h, ref } from "vue";
|
|
12
12
|
var ERROR_STYLE = {
|
|
13
13
|
padding: "16px",
|
|
14
14
|
border: "1px solid #fde2e2",
|
|
@@ -118,7 +118,19 @@ function createRecoverableErrorPlaceholder(loader, spec, userErrorComponent) {
|
|
|
118
118
|
}
|
|
119
119
|
function createRemoteComponent(loadRemote) {
|
|
120
120
|
return function remoteComponent(spec, opts = {}) {
|
|
121
|
-
const loader = () =>
|
|
121
|
+
const loader = () => {
|
|
122
|
+
const app = getCurrentInstance()?.appContext.app;
|
|
123
|
+
const consumerApp = app ? {
|
|
124
|
+
component: (name, comp) => {
|
|
125
|
+
const wrapped = typeof comp === "function" && comp.length === 0 ? defineAsyncComponent(async () => {
|
|
126
|
+
const m = await comp();
|
|
127
|
+
return m && typeof m === "object" && "default" in m ? m.default : m;
|
|
128
|
+
}) : comp;
|
|
129
|
+
return app.component(name, wrapped);
|
|
130
|
+
}
|
|
131
|
+
} : void 0;
|
|
132
|
+
return loadRemote(spec, { retries: opts.retries, consumerApp }).then((m) => m.default ?? m);
|
|
133
|
+
};
|
|
122
134
|
return defineAsyncComponent({
|
|
123
135
|
loader,
|
|
124
136
|
loadingComponent: opts.loadingComponent,
|
package/dist/vue.d.ts
CHANGED
|
@@ -274,6 +274,13 @@ interface LoadRemoteOptions {
|
|
|
274
274
|
shareScope?: string;
|
|
275
275
|
retries?: number;
|
|
276
276
|
fallbackModule?: () => any;
|
|
277
|
+
/**
|
|
278
|
+
* 发起本次加载的消费方应用实例(框架适配器自动传入,业务代码不用手填):
|
|
279
|
+
* Vue 侧 remoteComponent/useLoadRemote 捕获当前渲染 app;远程 setup 声明的
|
|
280
|
+
* globalComponents 会在每次加载时幂等注册到它(桥接子应用每次挂载新建 app 也能拿到注册)。
|
|
281
|
+
* 运行时只在当次调用内消费该引用,不保存、不感知具体框架类型。
|
|
282
|
+
*/
|
|
283
|
+
consumerApp?: unknown;
|
|
277
284
|
}
|
|
278
285
|
interface PreloadRemoteOptions {
|
|
279
286
|
mode?: 'preload' | 'prefetch';
|
|
@@ -338,6 +345,17 @@ interface RemoteSetupContext {
|
|
|
338
345
|
interface RemoteSetupModule {
|
|
339
346
|
default: (ctx: RemoteSetupContext) => void | Promise<void>;
|
|
340
347
|
onSession?: (ctx: RemoteSetupContext) => void | Promise<void>;
|
|
348
|
+
/**
|
|
349
|
+
* 远程暴露面依赖的「宿主全局注册组件」声明(键=组件注册名,值=组件对象或零参 loader):
|
|
350
|
+
* 组件联邦(remoteComponent)把远程组件渲染进消费方 app 上下文,模板里的
|
|
351
|
+
* 字符串标签(如 <a-divider>)按消费方 app 的全局注册表解析——消费方没注册就
|
|
352
|
+
* 渲染成死元素。提供方在此声明后,运行时在每次 loadRemote 时把它们幂等注册到
|
|
353
|
+
* 当次传入的 consumerApp 上;无 consumerApp(无组件上下文的手动加载)时静默跳过。
|
|
354
|
+
* 值推荐「零参 loader(() => import('./X.vue'))」:setup 模块保持零重依赖,
|
|
355
|
+
* 组件只在本框架消费方真实渲染时才加载——Vue 适配器注册时自动包 defineAsyncComponent;
|
|
356
|
+
* 静态组件值仍支持(同框架消费场景一步到位)。运行时对值原样透传,不做形状校验。
|
|
357
|
+
*/
|
|
358
|
+
globalComponents?: Record<string, unknown>;
|
|
341
359
|
}
|
|
342
360
|
declare function createRuntime(): {
|
|
343
361
|
shareScopeMap: ShareScopeMap;
|
package/docs/en/reference/api.md
CHANGED
|
@@ -54,6 +54,8 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
54
54
|
})
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
The `consumerApp` option is passed automatically by framework adapters (Vue `remoteComponent` captures the currently rendering app); business code never sets it by hand: a remote's declared setup `globalComponents` are registered idempotently onto it on every load. A manual `loadRemote` (no component context) omits the option and skips registration.
|
|
58
|
+
|
|
57
59
|
Call timing and lifecycle: `spec` fully resolved → container load (timeout/retries/breaker) → `init(shareScope)` (shared scope adoption) → setup → onSession → business module returned. The setup module's own imports complete their shared negotiation at that stage.
|
|
58
60
|
|
|
59
61
|
### Other exported general-purpose functions
|
|
@@ -244,6 +246,7 @@ const FederatedForm = remoteComponent('remote-a/Form', {
|
|
|
244
246
|
Semantics and boundaries:
|
|
245
247
|
|
|
246
248
|
- Internally = `defineAsyncComponent({ loader: () => loadRemote(spec, opts).then(m => m.default ?? m) })`, returning a standard Vue async component; `props` pass straight through at the usage site;
|
|
249
|
+
- **Global-component auto-install (6.1.0)**: a remote component renders inside the **consumer app** context, and string tags in its templates (e.g. `<a-divider>`) resolve against the consumer's global registry — the provider app's `app.use(X)` registrations do not travel with the component. When the remote declares `globalComponents` in its setup module, this factory captures the currently rendering app on load and registers them idempotently (including consumption inside bridge child apps); see Section 6 `federation({ setup })` for the globalComponents contract;
|
|
247
250
|
- **No fallback/degradation whatsoever** (zero silent fallback): a load failure explicitly enters the error state; without an `errorComponent`, the built-in placeholder renders (error code + root cause + fix + **Retry load / Refresh page**), and the `fulgurjs:error` event is emitted as usual by the runtime layer;
|
|
248
251
|
- Module dedup reuses `loadRemote`'s internal Promise cache — multiple component instances with the same spec load the container module only once;
|
|
249
252
|
- Call timing = zero side effects at factory declaration; loading happens at render time;
|
|
@@ -312,6 +315,23 @@ export async function onSession(context: RemoteSetupContext) {
|
|
|
312
315
|
if (context.signal.aborted) return // ← must be checked after awaits and before writing state: the account may have switched/logged out meanwhile
|
|
313
316
|
writeToStores(data)
|
|
314
317
|
}
|
|
318
|
+
|
|
319
|
+
// 6.1.0 optional named export: the "consumer-side globally registered components" the exposed
|
|
320
|
+
// surface depends on (key = registered name, value = a component object or a zero-arg loader).
|
|
321
|
+
// For component federation (remoteComponent): the remote component renders inside the CONSUMER
|
|
322
|
+
// app, and string tags in its templates (e.g. <a-divider>) resolve against the consumer's
|
|
323
|
+
// global registry — without registration they render as unstyled literal custom elements.
|
|
324
|
+
// The runtime registers these idempotently onto the current consumer app on every loadRemote;
|
|
325
|
+
// omit for zero behavior.
|
|
326
|
+
export const globalComponents: RemoteSetupModule['globalComponents'] = {
|
|
327
|
+
// Recommended zero-arg loader form: the setup module itself stays free of component imports,
|
|
328
|
+
// so components load only when actually rendered by a same-framework consumer (the Vue
|
|
329
|
+
// adapter wraps loaders with defineAsyncComponent at registration). Cross-framework
|
|
330
|
+
// consumers loading pure-TS modules never pull the framework graph.
|
|
331
|
+
ADivider: () => import('ant-design-vue').then((m) => m.Divider),
|
|
332
|
+
// Static component values also work (one step for same-framework consumers):
|
|
333
|
+
// AButton: Button,
|
|
334
|
+
}
|
|
315
335
|
```
|
|
316
336
|
|
|
317
337
|
`RemoteSetupContext`: `{ appContext: Readonly<AppContext>, sessionKey?: string, signal: AbortSignal }`. `appContext` is the snapshot taken from the page-level AppContext **at call time** (never a saved stale reference); `signal` is invalidated when the login generation changes or on logout cleanup.
|
|
@@ -321,11 +341,12 @@ Fixed contract:
|
|
|
321
341
|
| Dimension | Semantics |
|
|
322
342
|
|---|---|
|
|
323
343
|
| Trigger entry | `loadRemote('remote/module')` is the **unified entry** (`remoteComponent` and the host page adapters share the same source). `loadRemote('remote')`, `getContainer()`, `preloadRemote()`, and calling `container.get()` directly all **do not run** initialization |
|
|
324
|
-
| Timing | Container acquired → `init(shareScope)` (shared scope adoption) → **setup** → **onSession** → business module returned. The setup module's own imports complete their shared negotiation at that stage |
|
|
344
|
+
| Timing | Container acquired → `init(shareScope)` (shared scope adoption) → **setup** → **onSession** → **globalComponents install** → business module returned. The setup module's own imports complete their shared negotiation at that stage |
|
|
325
345
|
| Execution count (setup) | Once per container; concurrent calls share one Promise; never repeated after success. `preloadRemote` only prefetches resources and never executes |
|
|
346
|
+
| Execution count (globalComponents) | Declaration is extracted once with setup; **installation runs on every `loadRemote`** (idempotent — `app.component` same-name overwrite) so bridge child apps that create a fresh app instance per mount also receive the registration. A manual `loadRemote` (no `consumerApp`) skips installation without error |
|
|
326
347
|
| Execution count (onSession) | Deduplicated by the non-sensitive `sessionKey`: once per login generation; a new generation first invalidates the old `signal`, then chains the old call and the new call **serially** per remote (preventing two accounts' async writes from interleaving); `clearAppContext()` invalidates the dedup state, forcing a rerun on the next login. App-level setup does not re-run on logout/generation switch |
|
|
327
348
|
| sessionKey | The host login flow generates a new generation on every successful login/re-login (non-sensitive ID, never a token); kept when a token refreshes but the session does not. **onSession present but sessionKey missing → MFU-013**; identity is never guessed from a user object reference; remotes without onSession need no sessionKey |
|
|
328
|
-
| Export validation | Must default-export a function; the named `onSession` is optional and must be a function;
|
|
349
|
+
| Export validation | Must default-export a function; the named `onSession` is optional and must be a function; `globalComponents` is optional and must be an object (key = registered name, value = component). Violations → MFU-011 (reports actual type / expected signature / fix) |
|
|
329
350
|
| Failure and retry | setup/onSession throwing → that `loadRemote` rejects (MFU-012); **only the failed stage's cache is cleared** (after a setup failure the retry starts at setup; an onSession failure only reruns the session segment); already-successful stages are not repeated. `fallbackModule` never masks an initialization failure |
|
|
330
351
|
| Self-recursion | `loadRemote(same remote/…)` inside setup/onSession's synchronous segment → MFU-014 (the call waits on itself, deadlocking). Same-remote recursion inside the async segment cannot be attributed precisely and shows up as a hang — never load same-remote modules inside initialization |
|
|
331
352
|
| dev/prod parity | The dev container (middleware-served) and the prod container (build artifact) carry the same setup metadata (the container's `__fulgurjsSetup` field + the manifest's `setup` field); the internal expose key `./__fulgurjs_setup__` never appears in dts types or public exposes lists |
|
|
@@ -411,7 +432,7 @@ The bridge defaults to memory routing; URL sync makes the **host URL express the
|
|
|
411
432
|
| `createVueBridgeNavigation` | `(router: VueRouterLike) => BridgeHostNavigation` | Vue host navigation port. Vue Router fullPath is already the logical path; no deployment base needed. Vue Router 4, history or hash mode |
|
|
412
433
|
| `createReactBridgeNavigation` | `(navigate, { basename?, canNavigate? }) => BridgeHostNavigation` | React host navigation port. **Data router only** (`createBrowserRouter`/`createHashRouter` + `RouterProvider`); declarative mode (BrowserRouter) has no cancellation semantics and is not supported. React Router ≥ 6.11. `canNavigate` is optional and only an early rejection; the port observes the real blocker state — wait for `reset()` to resolve as cancelled and for the actual location to commit after `proceed()`; success is never judged solely by the settle of navigate's Promise |
|
|
413
434
|
| `connectVueBridgeRouter` | `(routing: BridgeChildRouting, router: Router, { signal? }) => { ready: Promise, dispose(): void }` | Vue child app wiring for the controlled memory router; `await …ready` settles before `app.use(router)` (order must not be reversed) |
|
|
414
|
-
| `createReactBridgeRouter` | `(routing, routes, { signal? }) => { element }` | React child app: returns a `RouterProvider` element used directly as the contract product |
|
|
435
|
+
| `createReactBridgeRouter` | `(routing, routes, { signal? }) => { element, dispose(), routerReady }` | React child app: returns a `RouterProvider` element used directly as the contract product. `routerReady: Promise<Router>` is the wired memory-router readiness contract (since 6.0.0): the fast path (module-level warmup already settled, the common case) returns an **already-resolved** Promise whose value equals `element.props.router`; the slow path (rare warmup race) resolves when the lazy host finishes wiring on first render; a missing react-router-dom rejects with a clear error. Introspect via `await routerReady` instead of assuming `element.props.router` exists synchronously. `dispose()` tears down the wiring idempotently (auto-invoked by the signal); late tasks after dispose never write state |
|
|
415
436
|
|
|
416
437
|
The channel parameter the host passes to the bridge component: `routing: BridgeHostRouting = { basePath: '/approval', navigation }`; after the child app contract's second parameter declares `{ routing: true }`, it receives the channel from `ctx.routing`. The wiring's third argument on both ends, `{ signal?: AbortSignal }`, defaults to empty; passing `ctx.signal` is recommended for automatic dispose — without it, the child app explicitly calls `dispose()`. A custom `BridgeHostNavigation.navigate(target, action, { signal })` should re-check the optional signal before an async commit and forbid late writes once aborted.
|
|
417
438
|
|
package/docs/zh/reference/api.md
CHANGED
|
@@ -54,6 +54,8 @@ const Panel = await loadRemote('shop/Panel', {
|
|
|
54
54
|
})
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
`consumerApp` 选项由框架适配器自动传入(Vue `remoteComponent` 捕获当前渲染 app),业务代码不用手填:远程 setup 声明的 `globalComponents` 会在每次加载时幂等注册到它。手动 `loadRemote`(无组件上下文)不传该选项,跳过注册。
|
|
58
|
+
|
|
57
59
|
调用时机与生命周期:`spec` 完整解析 → 容器加载(超时/重试/熔断)→ `init(shareScope)`(共享作用域收养)→ setup → onSession → 返回业务模块。setup 模块自身的导入在该阶段完成共享协商。
|
|
58
60
|
|
|
59
61
|
### 其他已导出的通用函数
|
|
@@ -243,6 +245,7 @@ const FederatedForm = remoteComponent('remote-a/Form', {
|
|
|
243
245
|
语义与边界:
|
|
244
246
|
|
|
245
247
|
- 内部 = `defineAsyncComponent({ loader: () => loadRemote(spec, opts).then(m => m.default ?? m) })`,返回标准 Vue 异步组件,`props` 在使用处直接透传;
|
|
248
|
+
- **全局注册组件自动安装(6.1.0)**:远程组件渲染在**消费方 app** 上下文里,其模板字符串标签(如 `<a-divider>`)按消费方全局注册表解析——提供方 app 的 `app.use(X)` 全局注册不随组件走。远程在 setup 模块声明 `globalComponents` 后,本工厂加载时自动捕获当前渲染 app 并完成幂等注册(含桥接子应用内消费的场景);详见第 6 节 `federation({ setup })` 的 globalComponents 契约;
|
|
246
249
|
- **无任何兜底/降级**(零兜底):加载失败显式进错误态;不传 `errorComponent` 时渲染内置占位(错误码 + 根因 + 修法 + **重试加载 / 刷新页面重试**),`fulgurjs:error` 事件由 runtime 层照常发出;
|
|
247
250
|
- 模块去重沿用 `loadRemote` 内部 Promise 缓存——同 spec 多组件实例只加载一次容器模块;
|
|
248
251
|
- 调用时机 = 组件工厂声明时零副作用,渲染时才加载;
|
|
@@ -311,6 +314,20 @@ export async function onSession(context: RemoteSetupContext) {
|
|
|
311
314
|
if (context.signal.aborted) return // ← await 之后写状态前必须检查:期间可能已换账号/退出
|
|
312
315
|
writeToStores(data)
|
|
313
316
|
}
|
|
317
|
+
|
|
318
|
+
// 6.1.0 可选具名导出:暴露面依赖的「消费方全局注册组件」声明
|
|
319
|
+
// (键=注册名,值=组件对象或零参 loader)。
|
|
320
|
+
// 适用场景:组件联邦(remoteComponent)把远程组件渲染进消费方 app,其模板里的字符串标签
|
|
321
|
+
// (如 <a-divider>)按消费方全局注册表解析——消费方没注册就渲染成无样式死元素。
|
|
322
|
+
// 运行时在每次 loadRemote 时把它们幂等注册到当次消费方 app;不声明则零行为。
|
|
323
|
+
export const globalComponents: RemoteSetupModule['globalComponents'] = {
|
|
324
|
+
// 推荐零参 loader 形态:setup 模块自身零组件依赖,组件只在本框架消费方真实渲染时
|
|
325
|
+
// 才加载(Vue 适配器注册时自动包 defineAsyncComponent)——跨框架消费方加载本远程
|
|
326
|
+
// 纯 TS 模块时不拖入框架依赖图。
|
|
327
|
+
ADivider: () => import('ant-design-vue').then((m) => m.Divider),
|
|
328
|
+
// 静态组件值同样支持(同框架消费一步到位):
|
|
329
|
+
// AButton: Button,
|
|
330
|
+
}
|
|
314
331
|
```
|
|
315
332
|
|
|
316
333
|
`RemoteSetupContext`:`{ appContext: Readonly<AppContext>, sessionKey?: string, signal: AbortSignal }`。`appContext` 是**调用时**从页面级 AppContext 取得的快照(不保存永不更新的旧引用);`signal` 在登录代次变化或退出清理时失效。
|
|
@@ -320,11 +337,12 @@ export async function onSession(context: RemoteSetupContext) {
|
|
|
320
337
|
| 维度 | 语义 |
|
|
321
338
|
|---|---|
|
|
322
339
|
| 触发入口 | `loadRemote('remote/模块')` 是**统一入口**(`remoteComponent` 与宿主页面适配器同源)。`loadRemote('remote')`、`getContainer()`、`preloadRemote()`、直调 `container.get()` 都**不执行**初始化 |
|
|
323
|
-
| 时序 | 取得容器 → `init(shareScope)`(共享作用域收养)→ **setup** → **onSession** → 返回业务模块。setup 模块自身的导入在该阶段完成共享协商 |
|
|
340
|
+
| 时序 | 取得容器 → `init(shareScope)`(共享作用域收养)→ **setup** → **onSession** → **globalComponents 安装** → 返回业务模块。setup 模块自身的导入在该阶段完成共享协商 |
|
|
324
341
|
| 执行次数(setup) | 每容器一次;并发调用共享同一 Promise;成功后不重复。`preloadRemote` 只预取资源不执行 |
|
|
342
|
+
| 执行次数(globalComponents) | 声明提取随 setup 一次;**安装随每次 `loadRemote` 执行**(幂等,`app.component` 同名覆盖)——桥接子应用每次挂载新建 app 实例也能拿到注册。手动 `loadRemote`(无 `consumerApp`)跳过安装,不报错 |
|
|
325
343
|
| 执行次数(onSession) | 按非敏感 `sessionKey` 去重:同一登录代次一次;新代次先作废旧 `signal`,再按远程**串行**衔接旧调用与新调用(防两账号异步写入交错);`clearAppContext()` 失效去重状态,下次登录必须重跑。应用级 setup 不因退出/换代重复执行 |
|
|
326
344
|
| sessionKey | 宿主登录流程每次成功登录/重登生成新代次(非敏感 ID,禁止用 token);token 刷新但会话未变时沿用。**有 onSession 却缺 sessionKey → MFU-013**,不凭用户对象引用猜测身份;无 onSession 的远程无需 sessionKey |
|
|
327
|
-
| 导出校验 | 必须默认导出函数;具名 `onSession`
|
|
345
|
+
| 导出校验 | 必须默认导出函数;具名 `onSession` 可选且必须是函数;`globalComponents` 可选且必须是对象(键=注册名,值=组件)。违反 → MFU-011(报实际类型/预期签名/修法) |
|
|
328
346
|
| 失败与重试 | setup/onSession 抛错 → 该次 `loadRemote` 拒绝(MFU-012);**只清失败阶段的缓存**(setup 失败重试从 setup 开始;onSession 失败只重跑会话段),已成功的阶段不重复。`fallbackModule` 不掩盖初始化失败 |
|
|
329
347
|
| 自递归 | setup/onSession 同步段内 `loadRemote(同 remote/…)` → MFU-014(该调用会等待自身形成死锁)。异步段内的同远程递归无法精确归因,表现为挂起——不要在初始化内加载同远程模块 |
|
|
330
348
|
| dev/prod 一致 | dev 容器(中间件直出)与 prod 容器(构建产物)携带同一 setup 元数据(容器上的 `__fulgurjsSetup` 字段 + manifest 的 `setup` 字段);内部 expose 键 `./__fulgurjs_setup__` 不出现在 dts 类型与公开文档 exposes 清单中 |
|
|
@@ -410,7 +428,7 @@ const RemoteVueApp = createReactBridgeApp<P>('vue-remote/bridge', {
|
|
|
410
428
|
| `createVueBridgeNavigation` | `(router: VueRouterLike) => BridgeHostNavigation` | Vue 宿主导航端口。Vue Router fullPath 已是逻辑路径,无需传部署 base。Vue Router 4,history/hash 模式皆可 |
|
|
411
429
|
| `createReactBridgeNavigation` | `(navigate, { basename?, canNavigate? }) => BridgeHostNavigation` | React 宿主导航端口。**仅支持 data router**(`createBrowserRouter`/`createHashRouter` + `RouterProvider`);declarative 模式(BrowserRouter)无取消语义,不支持。React Router ≥ 6.11。`canNavigate` 可选仅作提前拒绝;端口观察真实 blocker 状态,等待 `reset()` 返回 cancelled、`proceed()` 后实际位置提交返回 committed,不能只凭 navigate 的 Promise 落定判成功 |
|
|
412
430
|
| `connectVueBridgeRouter` | `(routing: BridgeChildRouting, router: Router, { signal? }) => { ready: Promise, dispose(): void }` | Vue 子应用接线受控 memory 路由;`await …ready` 落定后再 `app.use(router)`(顺序不能反) |
|
|
413
|
-
| `createReactBridgeRouter` | `(routing, routes, { signal? }) => { element }` | React 子应用:返回 `RouterProvider`
|
|
431
|
+
| `createReactBridgeRouter` | `(routing, routes, { signal? }) => { element, dispose(), routerReady }` | React 子应用:返回 `RouterProvider` 元素直接作契约产物。`routerReady: Promise<Router>` 是已接线 memory router 的就绪合同(6.0.0 起):fast 路径(模块级预热已就绪,常见)返回**同步已 resolve** 的 Promise,resolve 值与 `element.props.router` 等价;slow 路径(预热未落定的罕见竞态)在惰性宿主接线完成时 resolve,缺 react-router-dependency 时 reject 清晰错误。宿主内省/断言请优先 `await routerReady`,不要假设 `element.props.router` 同步存在。`dispose()` 幂等销毁接线(signal 触发时自动调用);已 dispose 后迟到任务不写状态 |
|
|
414
432
|
|
|
415
433
|
宿主传给桥接组件的通道参数:`routing: BridgeHostRouting = { basePath: '/approval', navigation }`;子应用契约第二参数声明 `{ routing: true }` 后从 `ctx.routing` 接收通道。两端接线第三参数 `{ signal?: AbortSignal }` 默认为空;推荐传 `ctx.signal` 自动 dispose,未传时由子应用显式调用 `dispose()`。自定义 `BridgeHostNavigation.navigate(target, action, { signal })` 应在异步提交前复核可选 signal,已 aborted 时禁止迟到写入。
|
|
416
434
|
|
|
@@ -11,8 +11,8 @@ importers:
|
|
|
11
11
|
react-host:
|
|
12
12
|
dependencies:
|
|
13
13
|
'@fulgurjs/federation':
|
|
14
|
-
specifier:
|
|
15
|
-
version:
|
|
14
|
+
specifier: 6.0.0
|
|
15
|
+
version: 6.0.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(vite@6.4.3)(vue-router@4.6.4(vue@3.5.43(typescript@5.9.3)))(vue@3.5.43(typescript@5.9.3))
|
|
16
16
|
react:
|
|
17
17
|
specifier: ^19.1.0
|
|
18
18
|
version: 19.3.0
|
|
@@ -42,8 +42,8 @@ importers:
|
|
|
42
42
|
vue-remote:
|
|
43
43
|
dependencies:
|
|
44
44
|
'@fulgurjs/federation':
|
|
45
|
-
specifier:
|
|
46
|
-
version:
|
|
45
|
+
specifier: 6.0.0
|
|
46
|
+
version: 6.0.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(vite@6.4.3)(vue-router@4.6.4(vue@3.5.43(typescript@5.9.3)))(vue@3.5.43(typescript@5.9.3))
|
|
47
47
|
vue:
|
|
48
48
|
specifier: ^3.5.13
|
|
49
49
|
version: 3.5.43(typescript@5.9.3)
|
|
@@ -458,8 +458,8 @@ packages:
|
|
|
458
458
|
cpu: [x64]
|
|
459
459
|
os: [win32]
|
|
460
460
|
|
|
461
|
-
'@fulgurjs/federation@
|
|
462
|
-
resolution: {integrity: sha512-
|
|
461
|
+
'@fulgurjs/federation@6.0.0':
|
|
462
|
+
resolution: {integrity: sha512-h3/ZvxdJZVtbvQcQ/OycsTQq7J9LYTfDjpjtoLli0eMk1gOjr2xdvtYaKw57Rt+ccGyfJgYPCsF2U48vVkRFpg==}
|
|
463
463
|
engines: {node: '>=18'}
|
|
464
464
|
hasBin: true
|
|
465
465
|
peerDependencies:
|
|
@@ -1196,7 +1196,7 @@ snapshots:
|
|
|
1196
1196
|
'@esbuild/win32-x64@0.27.7':
|
|
1197
1197
|
optional: true
|
|
1198
1198
|
|
|
1199
|
-
'@fulgurjs/federation@
|
|
1199
|
+
'@fulgurjs/federation@6.0.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0)(vite@6.4.3)(vue-router@4.6.4(vue@3.5.43(typescript@5.9.3)))(vue@3.5.43(typescript@5.9.3))':
|
|
1200
1200
|
dependencies:
|
|
1201
1201
|
es-module-lexer: 1.7.0
|
|
1202
1202
|
esbuild: 0.27.7
|
|
@@ -11,8 +11,8 @@ importers:
|
|
|
11
11
|
host:
|
|
12
12
|
dependencies:
|
|
13
13
|
'@fulgurjs/federation':
|
|
14
|
-
specifier:
|
|
15
|
-
version:
|
|
14
|
+
specifier: 6.0.0
|
|
15
|
+
version: 6.0.0(react-dom@19.3.0(react@19.3.0))(react-router-dom@7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react@19.3.0)(vite@6.4.3)
|
|
16
16
|
react:
|
|
17
17
|
specifier: ^19.1.0
|
|
18
18
|
version: 19.3.0
|
|
@@ -42,8 +42,8 @@ importers:
|
|
|
42
42
|
remote:
|
|
43
43
|
dependencies:
|
|
44
44
|
'@fulgurjs/federation':
|
|
45
|
-
specifier:
|
|
46
|
-
version:
|
|
45
|
+
specifier: 6.0.0
|
|
46
|
+
version: 6.0.0(react-dom@19.3.0(react@19.3.0))(react-router-dom@7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react@19.3.0)(vite@6.4.3)
|
|
47
47
|
react:
|
|
48
48
|
specifier: ^19.1.0
|
|
49
49
|
version: 19.3.0
|
|
@@ -464,8 +464,8 @@ packages:
|
|
|
464
464
|
cpu: [x64]
|
|
465
465
|
os: [win32]
|
|
466
466
|
|
|
467
|
-
'@fulgurjs/federation@
|
|
468
|
-
resolution: {integrity: sha512-
|
|
467
|
+
'@fulgurjs/federation@6.0.0':
|
|
468
|
+
resolution: {integrity: sha512-h3/ZvxdJZVtbvQcQ/OycsTQq7J9LYTfDjpjtoLli0eMk1gOjr2xdvtYaKw57Rt+ccGyfJgYPCsF2U48vVkRFpg==}
|
|
469
469
|
engines: {node: '>=18'}
|
|
470
470
|
hasBin: true
|
|
471
471
|
peerDependencies:
|
|
@@ -1169,7 +1169,7 @@ snapshots:
|
|
|
1169
1169
|
'@esbuild/win32-x64@0.27.7':
|
|
1170
1170
|
optional: true
|
|
1171
1171
|
|
|
1172
|
-
'@fulgurjs/federation@
|
|
1172
|
+
'@fulgurjs/federation@6.0.0(react-dom@19.3.0(react@19.3.0))(react-router-dom@7.18.4(react-dom@19.3.0(react@19.3.0))(react@19.3.0))(react@19.3.0)(vite@6.4.3)':
|
|
1173
1173
|
dependencies:
|
|
1174
1174
|
es-module-lexer: 1.7.0
|
|
1175
1175
|
esbuild: 0.27.7
|