mfe-runtime-z 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +119 -38
- package/build/index.esm.js +1 -340
- package/build/index.js +1 -355
- package/build/index.min.js +1 -1
- package/build/micro-fe/host/MFEHost.d.ts +11 -0
- package/build/micro-fe/router/createSharedRouter.d.ts +6 -2
- package/build/micro-fe/router/events.d.ts +1 -0
- package/package.json +50 -4
package/README.md
CHANGED
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
[](https://www.npmjs.com/package/mfe-runtime-z)
|
|
11
10
|
[](https://standardjs.com)
|
|
12
11
|

|
|
@@ -38,6 +37,7 @@ This library focuses on **application-level integration**, not component sharing
|
|
|
38
37
|
npm install mfe-runtime-z
|
|
39
38
|
# or
|
|
40
39
|
yarn add mfe-runtime-z
|
|
40
|
+
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
---
|
|
@@ -71,7 +71,7 @@ window.myRemoteApp = { mount(el, ctx), unmount(el) }
|
|
|
71
71
|
import { MFEHost, createSharedStore } from "mfe-runtime-z"
|
|
72
72
|
|
|
73
73
|
// shared store example
|
|
74
|
-
const authStore = createSharedStore({ user:
|
|
74
|
+
const authStore = createSharedStore({ user: { name: 'name' } })
|
|
75
75
|
|
|
76
76
|
// create host with isolate: true for Shadow DOM + error isolation
|
|
77
77
|
const host = new MFEHost({
|
|
@@ -81,19 +81,22 @@ const host = new MFEHost({
|
|
|
81
81
|
onRemoteError: (err) => console.error("Remote error:", err)
|
|
82
82
|
})
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const
|
|
84
|
+
async function init() {
|
|
85
|
+
// load remote apps
|
|
86
|
+
const productRemote = await host.load("http://localhost:3001/remote.js", "productApp")
|
|
87
|
+
const cartRemote = await host.load("http://localhost:3002/remote.js", "cartApp")
|
|
87
88
|
|
|
88
|
-
// mount remotes into host container divs
|
|
89
|
-
host.mount(productRemote, document.getElementById("product-root")!, "productApp", { isolate:
|
|
90
|
-
host.mount(cartRemote, document.getElementById("cart-root")!, "cartApp")
|
|
89
|
+
// mount remotes into host container divs
|
|
90
|
+
host.mount(productRemote, document.getElementById("product-root")!, "productApp", { isolate: false }) // shadow
|
|
91
|
+
host.mount(cartRemote, document.getElementById("cart-root")!, "cartApp")
|
|
91
92
|
|
|
92
|
-
// // Unmount Shadow DOM remote
|
|
93
|
-
// host.unmount(productRemote, document.getElementById("product-root")!, "productApp")
|
|
94
|
-
// // Unmount normal remote
|
|
95
|
-
// host.unmount(cartRemote, document.getElementById("cart-root")!, "cartApp")
|
|
93
|
+
// // Unmount Shadow DOM remote
|
|
94
|
+
// host.unmount(productRemote, document.getElementById("product-root")!, "productApp")
|
|
95
|
+
// // Unmount normal remote
|
|
96
|
+
// host.unmount(cartRemote, document.getElementById("cart-root")!, "cartApp")
|
|
97
|
+
}
|
|
96
98
|
|
|
99
|
+
init()
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
##### Remote application (framework-agnostic)
|
|
@@ -119,45 +122,65 @@ export function unmount(el: ShadowRoot) {
|
|
|
119
122
|
;(window as any).cartApp = { mount, unmount }
|
|
120
123
|
```
|
|
121
124
|
|
|
122
|
-
##### Remote
|
|
125
|
+
##### Remote application (framework-react-library)
|
|
123
126
|
|
|
124
127
|
```ts
|
|
125
128
|
import React from "react"
|
|
126
129
|
import ReactDOM from "react-dom/client"
|
|
130
|
+
import { createSharedStore } from "mfe-runtime-z"
|
|
127
131
|
|
|
128
|
-
|
|
129
|
-
user:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
132
|
+
export const authStore = createSharedStore<{ user: { id: string; name: string } | null }>({
|
|
133
|
+
user: null,
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
export default function App() {
|
|
137
|
+
const [user, setUser] = React.useState(authStore.getState().user)
|
|
133
138
|
|
|
134
|
-
function App({ store }: { store: AuthStore }) {
|
|
135
|
-
const [user, setUser] = React.useState(store.user)
|
|
136
139
|
React.useEffect(() => {
|
|
137
|
-
const
|
|
138
|
-
return () =>
|
|
139
|
-
}, [
|
|
140
|
+
const unsubscribe = authStore.subscribe((state) => setUser(state.user))
|
|
141
|
+
return () => unsubscribe()
|
|
142
|
+
}, [])
|
|
143
|
+
|
|
144
|
+
const handleLogin = () => {
|
|
145
|
+
authStore.setState({ user: { id: "1", name: "Alice" } })
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const handleLogout = () => {
|
|
149
|
+
authStore.setState({ user: null })
|
|
150
|
+
}
|
|
151
|
+
|
|
140
152
|
return (
|
|
141
153
|
<div>
|
|
142
|
-
{user ?
|
|
154
|
+
{user ? (
|
|
155
|
+
<>
|
|
156
|
+
<span>Hello {user.name}</span>
|
|
157
|
+
<button onClick={handleLogout}>Logout</button>
|
|
158
|
+
</>
|
|
159
|
+
) : (
|
|
160
|
+
<button onClick={handleLogin}>Login</button>
|
|
161
|
+
)}
|
|
143
162
|
</div>
|
|
144
163
|
)
|
|
145
164
|
}
|
|
146
165
|
|
|
147
|
-
// mount
|
|
148
|
-
export function mount(el: HTMLElement
|
|
149
|
-
const root = ReactDOM.createRoot(el
|
|
166
|
+
// mount function
|
|
167
|
+
export function mount(el: HTMLElement, ctx: any) {
|
|
168
|
+
const root = ReactDOM.createRoot(el)
|
|
150
169
|
;(el as any)._reactRoot = root
|
|
151
|
-
|
|
170
|
+
// @ts-ignore
|
|
171
|
+
root.render(<App />) // <- ctx.stores.auth
|
|
152
172
|
}
|
|
153
173
|
|
|
154
|
-
|
|
174
|
+
// unmount function
|
|
175
|
+
export function unmount(el: HTMLElement) {
|
|
155
176
|
const root = (el as any)._reactRoot
|
|
156
|
-
|
|
177
|
+
root?.unmount()
|
|
157
178
|
el.innerHTML = ""
|
|
158
179
|
}
|
|
159
180
|
|
|
181
|
+
// expose to window
|
|
160
182
|
;(window as any).productApp = { mount, unmount }
|
|
183
|
+
|
|
161
184
|
```
|
|
162
185
|
|
|
163
186
|
---
|
|
@@ -165,9 +188,17 @@ export function unmount(el: HTMLElement | ShadowRoot) {
|
|
|
165
188
|
### Shared State
|
|
166
189
|
|
|
167
190
|
```ts
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
store
|
|
191
|
+
import { createSharedStore } from "mfe-runtime-z"
|
|
192
|
+
|
|
193
|
+
export const store = createSharedStore({
|
|
194
|
+
auth: { user: null }
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
// Subscribe
|
|
198
|
+
store.subscribe((state) => console.log("New state:", state))
|
|
199
|
+
|
|
200
|
+
// Update
|
|
201
|
+
store.setState({ auth: { user: { id: 1, name: "Alice" } } })
|
|
171
202
|
```
|
|
172
203
|
|
|
173
204
|
- Push-based, no Redux, no shared framework state
|
|
@@ -179,10 +210,20 @@ store.setState({ count: 1 })
|
|
|
179
210
|
```ts
|
|
180
211
|
import { createSharedRouter } from "mfe-runtime-z"
|
|
181
212
|
|
|
182
|
-
|
|
213
|
+
// Remote app context
|
|
214
|
+
const router = createSharedRouter({ eventBus, name: "productApp" })
|
|
215
|
+
|
|
183
216
|
router.go("/cart")
|
|
184
217
|
router.onChange((path) => console.log("navigated to", path))
|
|
185
218
|
|
|
219
|
+
// Listen route changes from host or other remotes
|
|
220
|
+
router.onRouteChange((path) => {
|
|
221
|
+
console.log("Remote route changed:", path)
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
// Notify other remotes of route change
|
|
225
|
+
router.emitRouteChange("/checkout")
|
|
226
|
+
|
|
186
227
|
```
|
|
187
228
|
|
|
188
229
|
- Intent-based navigation
|
|
@@ -252,6 +293,7 @@ if (process.env.NODE_ENV === "development") {
|
|
|
252
293
|
```
|
|
253
294
|
|
|
254
295
|
###### Remote dev notify.
|
|
296
|
+
|
|
255
297
|
```ts
|
|
256
298
|
// Only run in development
|
|
257
299
|
if (import.meta.env.DEV) {
|
|
@@ -266,13 +308,20 @@ if (import.meta.env.DEV) {
|
|
|
266
308
|
}
|
|
267
309
|
```
|
|
268
310
|
|
|
269
|
-
|
|
311
|
+
---
|
|
270
312
|
|
|
271
|
-
|
|
313
|
+
### Plugin API Summary
|
|
272
314
|
|
|
273
|
-
|
|
315
|
+
| Method | Description |
|
|
316
|
+
| ------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
317
|
+
| `MFEHost.load(url, global)` | Load a remote JS bundle from URL. |
|
|
318
|
+
| `MFEHost.mount(remote, el, name, options?)` | Mount remote app into a container element, optionally in shadow DOM. |
|
|
319
|
+
| `MFEHost.unmount(remote, el)` | Unmount a remote app. |
|
|
320
|
+
| `MFEHost.reloadRemote({ name, url, global, el })` | Reload a remote app (unmount + reload script + mount). |
|
|
321
|
+
| `MFEHost.getEventBus()` | Access central event bus for custom events. |
|
|
322
|
+
| `createSharedStore(initial)` | Create a shared state store with `getState()`, `setState()`, `subscribe()`. |
|
|
323
|
+
| `createSharedRouter({ eventBus, name })` | Router helper: `go(path)`, `onChange(cb)`, `emitRouteChange(path)`, `onRouteChange(cb)`. |
|
|
274
324
|
|
|
275
|
-
- Purpose: smooth dev experience for micro-frontends, framework-agnostic, avoids full page reload.
|
|
276
325
|
|
|
277
326
|
---
|
|
278
327
|
|
|
@@ -314,6 +363,38 @@ if (import.meta.env.DEV) {
|
|
|
314
363
|
|
|
315
364
|
---
|
|
316
365
|
|
|
366
|
+
#### Flowchart
|
|
367
|
+
|
|
368
|
+
```css
|
|
369
|
+
┌────────────────────┐
|
|
370
|
+
│ Host │
|
|
371
|
+
│--------------------│
|
|
372
|
+
│ - stores │
|
|
373
|
+
│ - eventBus │
|
|
374
|
+
│ - navigate() │
|
|
375
|
+
└────────────────────┘
|
|
376
|
+
▲
|
|
377
|
+
│
|
|
378
|
+
┌─────────────┴─────────────┐
|
|
379
|
+
│ │
|
|
380
|
+
ROUTER / EVENTS SHARED STORE
|
|
381
|
+
│ │
|
|
382
|
+
▼ ▼
|
|
383
|
+
┌────────────────────┐ ┌────────────────────┐
|
|
384
|
+
│ Remote App A │ │ Remote App B │
|
|
385
|
+
│--------------------│ │--------------------│
|
|
386
|
+
│ - mount(container)│ │ - mount(container)│
|
|
387
|
+
│ - unmount() │ │ - unmount() │
|
|
388
|
+
│ - emit events │ │ - emit events │
|
|
389
|
+
│ - go(path) │ │ - go(path) │
|
|
390
|
+
│ - onChange(cb) │ │ - onChange(cb) │
|
|
391
|
+
│ - onRouteChange() │ │ - onRouteChange() │
|
|
392
|
+
│ - use shared store│ │ - use shared store│
|
|
393
|
+
└────────────────────┘ └────────────────────┘
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
317
398
|
### License
|
|
318
399
|
|
|
319
400
|
MIT
|
package/build/index.esm.js
CHANGED
|
@@ -1,340 +1 @@
|
|
|
1
|
-
|
|
2
|
-
Copyright (c) Microsoft Corporation.
|
|
3
|
-
|
|
4
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
5
|
-
purpose with or without fee is hereby granted.
|
|
6
|
-
|
|
7
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
-
***************************************************************************** */
|
|
15
|
-
|
|
16
|
-
var __assign = function() {
|
|
17
|
-
__assign = Object.assign || function __assign(t) {
|
|
18
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
19
|
-
s = arguments[i];
|
|
20
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
21
|
-
}
|
|
22
|
-
return t;
|
|
23
|
-
};
|
|
24
|
-
return __assign.apply(this, arguments);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
28
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
29
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
30
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
31
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
32
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
33
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function __generator(thisArg, body) {
|
|
38
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
39
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
40
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
41
|
-
function step(op) {
|
|
42
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
43
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
44
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
45
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
46
|
-
switch (op[0]) {
|
|
47
|
-
case 0: case 1: t = op; break;
|
|
48
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
49
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
50
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
51
|
-
default:
|
|
52
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
53
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
54
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
55
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
56
|
-
if (t[2]) _.ops.pop();
|
|
57
|
-
_.trys.pop(); continue;
|
|
58
|
-
}
|
|
59
|
-
op = body.call(thisArg, _);
|
|
60
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
61
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
66
|
-
var e = new Error(message);
|
|
67
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
// loader/loadScript.ts
|
|
71
|
-
var loaded = new Set();
|
|
72
|
-
function loadScript(url, options) {
|
|
73
|
-
if (options === void 0) { options = {}; }
|
|
74
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
75
|
-
var _a, timeout, _b, retries, attempt, err_1;
|
|
76
|
-
return __generator(this, function (_c) {
|
|
77
|
-
switch (_c.label) {
|
|
78
|
-
case 0:
|
|
79
|
-
_a = options.timeout, timeout = _a === void 0 ? 15000 : _a, _b = options.retries, retries = _b === void 0 ? 1 : _b;
|
|
80
|
-
if (loaded.has(url))
|
|
81
|
-
return [2 /*return*/];
|
|
82
|
-
attempt = 0;
|
|
83
|
-
_c.label = 1;
|
|
84
|
-
case 1:
|
|
85
|
-
if (!(attempt <= retries)) return [3 /*break*/, 6];
|
|
86
|
-
_c.label = 2;
|
|
87
|
-
case 2:
|
|
88
|
-
_c.trys.push([2, 4, , 5]);
|
|
89
|
-
return [4 /*yield*/, loadOnce(url, timeout)];
|
|
90
|
-
case 3:
|
|
91
|
-
_c.sent();
|
|
92
|
-
loaded.add(url);
|
|
93
|
-
return [2 /*return*/];
|
|
94
|
-
case 4:
|
|
95
|
-
err_1 = _c.sent();
|
|
96
|
-
if (attempt === retries) {
|
|
97
|
-
throw err_1;
|
|
98
|
-
}
|
|
99
|
-
return [3 /*break*/, 5];
|
|
100
|
-
case 5:
|
|
101
|
-
attempt++;
|
|
102
|
-
return [3 /*break*/, 1];
|
|
103
|
-
case 6: return [2 /*return*/];
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
function loadOnce(url, timeout) {
|
|
109
|
-
return new Promise(function (resolve, reject) {
|
|
110
|
-
var script = document.createElement("script");
|
|
111
|
-
script.src = url;
|
|
112
|
-
script.async = true;
|
|
113
|
-
var timer = setTimeout(function () {
|
|
114
|
-
cleanup();
|
|
115
|
-
reject(new Error("Timeout loading ".concat(url)));
|
|
116
|
-
}, timeout);
|
|
117
|
-
function cleanup() {
|
|
118
|
-
clearTimeout(timer);
|
|
119
|
-
script.remove();
|
|
120
|
-
}
|
|
121
|
-
script.onload = function () {
|
|
122
|
-
cleanup();
|
|
123
|
-
resolve();
|
|
124
|
-
};
|
|
125
|
-
script.onerror = function () {
|
|
126
|
-
cleanup();
|
|
127
|
-
reject(new Error("Failed to load ".concat(url)));
|
|
128
|
-
};
|
|
129
|
-
document.body.appendChild(script);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
var EventBus = /** @class */ (function () {
|
|
134
|
-
function EventBus() {
|
|
135
|
-
this.map = new Map();
|
|
136
|
-
}
|
|
137
|
-
EventBus.prototype.on = function (event, handler) {
|
|
138
|
-
if (!this.map.has(event)) {
|
|
139
|
-
this.map.set(event, new Set());
|
|
140
|
-
}
|
|
141
|
-
this.map.get(event).add(handler);
|
|
142
|
-
};
|
|
143
|
-
EventBus.prototype.off = function (event, handler) {
|
|
144
|
-
var _a;
|
|
145
|
-
(_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.delete(handler);
|
|
146
|
-
};
|
|
147
|
-
EventBus.prototype.emit = function (event, payload) {
|
|
148
|
-
var _a;
|
|
149
|
-
(_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.forEach(function (fn) { return fn(payload); });
|
|
150
|
-
};
|
|
151
|
-
return EventBus;
|
|
152
|
-
}());
|
|
153
|
-
|
|
154
|
-
var ROUTER_EVENTS = {
|
|
155
|
-
REQUEST_NAVIGATE: "ROUTER:REQUEST_NAVIGATE",
|
|
156
|
-
NAVIGATE: "ROUTER:NAVIGATE",
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
function enableRouterSync(eventBus, navigate) {
|
|
160
|
-
eventBus.on(ROUTER_EVENTS.REQUEST_NAVIGATE, function (_a) {
|
|
161
|
-
var path = _a.path;
|
|
162
|
-
navigate(path);
|
|
163
|
-
eventBus.emit(ROUTER_EVENTS.NAVIGATE, { path: path });
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
var MFEHost = /** @class */ (function () {
|
|
168
|
-
function MFEHost(options) {
|
|
169
|
-
if (options === void 0) { options = {}; }
|
|
170
|
-
var _a, _b;
|
|
171
|
-
this.eventBus = new EventBus();
|
|
172
|
-
this.isolate = false;
|
|
173
|
-
this.stores = (_a = options.stores) !== null && _a !== void 0 ? _a : {};
|
|
174
|
-
this.navigate = options.navigate;
|
|
175
|
-
this.onRemoteError = options.onRemoteError;
|
|
176
|
-
this.fallback = options.fallback;
|
|
177
|
-
this.isolate = (_b = options.isolate) !== null && _b !== void 0 ? _b : false;
|
|
178
|
-
if (this.navigate) {
|
|
179
|
-
enableRouterSync(this.eventBus, this.navigate);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
/** Load remote JS only */
|
|
183
|
-
MFEHost.prototype.load = function (url, global) {
|
|
184
|
-
var _a, _b;
|
|
185
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
186
|
-
var err_1, remote, err;
|
|
187
|
-
return __generator(this, function (_c) {
|
|
188
|
-
switch (_c.label) {
|
|
189
|
-
case 0:
|
|
190
|
-
_c.trys.push([0, 2, , 3]);
|
|
191
|
-
return [4 /*yield*/, loadScript(url, { retries: 1 })];
|
|
192
|
-
case 1:
|
|
193
|
-
_c.sent();
|
|
194
|
-
return [3 /*break*/, 3];
|
|
195
|
-
case 2:
|
|
196
|
-
err_1 = _c.sent();
|
|
197
|
-
(_a = this.onRemoteError) === null || _a === void 0 ? void 0 : _a.call(this, err_1);
|
|
198
|
-
throw err_1;
|
|
199
|
-
case 3:
|
|
200
|
-
remote = window[global];
|
|
201
|
-
if (!(remote === null || remote === void 0 ? void 0 : remote.mount)) {
|
|
202
|
-
err = new Error("Remote \"".concat(global, "\" not found"));
|
|
203
|
-
(_b = this.onRemoteError) === null || _b === void 0 ? void 0 : _b.call(this, err);
|
|
204
|
-
throw err;
|
|
205
|
-
}
|
|
206
|
-
return [2 /*return*/, remote];
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
};
|
|
211
|
-
/** Mount remote with optional Shadow DOM isolation */
|
|
212
|
-
MFEHost.prototype.mount = function (remote, el, name, options) {
|
|
213
|
-
var _a, _b;
|
|
214
|
-
var isolate = (_a = options === null || options === void 0 ? void 0 : options.isolate) !== null && _a !== void 0 ? _a : this.isolate;
|
|
215
|
-
var mountEl = el;
|
|
216
|
-
// Shadow DOM isolation
|
|
217
|
-
if (isolate) {
|
|
218
|
-
if (el._shadowRoot)
|
|
219
|
-
el._shadowRoot.innerHTML = "";
|
|
220
|
-
var mode = (_b = options === null || options === void 0 ? void 0 : options.shadowMode) !== null && _b !== void 0 ? _b : "open";
|
|
221
|
-
// @ts-ignore
|
|
222
|
-
var shadow = el.attachShadow({ mode: mode })(el)._shadowRoot = shadow;
|
|
223
|
-
// For React/Vue remotes, create container div
|
|
224
|
-
var container = document.createElement("div");
|
|
225
|
-
shadow.appendChild(container);
|
|
226
|
-
// @ts-ignore
|
|
227
|
-
mountEl = container(el)._mountEl = container;
|
|
228
|
-
}
|
|
229
|
-
var ctx = {
|
|
230
|
-
name: name,
|
|
231
|
-
stores: this.stores,
|
|
232
|
-
eventBus: this.eventBus,
|
|
233
|
-
host: { navigate: this.navigate },
|
|
234
|
-
};
|
|
235
|
-
try {
|
|
236
|
-
remote.mount(mountEl, ctx);
|
|
237
|
-
console.log("[MFE] mounted ".concat(name, " ").concat(isolate ? "(shadow)" : ""));
|
|
238
|
-
}
|
|
239
|
-
catch (err) {
|
|
240
|
-
var error = err;
|
|
241
|
-
console.error("[MFE] remote ".concat(name, " mount failed:"), error);
|
|
242
|
-
if (this.onRemoteError)
|
|
243
|
-
this.onRemoteError(error);
|
|
244
|
-
if (this.fallback) {
|
|
245
|
-
this.fallback(mountEl, name, error, ctx);
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
mountEl.innerHTML = "<div style=\"color:red\">Failed to load ".concat(name, "</div>");
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
};
|
|
252
|
-
/** Unmount remote */
|
|
253
|
-
MFEHost.prototype.unmount = function (remote, el, name) {
|
|
254
|
-
var _a, _b, _c, _d;
|
|
255
|
-
try {
|
|
256
|
-
var mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : (this.isolate ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
|
|
257
|
-
(_c = remote.unmount) === null || _c === void 0 ? void 0 : _c.call(remote, mountEl);
|
|
258
|
-
delete el._mountEl;
|
|
259
|
-
if (name)
|
|
260
|
-
console.log("[MFE] unmounted ".concat(name));
|
|
261
|
-
}
|
|
262
|
-
catch (err) {
|
|
263
|
-
(_d = this.onRemoteError) === null || _d === void 0 ? void 0 : _d.call(this, err);
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
/** Get central event bus */
|
|
267
|
-
MFEHost.prototype.getEventBus = function () {
|
|
268
|
-
return this.eventBus;
|
|
269
|
-
};
|
|
270
|
-
/** Reload remote: unmount + reload script + mount again */
|
|
271
|
-
MFEHost.prototype.reloadRemote = function (options) {
|
|
272
|
-
var _a, _b, _c;
|
|
273
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
274
|
-
var name, url, global, el, isolate, oldRemote, mountEl, newRemote;
|
|
275
|
-
return __generator(this, function (_d) {
|
|
276
|
-
switch (_d.label) {
|
|
277
|
-
case 0:
|
|
278
|
-
name = options.name, url = options.url, global = options.global, el = options.el, isolate = options.isolate;
|
|
279
|
-
try {
|
|
280
|
-
oldRemote = window[global];
|
|
281
|
-
mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : ((isolate !== null && isolate !== void 0 ? isolate : this.isolate) ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
|
|
282
|
-
(_c = oldRemote === null || oldRemote === void 0 ? void 0 : oldRemote.unmount) === null || _c === void 0 ? void 0 : _c.call(oldRemote, mountEl);
|
|
283
|
-
}
|
|
284
|
-
catch (_e) { }
|
|
285
|
-
delete window[global];
|
|
286
|
-
return [4 /*yield*/, this.load("".concat(url, "?t=").concat(Date.now()), global)];
|
|
287
|
-
case 1:
|
|
288
|
-
newRemote = _d.sent();
|
|
289
|
-
this.mount(newRemote, el, name, { isolate: isolate });
|
|
290
|
-
return [2 /*return*/];
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
};
|
|
295
|
-
return MFEHost;
|
|
296
|
-
}());
|
|
297
|
-
|
|
298
|
-
function createSharedStore(initial) {
|
|
299
|
-
var state = initial;
|
|
300
|
-
var listeners = new Set();
|
|
301
|
-
return {
|
|
302
|
-
getState: function () {
|
|
303
|
-
return state;
|
|
304
|
-
},
|
|
305
|
-
/** Update state (shallow merge) */
|
|
306
|
-
setState: function (partial) {
|
|
307
|
-
state = __assign(__assign({}, state), partial);
|
|
308
|
-
listeners.forEach(function (listener) { return listener(state); });
|
|
309
|
-
},
|
|
310
|
-
/** Subscribe to state changes */
|
|
311
|
-
subscribe: function (fn, callImmediately) {
|
|
312
|
-
if (callImmediately === void 0) { callImmediately = true; }
|
|
313
|
-
listeners.add(fn);
|
|
314
|
-
if (callImmediately)
|
|
315
|
-
fn(state); // Immediately call listener with current state
|
|
316
|
-
return function () { return listeners.delete(fn); };
|
|
317
|
-
},
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
function createSharedRouter(ctx) {
|
|
322
|
-
var eventBus = ctx.eventBus, name = ctx.name;
|
|
323
|
-
return {
|
|
324
|
-
/** Remote → Host */
|
|
325
|
-
go: function (path) {
|
|
326
|
-
eventBus.emit(ROUTER_EVENTS.REQUEST_NAVIGATE, {
|
|
327
|
-
from: name,
|
|
328
|
-
path: path,
|
|
329
|
-
});
|
|
330
|
-
},
|
|
331
|
-
/** Host → Remote */
|
|
332
|
-
onChange: function (cb) {
|
|
333
|
-
return eventBus.on(ROUTER_EVENTS.NAVIGATE, function (payload) {
|
|
334
|
-
cb(payload.path);
|
|
335
|
-
});
|
|
336
|
-
},
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export { EventBus, MFEHost, createSharedRouter, createSharedStore, enableRouterSync, loadScript };
|
|
1
|
+
var t=function(){return t=Object.assign||function(t){for(var n,o=1,e=arguments.length;o<e;o++)for(var r in n=arguments[o])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},t.apply(this,arguments)};function n(t,n,o,e){return new(o||(o=Promise))(function(r,i){function a(t){try{l(e.next(t))}catch(t){i(t)}}function u(t){try{l(e.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof o?n:new o(function(t){t(n)})).then(a,u)}l((e=e.apply(t,n||[])).next())})}function o(t,n){var o,e,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(o)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(o=1,e&&(r=2&u[0]?e.return:u[0]?e.throw||((r=e.return)&&r.call(e),0):e.next)&&!(r=r.call(e,u[1])).done)return r;switch(e=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,e=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],e=0}finally{o=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var e=new Set;function r(t,r){return void 0===r&&(r={}),n(this,void 0,void 0,function(){var n,a,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(n=r.timeout,a=void 0===n?15e3:n,u=r.retries,l=void 0===u?1:u,e.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,i(t,a)];case 3:return o.sent(),e.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function i(t,n){return new Promise(function(o,e){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),e(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),o()},r.onerror=function(){a(),e(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var a=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var o;null===(o=this.map.get(t))||void 0===o||o.delete(n)},t.prototype.emit=function(t,n){var o;null===(o=this.map.get(t))||void 0===o||o.forEach(function(t){return t(n)})},t}(),u="ROUTER:REQUEST_NAVIGATE",l="ROUTER:NAVIGATE",c="ROUTER:ON_CHANGE";function s(t,n){t.on(u,function(o){var e=o.path;n(e),t.emit(l,{path:e})})}var h=function(){function t(t){void 0===t&&(t={});var n,o,e=this;this.eventBus=new a,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(o=t.isolate)&&void 0!==o&&o,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&s(this.eventBus,this.navigate),this.eventBus.on(c,function(t){var n;null===(n=e.navigate)||void 0===n||n.call(e,t)})}return t.prototype.load=function(t,e){var i,a;return n(this,void 0,void 0,function(){var n,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[e])return[2,this.cache[e]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,r(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw n=o.sent(),null===(i=this.onRemoteError)||void 0===i||i.call(this,n),n;case 4:if(!(null==(u=window[e])?void 0:u.mount))throw l=new Error('Remote "'.concat(e,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[e]=u,[2,u]}})})},t.prototype.preload=function(t,e){return n(this,void 0,void 0,function(){return o(this,function(n){switch(n.label){case 0:return[4,this.load(t,e)];case 1:return n.sent(),[2]}})})},t.prototype.mount=function(t,n,o,e){var r,i,a,u,l,c=null!==(r=null==e?void 0:e.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==e?void 0:e.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:o,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,o),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,o),console.log("[MFE] mounted ".concat(o," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(o," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,o,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(o,"</div>")}},t.prototype.unmount=function(t,n,o){var e,r,i,a,u,l;try{null===(e=this.onUnmountStart)||void 0===e||e.call(this,null!=o?o:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=o?o:""),o&&console.log("[MFE] unmounted ".concat(o))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var e,r,i;return n(this,void 0,void 0,function(){var n,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:n=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(e=l._mountEl)&&void 0!==e?e:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,n,{isolate:c}),[2]}})})},t}();function d(n){var o=n,e=new Set;return{getState:function(){return o},setState:function(n){o=t(t({},o),n),e.forEach(function(t){return t(o)})},subscribe:function(t,n){return void 0===n&&(n=!0),e.add(t),n&&t(o),function(){return e.delete(t)}}}}function f(t){var n=t.eventBus,o=t.name;return{go:function(t){n.emit(u,{from:o,path:t})},onChange:function(t){return n.on(l,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(c,{from:o,path:t})},onRouteChange:function(t){return n.on(c,function(n){n.from!==o&&t(n.path)})}}}export{a as EventBus,h as MFEHost,f as createSharedRouter,d as createSharedStore,s as enableRouterSync,r as loadScript};
|
package/build/index.js
CHANGED
|
@@ -1,355 +1 @@
|
|
|
1
|
-
(function (global,
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MFERuntimeZ = {}));
|
|
5
|
-
})(this, (function (exports) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/******************************************************************************
|
|
8
|
-
Copyright (c) Microsoft Corporation.
|
|
9
|
-
|
|
10
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
11
|
-
purpose with or without fee is hereby granted.
|
|
12
|
-
|
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
14
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
15
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
16
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
17
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
18
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
19
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
20
|
-
***************************************************************************** */
|
|
21
|
-
|
|
22
|
-
var __assign = function() {
|
|
23
|
-
__assign = Object.assign || function __assign(t) {
|
|
24
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
25
|
-
s = arguments[i];
|
|
26
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
27
|
-
}
|
|
28
|
-
return t;
|
|
29
|
-
};
|
|
30
|
-
return __assign.apply(this, arguments);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
34
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
35
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
36
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
37
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
38
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
39
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function __generator(thisArg, body) {
|
|
44
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
45
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
46
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
47
|
-
function step(op) {
|
|
48
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
49
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
50
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
51
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
52
|
-
switch (op[0]) {
|
|
53
|
-
case 0: case 1: t = op; break;
|
|
54
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
55
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
56
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
57
|
-
default:
|
|
58
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
59
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
60
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
61
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
62
|
-
if (t[2]) _.ops.pop();
|
|
63
|
-
_.trys.pop(); continue;
|
|
64
|
-
}
|
|
65
|
-
op = body.call(thisArg, _);
|
|
66
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
67
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
72
|
-
var e = new Error(message);
|
|
73
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// loader/loadScript.ts
|
|
77
|
-
var loaded = new Set();
|
|
78
|
-
function loadScript(url, options) {
|
|
79
|
-
if (options === void 0) { options = {}; }
|
|
80
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
81
|
-
var _a, timeout, _b, retries, attempt, err_1;
|
|
82
|
-
return __generator(this, function (_c) {
|
|
83
|
-
switch (_c.label) {
|
|
84
|
-
case 0:
|
|
85
|
-
_a = options.timeout, timeout = _a === void 0 ? 15000 : _a, _b = options.retries, retries = _b === void 0 ? 1 : _b;
|
|
86
|
-
if (loaded.has(url))
|
|
87
|
-
return [2 /*return*/];
|
|
88
|
-
attempt = 0;
|
|
89
|
-
_c.label = 1;
|
|
90
|
-
case 1:
|
|
91
|
-
if (!(attempt <= retries)) return [3 /*break*/, 6];
|
|
92
|
-
_c.label = 2;
|
|
93
|
-
case 2:
|
|
94
|
-
_c.trys.push([2, 4, , 5]);
|
|
95
|
-
return [4 /*yield*/, loadOnce(url, timeout)];
|
|
96
|
-
case 3:
|
|
97
|
-
_c.sent();
|
|
98
|
-
loaded.add(url);
|
|
99
|
-
return [2 /*return*/];
|
|
100
|
-
case 4:
|
|
101
|
-
err_1 = _c.sent();
|
|
102
|
-
if (attempt === retries) {
|
|
103
|
-
throw err_1;
|
|
104
|
-
}
|
|
105
|
-
return [3 /*break*/, 5];
|
|
106
|
-
case 5:
|
|
107
|
-
attempt++;
|
|
108
|
-
return [3 /*break*/, 1];
|
|
109
|
-
case 6: return [2 /*return*/];
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
function loadOnce(url, timeout) {
|
|
115
|
-
return new Promise(function (resolve, reject) {
|
|
116
|
-
var script = document.createElement("script");
|
|
117
|
-
script.src = url;
|
|
118
|
-
script.async = true;
|
|
119
|
-
var timer = setTimeout(function () {
|
|
120
|
-
cleanup();
|
|
121
|
-
reject(new Error("Timeout loading ".concat(url)));
|
|
122
|
-
}, timeout);
|
|
123
|
-
function cleanup() {
|
|
124
|
-
clearTimeout(timer);
|
|
125
|
-
script.remove();
|
|
126
|
-
}
|
|
127
|
-
script.onload = function () {
|
|
128
|
-
cleanup();
|
|
129
|
-
resolve();
|
|
130
|
-
};
|
|
131
|
-
script.onerror = function () {
|
|
132
|
-
cleanup();
|
|
133
|
-
reject(new Error("Failed to load ".concat(url)));
|
|
134
|
-
};
|
|
135
|
-
document.body.appendChild(script);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
var EventBus = /** @class */ (function () {
|
|
140
|
-
function EventBus() {
|
|
141
|
-
this.map = new Map();
|
|
142
|
-
}
|
|
143
|
-
EventBus.prototype.on = function (event, handler) {
|
|
144
|
-
if (!this.map.has(event)) {
|
|
145
|
-
this.map.set(event, new Set());
|
|
146
|
-
}
|
|
147
|
-
this.map.get(event).add(handler);
|
|
148
|
-
};
|
|
149
|
-
EventBus.prototype.off = function (event, handler) {
|
|
150
|
-
var _a;
|
|
151
|
-
(_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.delete(handler);
|
|
152
|
-
};
|
|
153
|
-
EventBus.prototype.emit = function (event, payload) {
|
|
154
|
-
var _a;
|
|
155
|
-
(_a = this.map.get(event)) === null || _a === void 0 ? void 0 : _a.forEach(function (fn) { return fn(payload); });
|
|
156
|
-
};
|
|
157
|
-
return EventBus;
|
|
158
|
-
}());
|
|
159
|
-
|
|
160
|
-
var ROUTER_EVENTS = {
|
|
161
|
-
REQUEST_NAVIGATE: "ROUTER:REQUEST_NAVIGATE",
|
|
162
|
-
NAVIGATE: "ROUTER:NAVIGATE",
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
function enableRouterSync(eventBus, navigate) {
|
|
166
|
-
eventBus.on(ROUTER_EVENTS.REQUEST_NAVIGATE, function (_a) {
|
|
167
|
-
var path = _a.path;
|
|
168
|
-
navigate(path);
|
|
169
|
-
eventBus.emit(ROUTER_EVENTS.NAVIGATE, { path: path });
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
var MFEHost = /** @class */ (function () {
|
|
174
|
-
function MFEHost(options) {
|
|
175
|
-
if (options === void 0) { options = {}; }
|
|
176
|
-
var _a, _b;
|
|
177
|
-
this.eventBus = new EventBus();
|
|
178
|
-
this.isolate = false;
|
|
179
|
-
this.stores = (_a = options.stores) !== null && _a !== void 0 ? _a : {};
|
|
180
|
-
this.navigate = options.navigate;
|
|
181
|
-
this.onRemoteError = options.onRemoteError;
|
|
182
|
-
this.fallback = options.fallback;
|
|
183
|
-
this.isolate = (_b = options.isolate) !== null && _b !== void 0 ? _b : false;
|
|
184
|
-
if (this.navigate) {
|
|
185
|
-
enableRouterSync(this.eventBus, this.navigate);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
/** Load remote JS only */
|
|
189
|
-
MFEHost.prototype.load = function (url, global) {
|
|
190
|
-
var _a, _b;
|
|
191
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
192
|
-
var err_1, remote, err;
|
|
193
|
-
return __generator(this, function (_c) {
|
|
194
|
-
switch (_c.label) {
|
|
195
|
-
case 0:
|
|
196
|
-
_c.trys.push([0, 2, , 3]);
|
|
197
|
-
return [4 /*yield*/, loadScript(url, { retries: 1 })];
|
|
198
|
-
case 1:
|
|
199
|
-
_c.sent();
|
|
200
|
-
return [3 /*break*/, 3];
|
|
201
|
-
case 2:
|
|
202
|
-
err_1 = _c.sent();
|
|
203
|
-
(_a = this.onRemoteError) === null || _a === void 0 ? void 0 : _a.call(this, err_1);
|
|
204
|
-
throw err_1;
|
|
205
|
-
case 3:
|
|
206
|
-
remote = window[global];
|
|
207
|
-
if (!(remote === null || remote === void 0 ? void 0 : remote.mount)) {
|
|
208
|
-
err = new Error("Remote \"".concat(global, "\" not found"));
|
|
209
|
-
(_b = this.onRemoteError) === null || _b === void 0 ? void 0 : _b.call(this, err);
|
|
210
|
-
throw err;
|
|
211
|
-
}
|
|
212
|
-
return [2 /*return*/, remote];
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
};
|
|
217
|
-
/** Mount remote with optional Shadow DOM isolation */
|
|
218
|
-
MFEHost.prototype.mount = function (remote, el, name, options) {
|
|
219
|
-
var _a, _b;
|
|
220
|
-
var isolate = (_a = options === null || options === void 0 ? void 0 : options.isolate) !== null && _a !== void 0 ? _a : this.isolate;
|
|
221
|
-
var mountEl = el;
|
|
222
|
-
// Shadow DOM isolation
|
|
223
|
-
if (isolate) {
|
|
224
|
-
if (el._shadowRoot)
|
|
225
|
-
el._shadowRoot.innerHTML = "";
|
|
226
|
-
var mode = (_b = options === null || options === void 0 ? void 0 : options.shadowMode) !== null && _b !== void 0 ? _b : "open";
|
|
227
|
-
// @ts-ignore
|
|
228
|
-
var shadow = el.attachShadow({ mode: mode })(el)._shadowRoot = shadow;
|
|
229
|
-
// For React/Vue remotes, create container div
|
|
230
|
-
var container = document.createElement("div");
|
|
231
|
-
shadow.appendChild(container);
|
|
232
|
-
// @ts-ignore
|
|
233
|
-
mountEl = container(el)._mountEl = container;
|
|
234
|
-
}
|
|
235
|
-
var ctx = {
|
|
236
|
-
name: name,
|
|
237
|
-
stores: this.stores,
|
|
238
|
-
eventBus: this.eventBus,
|
|
239
|
-
host: { navigate: this.navigate },
|
|
240
|
-
};
|
|
241
|
-
try {
|
|
242
|
-
remote.mount(mountEl, ctx);
|
|
243
|
-
console.log("[MFE] mounted ".concat(name, " ").concat(isolate ? "(shadow)" : ""));
|
|
244
|
-
}
|
|
245
|
-
catch (err) {
|
|
246
|
-
var error = err;
|
|
247
|
-
console.error("[MFE] remote ".concat(name, " mount failed:"), error);
|
|
248
|
-
if (this.onRemoteError)
|
|
249
|
-
this.onRemoteError(error);
|
|
250
|
-
if (this.fallback) {
|
|
251
|
-
this.fallback(mountEl, name, error, ctx);
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
mountEl.innerHTML = "<div style=\"color:red\">Failed to load ".concat(name, "</div>");
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
/** Unmount remote */
|
|
259
|
-
MFEHost.prototype.unmount = function (remote, el, name) {
|
|
260
|
-
var _a, _b, _c, _d;
|
|
261
|
-
try {
|
|
262
|
-
var mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : (this.isolate ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
|
|
263
|
-
(_c = remote.unmount) === null || _c === void 0 ? void 0 : _c.call(remote, mountEl);
|
|
264
|
-
delete el._mountEl;
|
|
265
|
-
if (name)
|
|
266
|
-
console.log("[MFE] unmounted ".concat(name));
|
|
267
|
-
}
|
|
268
|
-
catch (err) {
|
|
269
|
-
(_d = this.onRemoteError) === null || _d === void 0 ? void 0 : _d.call(this, err);
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
/** Get central event bus */
|
|
273
|
-
MFEHost.prototype.getEventBus = function () {
|
|
274
|
-
return this.eventBus;
|
|
275
|
-
};
|
|
276
|
-
/** Reload remote: unmount + reload script + mount again */
|
|
277
|
-
MFEHost.prototype.reloadRemote = function (options) {
|
|
278
|
-
var _a, _b, _c;
|
|
279
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
280
|
-
var name, url, global, el, isolate, oldRemote, mountEl, newRemote;
|
|
281
|
-
return __generator(this, function (_d) {
|
|
282
|
-
switch (_d.label) {
|
|
283
|
-
case 0:
|
|
284
|
-
name = options.name, url = options.url, global = options.global, el = options.el, isolate = options.isolate;
|
|
285
|
-
try {
|
|
286
|
-
oldRemote = window[global];
|
|
287
|
-
mountEl = (_a = el._mountEl) !== null && _a !== void 0 ? _a : ((isolate !== null && isolate !== void 0 ? isolate : this.isolate) ? (_b = el.shadowRoot) !== null && _b !== void 0 ? _b : el : el);
|
|
288
|
-
(_c = oldRemote === null || oldRemote === void 0 ? void 0 : oldRemote.unmount) === null || _c === void 0 ? void 0 : _c.call(oldRemote, mountEl);
|
|
289
|
-
}
|
|
290
|
-
catch (_e) { }
|
|
291
|
-
delete window[global];
|
|
292
|
-
return [4 /*yield*/, this.load("".concat(url, "?t=").concat(Date.now()), global)];
|
|
293
|
-
case 1:
|
|
294
|
-
newRemote = _d.sent();
|
|
295
|
-
this.mount(newRemote, el, name, { isolate: isolate });
|
|
296
|
-
return [2 /*return*/];
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
});
|
|
300
|
-
};
|
|
301
|
-
return MFEHost;
|
|
302
|
-
}());
|
|
303
|
-
|
|
304
|
-
function createSharedStore(initial) {
|
|
305
|
-
var state = initial;
|
|
306
|
-
var listeners = new Set();
|
|
307
|
-
return {
|
|
308
|
-
getState: function () {
|
|
309
|
-
return state;
|
|
310
|
-
},
|
|
311
|
-
/** Update state (shallow merge) */
|
|
312
|
-
setState: function (partial) {
|
|
313
|
-
state = __assign(__assign({}, state), partial);
|
|
314
|
-
listeners.forEach(function (listener) { return listener(state); });
|
|
315
|
-
},
|
|
316
|
-
/** Subscribe to state changes */
|
|
317
|
-
subscribe: function (fn, callImmediately) {
|
|
318
|
-
if (callImmediately === void 0) { callImmediately = true; }
|
|
319
|
-
listeners.add(fn);
|
|
320
|
-
if (callImmediately)
|
|
321
|
-
fn(state); // Immediately call listener with current state
|
|
322
|
-
return function () { return listeners.delete(fn); };
|
|
323
|
-
},
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
function createSharedRouter(ctx) {
|
|
328
|
-
var eventBus = ctx.eventBus, name = ctx.name;
|
|
329
|
-
return {
|
|
330
|
-
/** Remote → Host */
|
|
331
|
-
go: function (path) {
|
|
332
|
-
eventBus.emit(ROUTER_EVENTS.REQUEST_NAVIGATE, {
|
|
333
|
-
from: name,
|
|
334
|
-
path: path,
|
|
335
|
-
});
|
|
336
|
-
},
|
|
337
|
-
/** Host → Remote */
|
|
338
|
-
onChange: function (cb) {
|
|
339
|
-
return eventBus.on(ROUTER_EVENTS.NAVIGATE, function (payload) {
|
|
340
|
-
cb(payload.path);
|
|
341
|
-
});
|
|
342
|
-
},
|
|
343
|
-
};
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
exports.EventBus = EventBus;
|
|
347
|
-
exports.MFEHost = MFEHost;
|
|
348
|
-
exports.createSharedRouter = createSharedRouter;
|
|
349
|
-
exports.createSharedStore = createSharedStore;
|
|
350
|
-
exports.enableRouterSync = enableRouterSync;
|
|
351
|
-
exports.loadScript = loadScript;
|
|
352
|
-
|
|
353
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
354
|
-
|
|
355
|
-
}));
|
|
1
|
+
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).MFERuntimeZ={})}(this,function(t){"use strict";var n=function(){return n=Object.assign||function(t){for(var n,e=1,o=arguments.length;e<o;e++)for(var r in n=arguments[e])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},n.apply(this,arguments)};function e(t,n,e,o){return new(e||(e=Promise))(function(r,i){function a(t){try{l(o.next(t))}catch(t){i(t)}}function u(t){try{l(o.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof e?n:new e(function(t){t(n)})).then(a,u)}l((o=o.apply(t,n||[])).next())})}function o(t,n){var e,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(e)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(e=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],o=0}finally{e=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var r=new Set;function i(t,n){return void 0===n&&(n={}),e(this,void 0,void 0,function(){var e,i,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(e=n.timeout,i=void 0===e?15e3:e,u=n.retries,l=void 0===u?1:u,r.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,a(t,i)];case 3:return o.sent(),r.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function a(t,n){return new Promise(function(e,o){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),o(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),e()},r.onerror=function(){a(),o(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var u=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.delete(n)},t.prototype.emit=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.forEach(function(t){return t(n)})},t}(),l="ROUTER:REQUEST_NAVIGATE",c="ROUTER:NAVIGATE",s="ROUTER:ON_CHANGE";function h(t,n){t.on(l,function(e){var o=e.path;n(o),t.emit(c,{path:o})})}var d=function(){function t(t){void 0===t&&(t={});var n,e,o=this;this.eventBus=new u,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(e=t.isolate)&&void 0!==e&&e,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&h(this.eventBus,this.navigate),this.eventBus.on(s,function(t){var n;null===(n=o.navigate)||void 0===n||n.call(o,t)})}return t.prototype.load=function(t,n){var r,a;return e(this,void 0,void 0,function(){var e,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[n])return[2,this.cache[n]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,i(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw e=o.sent(),null===(r=this.onRemoteError)||void 0===r||r.call(this,e),e;case 4:if(!(null==(u=window[n])?void 0:u.mount))throw l=new Error('Remote "'.concat(n,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[n]=u,[2,u]}})})},t.prototype.preload=function(t,n){return e(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,this.load(t,n)];case 1:return e.sent(),[2]}})})},t.prototype.mount=function(t,n,e,o){var r,i,a,u,l,c=null!==(r=null==o?void 0:o.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==o?void 0:o.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:e,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,e),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,e),console.log("[MFE] mounted ".concat(e," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(e," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,e,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(e,"</div>")}},t.prototype.unmount=function(t,n,e){var o,r,i,a,u,l;try{null===(o=this.onUnmountStart)||void 0===o||o.call(this,null!=e?e:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=e?e:""),e&&console.log("[MFE] unmounted ".concat(e))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var n,r,i;return e(this,void 0,void 0,function(){var e,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:e=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(n=l._mountEl)&&void 0!==n?n:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,e,{isolate:c}),[2]}})})},t}();t.EventBus=u,t.MFEHost=d,t.createSharedRouter=function(t){var n=t.eventBus,e=t.name;return{go:function(t){n.emit(l,{from:e,path:t})},onChange:function(t){return n.on(c,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(s,{from:e,path:t})},onRouteChange:function(t){return n.on(s,function(n){n.from!==e&&t(n.path)})}}},t.createSharedStore=function(t){var e=t,o=new Set;return{getState:function(){return e},setState:function(t){e=n(n({},e),t),o.forEach(function(t){return t(e)})},subscribe:function(t,n){return void 0===n&&(n=!0),o.add(t),n&&t(e),function(){return o.delete(t)}}}},t.enableRouterSync=h,t.loadScript=i,Object.defineProperty(t,"__esModule",{value:!0})});
|
package/build/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,
|
|
1
|
+
!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((t="undefined"!=typeof globalThis?globalThis:t||self).MFERuntimeZ={})}(this,function(t){"use strict";var n=function(){return n=Object.assign||function(t){for(var n,e=1,o=arguments.length;e<o;e++)for(var r in n=arguments[e])Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r]);return t},n.apply(this,arguments)};function e(t,n,e,o){return new(e||(e=Promise))(function(r,i){function a(t){try{l(o.next(t))}catch(t){i(t)}}function u(t){try{l(o.throw(t))}catch(t){i(t)}}function l(t){var n;t.done?r(t.value):(n=t.value,n instanceof e?n:new e(function(t){t(n)})).then(a,u)}l((o=o.apply(t,n||[])).next())})}function o(t,n){var e,o,r,i={label:0,sent:function(){if(1&r[0])throw r[1];return r[1]},trys:[],ops:[]},a=Object.create(("function"==typeof Iterator?Iterator:Object).prototype);return a.next=u(0),a.throw=u(1),a.return=u(2),"function"==typeof Symbol&&(a[Symbol.iterator]=function(){return this}),a;function u(u){return function(l){return function(u){if(e)throw new TypeError("Generator is already executing.");for(;a&&(a=0,u[0]&&(i=0)),i;)try{if(e=1,o&&(r=2&u[0]?o.return:u[0]?o.throw||((r=o.return)&&r.call(o),0):o.next)&&!(r=r.call(o,u[1])).done)return r;switch(o=0,r&&(u=[2&u[0],r.value]),u[0]){case 0:case 1:r=u;break;case 4:return i.label++,{value:u[1],done:!1};case 5:i.label++,o=u[1],u=[0];continue;case 7:u=i.ops.pop(),i.trys.pop();continue;default:if(!(r=i.trys,(r=r.length>0&&r[r.length-1])||6!==u[0]&&2!==u[0])){i=0;continue}if(3===u[0]&&(!r||u[1]>r[0]&&u[1]<r[3])){i.label=u[1];break}if(6===u[0]&&i.label<r[1]){i.label=r[1],r=u;break}if(r&&i.label<r[2]){i.label=r[2],i.ops.push(u);break}r[2]&&i.ops.pop(),i.trys.pop();continue}u=n.call(t,i)}catch(t){u=[6,t],o=0}finally{e=r=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}([u,l])}}}"function"==typeof SuppressedError&&SuppressedError;var r=new Set;function i(t,n){return void 0===n&&(n={}),e(this,void 0,void 0,function(){var e,i,u,l,c,s;return o(this,function(o){switch(o.label){case 0:if(e=n.timeout,i=void 0===e?15e3:e,u=n.retries,l=void 0===u?1:u,r.has(t))return[2];c=0,o.label=1;case 1:if(!(c<=l))return[3,6];o.label=2;case 2:return o.trys.push([2,4,,5]),[4,a(t,i)];case 3:return o.sent(),r.add(t),[2];case 4:if(s=o.sent(),c===l)throw s;return[3,5];case 5:return c++,[3,1];case 6:return[2]}})})}function a(t,n){return new Promise(function(e,o){var r=document.createElement("script");r.src=t,r.async=!0;var i=setTimeout(function(){a(),o(new Error("Timeout loading ".concat(t)))},n);function a(){clearTimeout(i),r.remove()}r.onload=function(){a(),e()},r.onerror=function(){a(),o(new Error("Failed to load ".concat(t)))},document.body.appendChild(r)})}var u=function(){function t(){this.map=new Map}return t.prototype.on=function(t,n){this.map.has(t)||this.map.set(t,new Set),this.map.get(t).add(n)},t.prototype.off=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.delete(n)},t.prototype.emit=function(t,n){var e;null===(e=this.map.get(t))||void 0===e||e.forEach(function(t){return t(n)})},t}(),l="ROUTER:REQUEST_NAVIGATE",c="ROUTER:NAVIGATE",s="ROUTER:ON_CHANGE";function h(t,n){t.on(l,function(e){var o=e.path;n(o),t.emit(c,{path:o})})}var d=function(){function t(t){void 0===t&&(t={});var n,e,o=this;this.eventBus=new u,this.isolate=!1,this.cache={},this.stores=null!==(n=t.stores)&&void 0!==n?n:{},this.navigate=t.navigate,this.onRemoteError=t.onRemoteError,this.fallback=t.fallback,this.isolate=null!==(e=t.isolate)&&void 0!==e&&e,this.onMountStart=t.onMountStart,this.onMountEnd=t.onMountEnd,this.onUnmountStart=t.onUnmountStart,this.onUnmountEnd=t.onUnmountEnd,this.navigate&&h(this.eventBus,this.navigate),this.eventBus.on(s,function(t){var n;null===(n=o.navigate)||void 0===n||n.call(o,t)})}return t.prototype.load=function(t,n){var r,a;return e(this,void 0,void 0,function(){var e,u,l;return o(this,function(o){switch(o.label){case 0:if(this.cache[n])return[2,this.cache[n]];o.label=1;case 1:return o.trys.push([1,3,,4]),[4,i(t,{retries:1})];case 2:return o.sent(),[3,4];case 3:throw e=o.sent(),null===(r=this.onRemoteError)||void 0===r||r.call(this,e),e;case 4:if(!(null==(u=window[n])?void 0:u.mount))throw l=new Error('Remote "'.concat(n,'" not found')),null===(a=this.onRemoteError)||void 0===a||a.call(this,l),l;return this.cache[n]=u,[2,u]}})})},t.prototype.preload=function(t,n){return e(this,void 0,void 0,function(){return o(this,function(e){switch(e.label){case 0:return[4,this.load(t,n)];case 1:return e.sent(),[2]}})})},t.prototype.mount=function(t,n,e,o){var r,i,a,u,l,c=null!==(r=null==o?void 0:o.isolate)&&void 0!==r?r:this.isolate,s=null;if(n._shadowRoot&&(n._shadowRoot.innerHTML=""),c&&"function"==typeof n.attachShadow)try{s=n.attachShadow({mode:null!==(i=null==o?void 0:o.shadowMode)&&void 0!==i?i:"open"})(n)._shadowRoot=s}catch(t){s=null}var h=document.createElement("div");s?s.appendChild(h):n.appendChild(h),n._mountEl=h;var d={name:e,stores:this.stores,eventBus:this.eventBus,host:{navigate:this.navigate}};try{null===(a=this.onMountStart)||void 0===a||a.call(this,e),t.mount(h,d),null===(u=this.onMountEnd)||void 0===u||u.call(this,e),console.log("[MFE] mounted ".concat(e," ").concat(c?"(shadow/fallback)":""))}catch(t){var f=t;console.error("[MFE] remote ".concat(e," mount failed:"),f),null===(l=this.onRemoteError)||void 0===l||l.call(this,f),this.fallback?this.fallback(h,e,f,d):h.innerHTML='<div style="color:red">Failed to load '.concat(e,"</div>")}},t.prototype.unmount=function(t,n,e){var o,r,i,a,u,l;try{null===(o=this.onUnmountStart)||void 0===o||o.call(this,null!=e?e:"");var c=null!==(r=n._mountEl)&&void 0!==r?r:this.isolate&&null!==(i=n.shadowRoot)&&void 0!==i?i:n;null===(a=t.unmount)||void 0===a||a.call(t,c),delete n._mountEl,null===(u=this.onUnmountEnd)||void 0===u||u.call(this,null!=e?e:""),e&&console.log("[MFE] unmounted ".concat(e))}catch(t){null===(l=this.onRemoteError)||void 0===l||l.call(this,t)}},t.prototype.getEventBus=function(){return this.eventBus},t.prototype.reloadRemote=function(t){var n,r,i;return e(this,void 0,void 0,function(){var e,a,u,l,c,s,h,d;return o(this,function(o){switch(o.label){case 0:e=t.name,a=t.url,u=t.global,l=t.el,c=t.isolate;try{s=window[u],h=null!==(n=l._mountEl)&&void 0!==n?n:(null!=c?c:this.isolate)&&null!==(r=l.shadowRoot)&&void 0!==r?r:l,null===(i=null==s?void 0:s.unmount)||void 0===i||i.call(s,h)}catch(t){}return delete window[u],delete this.cache[u],[4,this.load("".concat(a,"?t=").concat(Date.now()),u)];case 1:return d=o.sent(),this.mount(d,l,e,{isolate:c}),[2]}})})},t}();t.EventBus=u,t.MFEHost=d,t.createSharedRouter=function(t){var n=t.eventBus,e=t.name;return{go:function(t){n.emit(l,{from:e,path:t})},onChange:function(t){return n.on(c,function(n){t(n.path)})},emitRouteChange:function(t){n.emit(s,{from:e,path:t})},onRouteChange:function(t){return n.on(s,function(n){n.from!==e&&t(n.path)})}}},t.createSharedStore=function(t){var e=t,o=new Set;return{getState:function(){return e},setState:function(t){e=n(n({},e),t),o.forEach(function(t){return t(e)})},subscribe:function(t,n){return void 0===n&&(n=!0),o.add(t),n&&t(e),function(){return o.delete(t)}}}},t.enableRouterSync=h,t.loadScript=i,Object.defineProperty(t,"__esModule",{value:!0})});
|
|
@@ -7,6 +7,10 @@ type HostOptions<S extends Record<string, any> = any> = {
|
|
|
7
7
|
onRemoteError?: (error: Error) => void;
|
|
8
8
|
isolate?: boolean;
|
|
9
9
|
fallback?: (el: HTMLElement, name: string, error: Error, ctx: MFEContext<S>) => void;
|
|
10
|
+
onMountStart?: (name: string) => void;
|
|
11
|
+
onMountEnd?: (name: string) => void;
|
|
12
|
+
onUnmountStart?: (name: string) => void;
|
|
13
|
+
onUnmountEnd?: (name: string) => void;
|
|
10
14
|
};
|
|
11
15
|
interface MountOptions {
|
|
12
16
|
isolate?: boolean;
|
|
@@ -19,9 +23,16 @@ export declare class MFEHost<S extends Record<string, any> = any> {
|
|
|
19
23
|
private onRemoteError?;
|
|
20
24
|
private fallback?;
|
|
21
25
|
private isolate;
|
|
26
|
+
private onMountStart?;
|
|
27
|
+
private onMountEnd?;
|
|
28
|
+
private onUnmountStart?;
|
|
29
|
+
private onUnmountEnd?;
|
|
30
|
+
private cache;
|
|
22
31
|
constructor(options?: HostOptions<S>);
|
|
23
32
|
/** Load remote JS only */
|
|
24
33
|
load(url: string, global: string): Promise<RemoteApp>;
|
|
34
|
+
/** Preload remote script */
|
|
35
|
+
preload(url: string, global: string): Promise<void>;
|
|
25
36
|
/** Mount remote with optional Shadow DOM isolation */
|
|
26
37
|
mount(remote: RemoteApp, el: HTMLElement, name: string, options?: MountOptions): void;
|
|
27
38
|
/** Unmount remote */
|
|
@@ -2,8 +2,12 @@ export declare function createSharedRouter(ctx: {
|
|
|
2
2
|
eventBus: any;
|
|
3
3
|
name: string;
|
|
4
4
|
}): {
|
|
5
|
-
/** Remote → Host */
|
|
5
|
+
/** Remote → Host: request host navigation */
|
|
6
6
|
go(path: string): void;
|
|
7
|
-
/** Host → Remote */
|
|
7
|
+
/** Host → Remote: register callback when host navigates */
|
|
8
8
|
onChange(cb: (path: string) => void): any;
|
|
9
|
+
/** Remote → all: notify route change */
|
|
10
|
+
emitRouteChange(path: string): void;
|
|
11
|
+
/** Remote → Remote: register listener for route changes (excluding self) */
|
|
12
|
+
onRouteChange(cb: (path: string) => void): any;
|
|
9
13
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mfe-runtime-z",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "Framework-agnostic micro-frontend runtime (host, event bus, shared state, router sync)",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"module": "build/index.esm.js",
|
|
@@ -33,14 +33,60 @@
|
|
|
33
33
|
"homepage": "https://github.com/delpikye-v/mfe-runtime-z#readme",
|
|
34
34
|
"keywords": [
|
|
35
35
|
"micro-frontend",
|
|
36
|
+
"microfrontend",
|
|
36
37
|
"mfe",
|
|
38
|
+
"micro-fe",
|
|
39
|
+
|
|
40
|
+
"module-federation",
|
|
41
|
+
"webpack-module-federation",
|
|
42
|
+
"vite-federation",
|
|
43
|
+
|
|
37
44
|
"runtime",
|
|
45
|
+
"runtime-loader",
|
|
46
|
+
"dynamic-runtime",
|
|
47
|
+
"micro-frontend-runtime",
|
|
48
|
+
"mfe-runtime",
|
|
49
|
+
|
|
50
|
+
"framework-agnostic",
|
|
51
|
+
"framework-independent",
|
|
52
|
+
"cross-framework",
|
|
53
|
+
|
|
54
|
+
"react",
|
|
55
|
+
"vue",
|
|
56
|
+
"angular",
|
|
57
|
+
"svelte",
|
|
58
|
+
|
|
38
59
|
"event-bus",
|
|
60
|
+
"global-event-bus",
|
|
61
|
+
"cross-app-events",
|
|
62
|
+
|
|
39
63
|
"shared-state",
|
|
64
|
+
"global-state",
|
|
65
|
+
"state-sync",
|
|
66
|
+
"state-sharing",
|
|
67
|
+
|
|
40
68
|
"router-sync",
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
|
|
69
|
+
"route-sync",
|
|
70
|
+
"cross-app-routing",
|
|
71
|
+
|
|
72
|
+
"isolation",
|
|
73
|
+
"sandbox",
|
|
74
|
+
"js-sandbox",
|
|
75
|
+
|
|
76
|
+
"lazy-load",
|
|
77
|
+
"dynamic-import",
|
|
78
|
+
"remote-module",
|
|
79
|
+
|
|
80
|
+
"frontend-architecture",
|
|
81
|
+
"frontend-platform",
|
|
82
|
+
"frontend-infrastructure",
|
|
83
|
+
|
|
84
|
+
"monorepo",
|
|
85
|
+
"polyrepo",
|
|
86
|
+
|
|
87
|
+
"enterprise-frontend",
|
|
88
|
+
"scalable-frontend",
|
|
89
|
+
"large-scale-app"
|
|
44
90
|
],
|
|
45
91
|
"author": "Delpi.Kye",
|
|
46
92
|
"license": "MIT",
|