@micro-zoe/micro-app 1.0.0-alpha.2 → 1.0.0-alpha.5
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/lib/index.d.ts +8 -3
- package/lib/index.esm.js +490 -221
- package/lib/index.esm.js.map +1 -1
- package/lib/index.min.js +1 -1
- package/lib/index.min.js.map +1 -1
- package/lib/index.umd.js +1 -1
- package/lib/index.umd.js.map +1 -1
- package/package.json +3 -1
- package/typings/global.d.ts +49 -11
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '1.0.0-alpha.
|
|
1
|
+
const version = '1.0.0-alpha.5';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -72,6 +72,10 @@ function isShadowRoot(target) {
|
|
|
72
72
|
function isURL(target) {
|
|
73
73
|
return target instanceof URL;
|
|
74
74
|
}
|
|
75
|
+
// is ProxyDocument
|
|
76
|
+
function isProxyDocument(target) {
|
|
77
|
+
return toString.call(target) === '[object ProxyDocument]';
|
|
78
|
+
}
|
|
75
79
|
/**
|
|
76
80
|
* format error log
|
|
77
81
|
* @param msg message
|
|
@@ -498,6 +502,66 @@ function fetchSource(url, appName = null, options = {}) {
|
|
|
498
502
|
});
|
|
499
503
|
}
|
|
500
504
|
|
|
505
|
+
class HTMLLoader {
|
|
506
|
+
static getInstance() {
|
|
507
|
+
if (!this.instance) {
|
|
508
|
+
this.instance = new HTMLLoader();
|
|
509
|
+
}
|
|
510
|
+
return this.instance;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* run logic of load and format html
|
|
514
|
+
* @param successCb success callback
|
|
515
|
+
* @param errorCb error callback, type: (err: Error, meetFetchErr: boolean) => void
|
|
516
|
+
*/
|
|
517
|
+
run(app, successCb) {
|
|
518
|
+
const appName = app.name;
|
|
519
|
+
const htmlUrl = app.ssrUrl || app.url;
|
|
520
|
+
fetchSource(htmlUrl, appName, { cache: 'no-cache' }).then((htmlStr) => {
|
|
521
|
+
if (!htmlStr) {
|
|
522
|
+
const msg = 'html is empty, please check in detail';
|
|
523
|
+
app.onerror(new Error(msg));
|
|
524
|
+
return logError(msg, appName);
|
|
525
|
+
}
|
|
526
|
+
htmlStr = this.formatHTML(htmlUrl, htmlStr, appName);
|
|
527
|
+
successCb(htmlStr, app);
|
|
528
|
+
}).catch((e) => {
|
|
529
|
+
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, appName, e);
|
|
530
|
+
app.onLoadError(e);
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
formatHTML(htmlUrl, htmlStr, appName) {
|
|
534
|
+
return this.processHtml(htmlUrl, htmlStr, appName, microApp.plugins)
|
|
535
|
+
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
536
|
+
return match
|
|
537
|
+
.replace(/<head/i, '<micro-app-head')
|
|
538
|
+
.replace(/<\/head>/i, '</micro-app-head>');
|
|
539
|
+
})
|
|
540
|
+
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
541
|
+
return match
|
|
542
|
+
.replace(/<body/i, '<micro-app-body')
|
|
543
|
+
.replace(/<\/body>/i, '</micro-app-body>');
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
processHtml(url, code, appName, plugins) {
|
|
547
|
+
var _a;
|
|
548
|
+
if (!plugins)
|
|
549
|
+
return code;
|
|
550
|
+
const mergedPlugins = [];
|
|
551
|
+
plugins.global && mergedPlugins.push(...plugins.global);
|
|
552
|
+
((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]) && mergedPlugins.push(...plugins.modules[appName]);
|
|
553
|
+
if (mergedPlugins.length > 0) {
|
|
554
|
+
return mergedPlugins.reduce((preCode, plugin) => {
|
|
555
|
+
if (isPlainObject(plugin) && isFunction(plugin.processHtml)) {
|
|
556
|
+
return plugin.processHtml(preCode, url, plugin.options);
|
|
557
|
+
}
|
|
558
|
+
return preCode;
|
|
559
|
+
}, code);
|
|
560
|
+
}
|
|
561
|
+
return code;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
501
565
|
// common reg
|
|
502
566
|
const rootSelectorREG = /(^|\s+)(html|:root)(?=[\s>~[.#:]+|$)/;
|
|
503
567
|
const bodySelectorREG = /(^|\s+)((html[\s>~]+body)|body)(?=[\s>~[.#:]+|$)/;
|
|
@@ -1139,12 +1203,12 @@ function handleNewNode(parent, child, app) {
|
|
|
1139
1203
|
return child;
|
|
1140
1204
|
}
|
|
1141
1205
|
else if (child instanceof HTMLLinkElement) {
|
|
1142
|
-
if (child.hasAttribute('exclude')) {
|
|
1206
|
+
if (child.hasAttribute('exclude') || checkExcludeUrl(child.getAttribute('href'), app.name)) {
|
|
1143
1207
|
const linkReplaceComment = document.createComment('link element with exclude attribute ignored by micro-app');
|
|
1144
1208
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
1145
1209
|
return linkReplaceComment;
|
|
1146
1210
|
}
|
|
1147
|
-
else if (child.hasAttribute('ignore')) {
|
|
1211
|
+
else if (child.hasAttribute('ignore') || checkIgnoreUrl(child.getAttribute('href'), app.name)) {
|
|
1148
1212
|
return child;
|
|
1149
1213
|
}
|
|
1150
1214
|
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
@@ -1363,101 +1427,112 @@ function markElement(element) {
|
|
|
1363
1427
|
// methods of document
|
|
1364
1428
|
function patchDocument() {
|
|
1365
1429
|
const rawDocument = globalEnv.rawDocument;
|
|
1430
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1431
|
+
function getBindTarget(target) {
|
|
1432
|
+
return isProxyDocument(target) ? rawDocument : target;
|
|
1433
|
+
}
|
|
1366
1434
|
// create element 👇
|
|
1367
|
-
|
|
1368
|
-
const element = globalEnv.rawCreateElement.call(this, tagName, options);
|
|
1435
|
+
rawRootDocument.prototype.createElement = function createElement(tagName, options) {
|
|
1436
|
+
const element = globalEnv.rawCreateElement.call(getBindTarget(this), tagName, options);
|
|
1369
1437
|
return markElement(element);
|
|
1370
1438
|
};
|
|
1371
|
-
|
|
1372
|
-
const element = globalEnv.rawCreateElementNS.call(this, namespaceURI, name, options);
|
|
1439
|
+
rawRootDocument.prototype.createElementNS = function createElementNS(namespaceURI, name, options) {
|
|
1440
|
+
const element = globalEnv.rawCreateElementNS.call(getBindTarget(this), namespaceURI, name, options);
|
|
1373
1441
|
return markElement(element);
|
|
1374
1442
|
};
|
|
1375
|
-
|
|
1376
|
-
const element = globalEnv.rawCreateDocumentFragment.call(this);
|
|
1443
|
+
rawRootDocument.prototype.createDocumentFragment = function createDocumentFragment() {
|
|
1444
|
+
const element = globalEnv.rawCreateDocumentFragment.call(getBindTarget(this));
|
|
1377
1445
|
return markElement(element);
|
|
1378
1446
|
};
|
|
1379
1447
|
// query element👇
|
|
1380
1448
|
function querySelector(selectors) {
|
|
1381
1449
|
var _a, _b, _c, _d;
|
|
1450
|
+
const _this = getBindTarget(this);
|
|
1382
1451
|
const currentAppName = getCurrentAppName();
|
|
1383
1452
|
if (!currentAppName ||
|
|
1384
1453
|
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1385
1454
|
!selectors ||
|
|
1386
1455
|
isUniqueElement(selectors) ||
|
|
1387
1456
|
// see https://github.com/micro-zoe/micro-app/issues/56
|
|
1388
|
-
rawDocument !==
|
|
1389
|
-
return globalEnv.rawQuerySelector.call(
|
|
1457
|
+
rawDocument !== _this) {
|
|
1458
|
+
return globalEnv.rawQuerySelector.call(_this, selectors);
|
|
1390
1459
|
}
|
|
1391
1460
|
return (_d = (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelector(selectors)) !== null && _d !== void 0 ? _d : null;
|
|
1392
1461
|
}
|
|
1393
1462
|
function querySelectorAll(selectors) {
|
|
1394
1463
|
var _a, _b, _c, _d;
|
|
1464
|
+
const _this = getBindTarget(this);
|
|
1395
1465
|
const currentAppName = getCurrentAppName();
|
|
1396
1466
|
if (!currentAppName ||
|
|
1397
1467
|
!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.container) ||
|
|
1398
1468
|
!selectors ||
|
|
1399
1469
|
isUniqueElement(selectors) ||
|
|
1400
|
-
rawDocument !==
|
|
1401
|
-
return globalEnv.rawQuerySelectorAll.call(
|
|
1470
|
+
rawDocument !== _this) {
|
|
1471
|
+
return globalEnv.rawQuerySelectorAll.call(_this, selectors);
|
|
1402
1472
|
}
|
|
1403
1473
|
return (_d = (_c = (_b = appInstanceMap.get(currentAppName)) === null || _b === void 0 ? void 0 : _b.container) === null || _c === void 0 ? void 0 : _c.querySelectorAll(selectors)) !== null && _d !== void 0 ? _d : [];
|
|
1404
1474
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1475
|
+
rawRootDocument.prototype.querySelector = querySelector;
|
|
1476
|
+
rawRootDocument.prototype.querySelectorAll = querySelectorAll;
|
|
1477
|
+
rawRootDocument.prototype.getElementById = function getElementById(key) {
|
|
1478
|
+
const _this = getBindTarget(this);
|
|
1408
1479
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1409
|
-
return globalEnv.rawGetElementById.call(
|
|
1480
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1410
1481
|
}
|
|
1411
1482
|
try {
|
|
1412
|
-
return querySelector.call(
|
|
1483
|
+
return querySelector.call(_this, `#${key}`);
|
|
1413
1484
|
}
|
|
1414
1485
|
catch (_a) {
|
|
1415
|
-
return globalEnv.rawGetElementById.call(
|
|
1486
|
+
return globalEnv.rawGetElementById.call(_this, key);
|
|
1416
1487
|
}
|
|
1417
1488
|
};
|
|
1418
|
-
|
|
1489
|
+
rawRootDocument.prototype.getElementsByClassName = function getElementsByClassName(key) {
|
|
1490
|
+
const _this = getBindTarget(this);
|
|
1419
1491
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1420
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1492
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1421
1493
|
}
|
|
1422
1494
|
try {
|
|
1423
|
-
return querySelectorAll.call(
|
|
1495
|
+
return querySelectorAll.call(_this, `.${key}`);
|
|
1424
1496
|
}
|
|
1425
1497
|
catch (_a) {
|
|
1426
|
-
return globalEnv.rawGetElementsByClassName.call(
|
|
1498
|
+
return globalEnv.rawGetElementsByClassName.call(_this, key);
|
|
1427
1499
|
}
|
|
1428
1500
|
};
|
|
1429
|
-
|
|
1501
|
+
rawRootDocument.prototype.getElementsByTagName = function getElementsByTagName(key) {
|
|
1430
1502
|
var _a;
|
|
1503
|
+
const _this = getBindTarget(this);
|
|
1431
1504
|
const currentAppName = getCurrentAppName();
|
|
1432
1505
|
if (!currentAppName ||
|
|
1433
1506
|
isUniqueElement(key) ||
|
|
1434
1507
|
isInvalidQuerySelectorKey(key) ||
|
|
1435
1508
|
(!((_a = appInstanceMap.get(currentAppName)) === null || _a === void 0 ? void 0 : _a.inline) && /^script$/i.test(key))) {
|
|
1436
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1509
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1437
1510
|
}
|
|
1438
1511
|
try {
|
|
1439
|
-
return querySelectorAll.call(
|
|
1512
|
+
return querySelectorAll.call(_this, key);
|
|
1440
1513
|
}
|
|
1441
1514
|
catch (_b) {
|
|
1442
|
-
return globalEnv.rawGetElementsByTagName.call(
|
|
1515
|
+
return globalEnv.rawGetElementsByTagName.call(_this, key);
|
|
1443
1516
|
}
|
|
1444
1517
|
};
|
|
1445
|
-
|
|
1518
|
+
rawRootDocument.prototype.getElementsByName = function getElementsByName(key) {
|
|
1519
|
+
const _this = getBindTarget(this);
|
|
1446
1520
|
if (!getCurrentAppName() || isInvalidQuerySelectorKey(key)) {
|
|
1447
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1521
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1448
1522
|
}
|
|
1449
1523
|
try {
|
|
1450
|
-
return querySelectorAll.call(
|
|
1524
|
+
return querySelectorAll.call(_this, `[name=${key}]`);
|
|
1451
1525
|
}
|
|
1452
1526
|
catch (_a) {
|
|
1453
|
-
return globalEnv.rawGetElementsByName.call(
|
|
1527
|
+
return globalEnv.rawGetElementsByName.call(_this, key);
|
|
1454
1528
|
}
|
|
1455
1529
|
};
|
|
1456
1530
|
}
|
|
1457
1531
|
/**
|
|
1458
1532
|
* patchSetAttribute is different from other patch
|
|
1459
|
-
*
|
|
1460
|
-
* it
|
|
1533
|
+
* NOTE:
|
|
1534
|
+
* 1. it not dependent on sandbox
|
|
1535
|
+
* 2. it should exec when first micro-app-element created & release when all app unmounted
|
|
1461
1536
|
*/
|
|
1462
1537
|
let hasRewriteSetAttribute = false;
|
|
1463
1538
|
function patchSetAttribute() {
|
|
@@ -1492,24 +1567,21 @@ function patchSetAttribute() {
|
|
|
1492
1567
|
}
|
|
1493
1568
|
};
|
|
1494
1569
|
}
|
|
1495
|
-
function releasePatchSetAttribute() {
|
|
1496
|
-
hasRewriteSetAttribute = false;
|
|
1497
|
-
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1498
|
-
}
|
|
1499
1570
|
function releasePatchDocument() {
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1571
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
1572
|
+
rawRootDocument.prototype.createElement = globalEnv.rawCreateElement;
|
|
1573
|
+
rawRootDocument.prototype.createElementNS = globalEnv.rawCreateElementNS;
|
|
1574
|
+
rawRootDocument.prototype.createDocumentFragment = globalEnv.rawCreateDocumentFragment;
|
|
1575
|
+
rawRootDocument.prototype.querySelector = globalEnv.rawQuerySelector;
|
|
1576
|
+
rawRootDocument.prototype.querySelectorAll = globalEnv.rawQuerySelectorAll;
|
|
1577
|
+
rawRootDocument.prototype.getElementById = globalEnv.rawGetElementById;
|
|
1578
|
+
rawRootDocument.prototype.getElementsByClassName = globalEnv.rawGetElementsByClassName;
|
|
1579
|
+
rawRootDocument.prototype.getElementsByTagName = globalEnv.rawGetElementsByTagName;
|
|
1580
|
+
rawRootDocument.prototype.getElementsByName = globalEnv.rawGetElementsByName;
|
|
1509
1581
|
}
|
|
1510
1582
|
// release patch
|
|
1511
1583
|
function releasePatches() {
|
|
1512
|
-
|
|
1584
|
+
removeDomScope();
|
|
1513
1585
|
releasePatchDocument();
|
|
1514
1586
|
Element.prototype.appendChild = globalEnv.rawAppendChild;
|
|
1515
1587
|
Element.prototype.insertBefore = globalEnv.rawInsertBefore;
|
|
@@ -1519,6 +1591,11 @@ function releasePatches() {
|
|
|
1519
1591
|
Element.prototype.prepend = globalEnv.rawPrepend;
|
|
1520
1592
|
Element.prototype.cloneNode = globalEnv.rawCloneNode;
|
|
1521
1593
|
}
|
|
1594
|
+
// exec when last child unmount
|
|
1595
|
+
function releasePatchSetAttribute() {
|
|
1596
|
+
hasRewriteSetAttribute = false;
|
|
1597
|
+
Element.prototype.setAttribute = globalEnv.rawSetAttribute;
|
|
1598
|
+
}
|
|
1522
1599
|
// Set the style of micro-app-head and micro-app-body
|
|
1523
1600
|
let hasRejectMicroAppStyle = false;
|
|
1524
1601
|
function rejectMicroAppStyle() {
|
|
@@ -1538,6 +1615,10 @@ const globalEnv = {};
|
|
|
1538
1615
|
*/
|
|
1539
1616
|
function initGlobalEnv() {
|
|
1540
1617
|
if (isBrowser) {
|
|
1618
|
+
const rawWindow = Function('return window')();
|
|
1619
|
+
const rawDocument = Function('return document')();
|
|
1620
|
+
const rawRootDocument = Function('return Document')();
|
|
1621
|
+
const supportModuleScript = isSupportModuleScript();
|
|
1541
1622
|
/**
|
|
1542
1623
|
* save patch raw methods
|
|
1543
1624
|
* pay attention to this binding
|
|
@@ -1550,15 +1631,15 @@ function initGlobalEnv() {
|
|
|
1550
1631
|
const rawAppend = Element.prototype.append;
|
|
1551
1632
|
const rawPrepend = Element.prototype.prepend;
|
|
1552
1633
|
const rawCloneNode = Element.prototype.cloneNode;
|
|
1553
|
-
const rawCreateElement =
|
|
1554
|
-
const rawCreateElementNS =
|
|
1555
|
-
const rawCreateDocumentFragment =
|
|
1556
|
-
const rawQuerySelector =
|
|
1557
|
-
const rawQuerySelectorAll =
|
|
1558
|
-
const rawGetElementById =
|
|
1559
|
-
const rawGetElementsByClassName =
|
|
1560
|
-
const rawGetElementsByTagName =
|
|
1561
|
-
const rawGetElementsByName =
|
|
1634
|
+
const rawCreateElement = rawRootDocument.prototype.createElement;
|
|
1635
|
+
const rawCreateElementNS = rawRootDocument.prototype.createElementNS;
|
|
1636
|
+
const rawCreateDocumentFragment = rawRootDocument.prototype.createDocumentFragment;
|
|
1637
|
+
const rawQuerySelector = rawRootDocument.prototype.querySelector;
|
|
1638
|
+
const rawQuerySelectorAll = rawRootDocument.prototype.querySelectorAll;
|
|
1639
|
+
const rawGetElementById = rawRootDocument.prototype.getElementById;
|
|
1640
|
+
const rawGetElementsByClassName = rawRootDocument.prototype.getElementsByClassName;
|
|
1641
|
+
const rawGetElementsByTagName = rawRootDocument.prototype.getElementsByTagName;
|
|
1642
|
+
const rawGetElementsByName = rawRootDocument.prototype.getElementsByName;
|
|
1562
1643
|
const ImageProxy = new Proxy(Image, {
|
|
1563
1644
|
construct(Target, args) {
|
|
1564
1645
|
const elementImage = new Target(...args);
|
|
@@ -1566,9 +1647,6 @@ function initGlobalEnv() {
|
|
|
1566
1647
|
return elementImage;
|
|
1567
1648
|
},
|
|
1568
1649
|
});
|
|
1569
|
-
const rawWindow = Function('return window')();
|
|
1570
|
-
const rawDocument = Function('return document')();
|
|
1571
|
-
const supportModuleScript = isSupportModuleScript();
|
|
1572
1650
|
/**
|
|
1573
1651
|
* save effect raw methods
|
|
1574
1652
|
* pay attention to this binding, especially setInterval, setTimeout, clearInterval, clearTimeout
|
|
@@ -1579,11 +1657,18 @@ function initGlobalEnv() {
|
|
|
1579
1657
|
const rawSetTimeout = rawWindow.setTimeout;
|
|
1580
1658
|
const rawClearInterval = rawWindow.clearInterval;
|
|
1581
1659
|
const rawClearTimeout = rawWindow.clearTimeout;
|
|
1660
|
+
const rawPushState = rawWindow.history.pushState;
|
|
1661
|
+
const rawReplaceState = rawWindow.history.replaceState;
|
|
1582
1662
|
const rawDocumentAddEventListener = rawDocument.addEventListener;
|
|
1583
1663
|
const rawDocumentRemoveEventListener = rawDocument.removeEventListener;
|
|
1584
1664
|
// mark current application as base application
|
|
1585
1665
|
window.__MICRO_APP_BASE_APPLICATION__ = true;
|
|
1586
1666
|
assign(globalEnv, {
|
|
1667
|
+
// common global vars
|
|
1668
|
+
rawWindow,
|
|
1669
|
+
rawDocument,
|
|
1670
|
+
rawRootDocument,
|
|
1671
|
+
supportModuleScript,
|
|
1587
1672
|
// source/patch
|
|
1588
1673
|
rawSetAttribute,
|
|
1589
1674
|
rawAppendChild,
|
|
@@ -1603,10 +1688,6 @@ function initGlobalEnv() {
|
|
|
1603
1688
|
rawGetElementsByTagName,
|
|
1604
1689
|
rawGetElementsByName,
|
|
1605
1690
|
ImageProxy,
|
|
1606
|
-
// common global vars
|
|
1607
|
-
rawWindow,
|
|
1608
|
-
rawDocument,
|
|
1609
|
-
supportModuleScript,
|
|
1610
1691
|
// sandbox/effect
|
|
1611
1692
|
rawWindowAddEventListener,
|
|
1612
1693
|
rawWindowRemoveEventListener,
|
|
@@ -1616,6 +1697,8 @@ function initGlobalEnv() {
|
|
|
1616
1697
|
rawClearTimeout,
|
|
1617
1698
|
rawDocumentAddEventListener,
|
|
1618
1699
|
rawDocumentRemoveEventListener,
|
|
1700
|
+
rawPushState,
|
|
1701
|
+
rawReplaceState,
|
|
1619
1702
|
});
|
|
1620
1703
|
// global effect
|
|
1621
1704
|
rejectMicroAppStyle();
|
|
@@ -1634,11 +1717,14 @@ const globalScripts = new Map();
|
|
|
1634
1717
|
function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
1635
1718
|
let replaceComment = null;
|
|
1636
1719
|
let src = script.getAttribute('src');
|
|
1637
|
-
if (
|
|
1720
|
+
if (src) {
|
|
1721
|
+
src = CompletionPath(src, app.url);
|
|
1722
|
+
}
|
|
1723
|
+
if (script.hasAttribute('exclude') || checkExcludeUrl(src, app.name)) {
|
|
1638
1724
|
replaceComment = document.createComment('script element with exclude attribute removed by micro-app');
|
|
1639
1725
|
}
|
|
1640
|
-
else if ((script.type && !['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module'].includes(script.type)) ||
|
|
1641
|
-
script.hasAttribute('ignore')) {
|
|
1726
|
+
else if ((script.type && !['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module', 'systemjs-module', 'systemjs-importmap'].includes(script.type)) ||
|
|
1727
|
+
script.hasAttribute('ignore') || checkIgnoreUrl(src, app.name)) {
|
|
1642
1728
|
return null;
|
|
1643
1729
|
}
|
|
1644
1730
|
else if ((globalEnv.supportModuleScript && script.noModule) ||
|
|
@@ -1646,7 +1732,6 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1646
1732
|
replaceComment = document.createComment(`${script.noModule ? 'noModule' : 'module'} script ignored by micro-app`);
|
|
1647
1733
|
}
|
|
1648
1734
|
else if (src) { // remote script
|
|
1649
|
-
src = CompletionPath(src, app.url);
|
|
1650
1735
|
const info = {
|
|
1651
1736
|
code: '',
|
|
1652
1737
|
isExternal: true,
|
|
@@ -1696,6 +1781,46 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1696
1781
|
return parent.replaceChild(replaceComment, script);
|
|
1697
1782
|
}
|
|
1698
1783
|
}
|
|
1784
|
+
/**
|
|
1785
|
+
* get assets plugins
|
|
1786
|
+
* @param appName app name
|
|
1787
|
+
*/
|
|
1788
|
+
function getAssetsPlugins(appName) {
|
|
1789
|
+
var _a, _b, _c;
|
|
1790
|
+
const globalPlugins = ((_a = microApp.plugins) === null || _a === void 0 ? void 0 : _a.global) || [];
|
|
1791
|
+
const modulePlugins = ((_c = (_b = microApp.plugins) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[appName]) || [];
|
|
1792
|
+
return [...globalPlugins, ...modulePlugins];
|
|
1793
|
+
}
|
|
1794
|
+
/**
|
|
1795
|
+
* whether the url needs to be excluded
|
|
1796
|
+
* @param url css or js link
|
|
1797
|
+
* @param plugins microApp plugins
|
|
1798
|
+
*/
|
|
1799
|
+
function checkExcludeUrl(url, appName) {
|
|
1800
|
+
if (!url)
|
|
1801
|
+
return false;
|
|
1802
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1803
|
+
return plugins.some(plugin => {
|
|
1804
|
+
if (!plugin.excludeChecker)
|
|
1805
|
+
return false;
|
|
1806
|
+
return plugin.excludeChecker(url);
|
|
1807
|
+
});
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* whether the url needs to be ignore
|
|
1811
|
+
* @param url css or js link
|
|
1812
|
+
* @param plugins microApp plugins
|
|
1813
|
+
*/
|
|
1814
|
+
function checkIgnoreUrl(url, appName) {
|
|
1815
|
+
if (!url)
|
|
1816
|
+
return false;
|
|
1817
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1818
|
+
return plugins.some(plugin => {
|
|
1819
|
+
if (!plugin.ignoreChecker)
|
|
1820
|
+
return false;
|
|
1821
|
+
return plugin.ignoreChecker(url);
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1699
1824
|
/**
|
|
1700
1825
|
* Get remote resources of script
|
|
1701
1826
|
* @param wrapElement htmlDom
|
|
@@ -1836,6 +1961,13 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1836
1961
|
if (app.source.scripts.has(url)) {
|
|
1837
1962
|
const existInfo = app.source.scripts.get(url);
|
|
1838
1963
|
!existInfo.module && defer(dispatchScriptOnLoadEvent);
|
|
1964
|
+
/**
|
|
1965
|
+
* TODO: 这里要改,当script初始化时动态创建远程script时,初次渲染和二次渲染的顺序不一致,会导致错误
|
|
1966
|
+
* 1、url不存在缓存,初始化的时候肯定是要异步请求,那么执行顺序就会靠后,至少落后于html自带的script
|
|
1967
|
+
* 2、url存在缓存,那么二次渲染的时候这里会同步执行,就会先于html自带的script执行
|
|
1968
|
+
* 3、测试一下,初次渲染和二次渲染时,onload的执行时机,是在js执行完成,还是执行之前
|
|
1969
|
+
* 4、将上述问题做成注释,方便后续阅读和理解
|
|
1970
|
+
*/
|
|
1839
1971
|
return runScript(url, app, existInfo, true, dispatchScriptOnLoadEvent);
|
|
1840
1972
|
}
|
|
1841
1973
|
if (globalScripts.has(url)) {
|
|
@@ -1868,7 +2000,7 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1868
2000
|
catch (e) {
|
|
1869
2001
|
console.error(`[micro-app from runDynamicScript] app ${app.name}: `, e, url);
|
|
1870
2002
|
}
|
|
1871
|
-
!info.module &&
|
|
2003
|
+
!info.module && dispatchScriptOnLoadEvent();
|
|
1872
2004
|
}).catch((err) => {
|
|
1873
2005
|
logError(err, app.name);
|
|
1874
2006
|
dispatchOnErrorEvent(originScript);
|
|
@@ -1916,6 +2048,7 @@ function runCode2Function(code, info) {
|
|
|
1916
2048
|
* @param info source script info
|
|
1917
2049
|
*/
|
|
1918
2050
|
function bindScope(url, app, code, info) {
|
|
2051
|
+
// TODO: 增加缓存机制
|
|
1919
2052
|
if (isPlainObject(microApp.plugins)) {
|
|
1920
2053
|
code = usePlugins(url, code, app.name, microApp.plugins, info);
|
|
1921
2054
|
}
|
|
@@ -1972,10 +2105,10 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1972
2105
|
});
|
|
1973
2106
|
for (const dom of children) {
|
|
1974
2107
|
if (dom instanceof HTMLLinkElement) {
|
|
1975
|
-
if (dom.hasAttribute('exclude')) {
|
|
2108
|
+
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
|
|
1976
2109
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
1977
2110
|
}
|
|
1978
|
-
else if (!dom.hasAttribute('ignore')) {
|
|
2111
|
+
else if (!(dom.hasAttribute('ignore') || checkIgnoreUrl(dom.getAttribute('href'), app.name))) {
|
|
1979
2112
|
extractLinkFromHtml(dom, parent, app);
|
|
1980
2113
|
}
|
|
1981
2114
|
else if (dom.hasAttribute('href')) {
|
|
@@ -2029,34 +2162,6 @@ function extractSourceDom(htmlStr, app) {
|
|
|
2029
2162
|
app.onLoad(wrapElement);
|
|
2030
2163
|
}
|
|
2031
2164
|
}
|
|
2032
|
-
/**
|
|
2033
|
-
* Get and format html
|
|
2034
|
-
* @param app app
|
|
2035
|
-
*/
|
|
2036
|
-
function extractHtml(app) {
|
|
2037
|
-
fetchSource(app.ssrUrl || app.url, app.name, { cache: 'no-cache' }).then((htmlStr) => {
|
|
2038
|
-
if (!htmlStr) {
|
|
2039
|
-
const msg = 'html is empty, please check in detail';
|
|
2040
|
-
app.onerror(new Error(msg));
|
|
2041
|
-
return logError(msg, app.name);
|
|
2042
|
-
}
|
|
2043
|
-
htmlStr = htmlStr
|
|
2044
|
-
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
2045
|
-
return match
|
|
2046
|
-
.replace(/<head/i, '<micro-app-head')
|
|
2047
|
-
.replace(/<\/head>/i, '</micro-app-head>');
|
|
2048
|
-
})
|
|
2049
|
-
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
2050
|
-
return match
|
|
2051
|
-
.replace(/<body/i, '<micro-app-body')
|
|
2052
|
-
.replace(/<\/body>/i, '</micro-app-body>');
|
|
2053
|
-
});
|
|
2054
|
-
extractSourceDom(htmlStr, app);
|
|
2055
|
-
}).catch((e) => {
|
|
2056
|
-
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, app.name, e);
|
|
2057
|
-
app.onLoadError(e);
|
|
2058
|
-
});
|
|
2059
|
-
}
|
|
2060
2165
|
|
|
2061
2166
|
class EventCenter {
|
|
2062
2167
|
constructor() {
|
|
@@ -2339,12 +2444,39 @@ function rebuildDataCenterSnapshot(microAppEventCenter) {
|
|
|
2339
2444
|
}
|
|
2340
2445
|
}
|
|
2341
2446
|
|
|
2447
|
+
// 管理 app 的单例
|
|
2448
|
+
class AppManager {
|
|
2449
|
+
constructor() {
|
|
2450
|
+
// Todo: appInstanceMap 由 AppManager 来创建,不再由 create_app 管理
|
|
2451
|
+
this.appInstanceMap = appInstanceMap;
|
|
2452
|
+
}
|
|
2453
|
+
static getInstance() {
|
|
2454
|
+
if (!this.instance) {
|
|
2455
|
+
this.instance = new AppManager();
|
|
2456
|
+
}
|
|
2457
|
+
return this.instance;
|
|
2458
|
+
}
|
|
2459
|
+
get(appName) {
|
|
2460
|
+
return this.appInstanceMap.get(appName);
|
|
2461
|
+
}
|
|
2462
|
+
set(appName, app) {
|
|
2463
|
+
this.appInstanceMap.set(appName, app);
|
|
2464
|
+
}
|
|
2465
|
+
getAll() {
|
|
2466
|
+
return Array.from(this.appInstanceMap.values());
|
|
2467
|
+
}
|
|
2468
|
+
clear() {
|
|
2469
|
+
this.appInstanceMap.clear();
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2342
2473
|
function unmountNestedApp() {
|
|
2343
|
-
|
|
2474
|
+
releaseUnmountOfNestedApp();
|
|
2475
|
+
AppManager.getInstance().getAll().forEach(app => {
|
|
2344
2476
|
// @ts-ignore
|
|
2345
2477
|
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
2346
2478
|
});
|
|
2347
|
-
!window.__MICRO_APP_UMD_MODE__ &&
|
|
2479
|
+
!window.__MICRO_APP_UMD_MODE__ && AppManager.getInstance().clear();
|
|
2348
2480
|
}
|
|
2349
2481
|
// release listener
|
|
2350
2482
|
function releaseUnmountOfNestedApp() {
|
|
@@ -2556,6 +2688,13 @@ function effect(appName, microAppWindow) {
|
|
|
2556
2688
|
let umdIntervalIdMap = new Map();
|
|
2557
2689
|
let umdTimeoutIdMap = new Map();
|
|
2558
2690
|
let umdOnClickHandler;
|
|
2691
|
+
const clearUmdSnapshotData = () => {
|
|
2692
|
+
umdWindowListenerMap.clear();
|
|
2693
|
+
umdIntervalIdMap.clear();
|
|
2694
|
+
umdTimeoutIdMap.clear();
|
|
2695
|
+
umdDocumentListenerMap.clear();
|
|
2696
|
+
umdOnClickHandler = null;
|
|
2697
|
+
};
|
|
2559
2698
|
// record event and timer before exec umdMountHook
|
|
2560
2699
|
const recordUmdEffect = () => {
|
|
2561
2700
|
// record window event
|
|
@@ -2601,13 +2740,12 @@ function effect(appName, microAppWindow) {
|
|
|
2601
2740
|
// rebuild onclick event
|
|
2602
2741
|
umdOnClickHandler && documentClickListMap.set(appName, umdOnClickHandler);
|
|
2603
2742
|
// rebuild document event
|
|
2604
|
-
setCurrentAppName(appName);
|
|
2605
2743
|
umdDocumentListenerMap.forEach((listenerList, type) => {
|
|
2606
2744
|
for (const listener of listenerList) {
|
|
2607
2745
|
document.addEventListener(type, listener, listener === null || listener === void 0 ? void 0 : listener.__MICRO_APP_MARK_OPTIONS__);
|
|
2608
2746
|
}
|
|
2609
2747
|
});
|
|
2610
|
-
|
|
2748
|
+
clearUmdSnapshotData();
|
|
2611
2749
|
};
|
|
2612
2750
|
// release all event listener & interval & timeout when unmount app
|
|
2613
2751
|
const releaseEffect = () => {
|
|
@@ -2654,7 +2792,8 @@ function effect(appName, microAppWindow) {
|
|
|
2654
2792
|
}
|
|
2655
2793
|
|
|
2656
2794
|
// set micro app state to origin state
|
|
2657
|
-
function setMicroState(appName,
|
|
2795
|
+
function setMicroState(appName, microState) {
|
|
2796
|
+
const rawState = globalEnv.rawWindow.history.state;
|
|
2658
2797
|
const additionalState = {
|
|
2659
2798
|
microAppState: assign({}, rawState === null || rawState === void 0 ? void 0 : rawState.microAppState, {
|
|
2660
2799
|
[appName]: microState
|
|
@@ -2677,9 +2816,9 @@ function removeMicroState(appName, rawState) {
|
|
|
2677
2816
|
return assign({}, rawState);
|
|
2678
2817
|
}
|
|
2679
2818
|
// get micro app state form origin state
|
|
2680
|
-
function getMicroState(appName
|
|
2681
|
-
var _a;
|
|
2682
|
-
return ((_a = state === null ||
|
|
2819
|
+
function getMicroState(appName) {
|
|
2820
|
+
var _a, _b;
|
|
2821
|
+
return ((_b = (_a = globalEnv.rawWindow.history.state) === null || _a === void 0 ? void 0 : _a.microAppState) === null || _b === void 0 ? void 0 : _b[appName]) || null;
|
|
2683
2822
|
}
|
|
2684
2823
|
const ENC_AD_RE = /&/g; // %M1
|
|
2685
2824
|
const ENC_EQ_RE = /=/g; // %M2
|
|
@@ -2704,7 +2843,8 @@ function commonDecode(path) {
|
|
|
2704
2843
|
}
|
|
2705
2844
|
// 格式化query参数key,防止与原有参数的冲突
|
|
2706
2845
|
function formatQueryAppName(appName) {
|
|
2707
|
-
return `app-${appName}
|
|
2846
|
+
// return `app-${appName}`
|
|
2847
|
+
return appName;
|
|
2708
2848
|
}
|
|
2709
2849
|
// 根据浏览器url参数,获取当前子应用的path
|
|
2710
2850
|
function getMicroPathFromURL(appName) {
|
|
@@ -2827,7 +2967,7 @@ function addHistoryListener(appName) {
|
|
|
2827
2967
|
isHashChange = proxyWindow.location.hash !== oldHash;
|
|
2828
2968
|
}
|
|
2829
2969
|
// dispatch formatted popStateEvent to child
|
|
2830
|
-
dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2970
|
+
dispatchPopStateEventToMicroApp(appName, proxyWindow);
|
|
2831
2971
|
// dispatch formatted hashChangeEvent to child when hash change
|
|
2832
2972
|
if (isHashChange)
|
|
2833
2973
|
dispatchHashChangeEventToMicroApp(appName, proxyWindow, oldHref);
|
|
@@ -2846,9 +2986,9 @@ function addHistoryListener(appName) {
|
|
|
2846
2986
|
* @param proxyWindow sandbox window
|
|
2847
2987
|
* @param eventState history.state
|
|
2848
2988
|
*/
|
|
2849
|
-
function dispatchPopStateEventToMicroApp(appName, proxyWindow
|
|
2989
|
+
function dispatchPopStateEventToMicroApp(appName, proxyWindow) {
|
|
2850
2990
|
// create PopStateEvent named popstate-appName with sub app state
|
|
2851
|
-
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName
|
|
2991
|
+
const newPopStateEvent = new PopStateEvent(formatEventName$1('popstate', appName), { state: getMicroState(appName) });
|
|
2852
2992
|
globalEnv.rawWindow.dispatchEvent(newPopStateEvent);
|
|
2853
2993
|
// call function window.onpopstate if it exists
|
|
2854
2994
|
typeof proxyWindow.onpopstate === 'function' && proxyWindow.onpopstate(newPopStateEvent);
|
|
@@ -2916,19 +3056,15 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2916
3056
|
if (isString(rests[2]) || isURL(rests[2])) {
|
|
2917
3057
|
const targetLocation = createURL(rests[2], microLocation.href);
|
|
2918
3058
|
if (targetLocation.origin === microLocation.origin) {
|
|
2919
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName,
|
|
3059
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), true, setMicroState(appName, rests[0]), rests[1]);
|
|
2920
3060
|
const targetFullPath = targetLocation.pathname + targetLocation.search + targetLocation.hash;
|
|
2921
3061
|
if (targetFullPath !== microLocation.fullPath) {
|
|
2922
3062
|
updateMicroLocation(appName, targetFullPath, microLocation);
|
|
2923
3063
|
}
|
|
3064
|
+
return void 0;
|
|
2924
3065
|
}
|
|
2925
|
-
else {
|
|
2926
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2927
|
-
}
|
|
2928
|
-
}
|
|
2929
|
-
else {
|
|
2930
|
-
rawHistory[methodName].apply(rawHistory, rests);
|
|
2931
3066
|
}
|
|
3067
|
+
nativeHistoryNavigate(methodName, rests[2], rests[0], rests[1]);
|
|
2932
3068
|
};
|
|
2933
3069
|
}
|
|
2934
3070
|
const pushState = getMicroHistoryMethod('pushState');
|
|
@@ -2936,7 +3072,7 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2936
3072
|
return new Proxy(rawHistory, {
|
|
2937
3073
|
get(target, key) {
|
|
2938
3074
|
if (key === 'state') {
|
|
2939
|
-
return getMicroState(appName
|
|
3075
|
+
return getMicroState(appName);
|
|
2940
3076
|
}
|
|
2941
3077
|
else if (key === 'pushState') {
|
|
2942
3078
|
return pushState;
|
|
@@ -2946,6 +3082,15 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2946
3082
|
}
|
|
2947
3083
|
const rawValue = Reflect.get(target, key);
|
|
2948
3084
|
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'HISTORY') : rawValue;
|
|
3085
|
+
},
|
|
3086
|
+
set(target, key, value) {
|
|
3087
|
+
Reflect.set(target, key, value);
|
|
3088
|
+
/**
|
|
3089
|
+
* If the set() method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
|
|
3090
|
+
* e.g. history.state = {}
|
|
3091
|
+
* TypeError: 'set' on proxy: trap returned falsish for property 'state'
|
|
3092
|
+
*/
|
|
3093
|
+
return true;
|
|
2949
3094
|
}
|
|
2950
3095
|
});
|
|
2951
3096
|
}
|
|
@@ -2957,7 +3102,8 @@ function createMicroHistory(appName, microLocation) {
|
|
|
2957
3102
|
* @param title history.title, default is ''
|
|
2958
3103
|
*/
|
|
2959
3104
|
function nativeHistoryNavigate(methodName, fullPath, state = null, title = '') {
|
|
2960
|
-
globalEnv.
|
|
3105
|
+
const method = methodName === 'pushState' ? globalEnv.rawPushState : globalEnv.rawReplaceState;
|
|
3106
|
+
method.call(globalEnv.rawWindow.history, state, title, fullPath);
|
|
2961
3107
|
}
|
|
2962
3108
|
/**
|
|
2963
3109
|
* Navigate to new path, and dispatch native popStateEvent/hashChangeEvent to browser
|
|
@@ -2992,10 +3138,10 @@ function attachRouteToBrowserURL(result, state) {
|
|
|
2992
3138
|
}
|
|
2993
3139
|
/**
|
|
2994
3140
|
* When path is same, keep the microAppState in history.state
|
|
2995
|
-
* Fix bug of missing microAppState
|
|
3141
|
+
* Fix bug of missing microAppState when base app is next.js or angular
|
|
2996
3142
|
* @param method history.pushState/replaceState
|
|
2997
3143
|
*/
|
|
2998
|
-
function
|
|
3144
|
+
function reWriteHistoryMethod(method) {
|
|
2999
3145
|
const rawWindow = globalEnv.rawWindow;
|
|
3000
3146
|
return function (...rests) {
|
|
3001
3147
|
var _a;
|
|
@@ -3011,22 +3157,38 @@ function patchHistoryState(method) {
|
|
|
3011
3157
|
}
|
|
3012
3158
|
}
|
|
3013
3159
|
method.apply(rawWindow.history, rests);
|
|
3160
|
+
/**
|
|
3161
|
+
* Attach child router info to browser url when base app navigate with pushState/replaceState
|
|
3162
|
+
* NOTE:
|
|
3163
|
+
* 1. Exec after apply pushState/replaceState
|
|
3164
|
+
* 2. Unable to catch when base app navigate with location
|
|
3165
|
+
* 3. When in nest app, rawPushState/rawReplaceState has been modified by parent
|
|
3166
|
+
* 4.
|
|
3167
|
+
*/
|
|
3168
|
+
getActiveApps(true).forEach(appName => {
|
|
3169
|
+
const app = appInstanceMap.get(appName);
|
|
3170
|
+
if (app.sandBox && app.useMemoryRouter && !getMicroPathFromURL(appName)) {
|
|
3171
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3172
|
+
}
|
|
3173
|
+
});
|
|
3174
|
+
// fix bug for nest app
|
|
3175
|
+
removeDomScope();
|
|
3014
3176
|
};
|
|
3015
3177
|
}
|
|
3016
|
-
let isReWriteHistoryState = false;
|
|
3017
3178
|
/**
|
|
3018
3179
|
* rewrite history.pushState/replaceState
|
|
3019
3180
|
* used to fix the problem that the microAppState maybe missing when mainApp navigate to same path
|
|
3020
3181
|
* e.g: when nextjs, angular receive popstate event, they will use history.replaceState to update browser url with a new state object
|
|
3021
3182
|
*/
|
|
3022
|
-
function
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3183
|
+
function patchHistory() {
|
|
3184
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3185
|
+
rawWindow.history.pushState = reWriteHistoryMethod(globalEnv.rawPushState);
|
|
3186
|
+
rawWindow.history.replaceState = reWriteHistoryMethod(globalEnv.rawReplaceState);
|
|
3187
|
+
}
|
|
3188
|
+
function releasePatchHistory() {
|
|
3189
|
+
const rawWindow = globalEnv.rawWindow;
|
|
3190
|
+
rawWindow.history.pushState = globalEnv.rawPushState;
|
|
3191
|
+
rawWindow.history.replaceState = globalEnv.rawReplaceState;
|
|
3030
3192
|
}
|
|
3031
3193
|
|
|
3032
3194
|
function createRouterApi() {
|
|
@@ -3038,7 +3200,7 @@ function createRouterApi() {
|
|
|
3038
3200
|
* @param state to.state
|
|
3039
3201
|
*/
|
|
3040
3202
|
function navigateWithRawHistory(appName, methodName, targetLocation, state) {
|
|
3041
|
-
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName,
|
|
3203
|
+
navigateWithNativeEvent(methodName, setMicroPathToURL(appName, targetLocation), false, setMicroState(appName, state !== null && state !== void 0 ? state : null));
|
|
3042
3204
|
// clear element scope after navigate
|
|
3043
3205
|
removeDomScope();
|
|
3044
3206
|
}
|
|
@@ -3100,7 +3262,7 @@ function createRouterApi() {
|
|
|
3100
3262
|
* NOTE:
|
|
3101
3263
|
* 1. Modify browser url first, and then run guards,
|
|
3102
3264
|
* consistent with the browser forward & back button
|
|
3103
|
-
* 2.
|
|
3265
|
+
* 2. Prevent the element binding
|
|
3104
3266
|
* @param appName app name
|
|
3105
3267
|
* @param to target location
|
|
3106
3268
|
* @param from old location
|
|
@@ -3142,7 +3304,7 @@ function createRouterApi() {
|
|
|
3142
3304
|
function commonHandlerForAttachToURL(appName) {
|
|
3143
3305
|
const app = appInstanceMap.get(appName);
|
|
3144
3306
|
if (app.sandBox && app.useMemoryRouter) {
|
|
3145
|
-
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName,
|
|
3307
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, app.sandBox.proxyWindow.location), setMicroState(appName, getMicroState(appName)));
|
|
3146
3308
|
}
|
|
3147
3309
|
}
|
|
3148
3310
|
/**
|
|
@@ -3157,21 +3319,24 @@ function createRouterApi() {
|
|
|
3157
3319
|
}
|
|
3158
3320
|
/**
|
|
3159
3321
|
* Attach all active app router info to browser url
|
|
3322
|
+
* exclude hidden keep-alive app
|
|
3160
3323
|
*/
|
|
3161
|
-
function attachAllToURL() {
|
|
3162
|
-
getActiveApps().forEach(appName => commonHandlerForAttachToURL(appName));
|
|
3324
|
+
function attachAllToURL(includeHiddenApp = false) {
|
|
3325
|
+
getActiveApps(!includeHiddenApp).forEach(appName => commonHandlerForAttachToURL(appName));
|
|
3163
3326
|
}
|
|
3164
3327
|
function createDefaultPageApi() {
|
|
3165
3328
|
// defaultPage data
|
|
3166
3329
|
const defaultPageRecord = useMapRecord();
|
|
3167
3330
|
/**
|
|
3168
3331
|
* defaultPage only effect when mount, and has lower priority than query on browser url
|
|
3169
|
-
*
|
|
3170
|
-
*
|
|
3332
|
+
* SetDefaultPageOptions {
|
|
3333
|
+
* @param name app name
|
|
3334
|
+
* @param path page path
|
|
3335
|
+
* }
|
|
3171
3336
|
*/
|
|
3172
|
-
function setDefaultPage(
|
|
3173
|
-
appName = formatAppName(
|
|
3174
|
-
if (!appName || !path) {
|
|
3337
|
+
function setDefaultPage(options) {
|
|
3338
|
+
const appName = formatAppName(options.name);
|
|
3339
|
+
if (!appName || !options.path) {
|
|
3175
3340
|
if (process.env.NODE_ENV !== 'production') {
|
|
3176
3341
|
if (!appName) {
|
|
3177
3342
|
logWarn(`setDefaultPage: invalid appName "${appName}"`);
|
|
@@ -3182,7 +3347,7 @@ function createRouterApi() {
|
|
|
3182
3347
|
}
|
|
3183
3348
|
return noopFalse;
|
|
3184
3349
|
}
|
|
3185
|
-
return defaultPageRecord.add(appName, path);
|
|
3350
|
+
return defaultPageRecord.add(appName, options.path);
|
|
3186
3351
|
}
|
|
3187
3352
|
function removeDefaultPage(appName) {
|
|
3188
3353
|
appName = formatAppName(appName);
|
|
@@ -3208,6 +3373,10 @@ function createRouterApi() {
|
|
|
3208
3373
|
removeDomScope();
|
|
3209
3374
|
const rawValue = Reflect.get(target, key);
|
|
3210
3375
|
return isFunction(rawValue) ? bindFunctionToRawObject(target, rawValue, 'BASEROUTER') : rawValue;
|
|
3376
|
+
},
|
|
3377
|
+
set(target, key, value) {
|
|
3378
|
+
Reflect.set(target, key, value);
|
|
3379
|
+
return true;
|
|
3211
3380
|
}
|
|
3212
3381
|
});
|
|
3213
3382
|
}
|
|
@@ -3439,7 +3608,6 @@ function updateMicroLocation(appName, path, microLocation, type) {
|
|
|
3439
3608
|
* @returns MicroRouter
|
|
3440
3609
|
*/
|
|
3441
3610
|
function createMicroRouter(appName, url) {
|
|
3442
|
-
rewriteHistoryState();
|
|
3443
3611
|
const microLocation = createMicroLocation(appName, url);
|
|
3444
3612
|
return {
|
|
3445
3613
|
microLocation,
|
|
@@ -3465,7 +3633,7 @@ function updateBrowserURLWithLocation(appName, microLocation, defaultPage) {
|
|
|
3465
3633
|
if (defaultPage)
|
|
3466
3634
|
updateMicroLocation(appName, defaultPage, microLocation, 'prevent');
|
|
3467
3635
|
// attach microApp route info to browser URL
|
|
3468
|
-
attachRouteToBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName,
|
|
3636
|
+
attachRouteToBrowserURL(setMicroPathToURL(appName, microLocation), setMicroState(appName, null));
|
|
3469
3637
|
// trigger guards after change browser URL
|
|
3470
3638
|
autoTriggerNavigationGuard(appName, microLocation);
|
|
3471
3639
|
}
|
|
@@ -3610,6 +3778,8 @@ class SandBox {
|
|
|
3610
3778
|
this.injectedKeys = new Set();
|
|
3611
3779
|
// Properties escape to rawWindow, cleared when unmount
|
|
3612
3780
|
this.escapeKeys = new Set();
|
|
3781
|
+
// record injected values before the first execution of umdHookMount and rebuild before remount umd app
|
|
3782
|
+
// private recordUmdInjectedValues?: Map<PropertyKey, unknown>
|
|
3613
3783
|
// sandbox state
|
|
3614
3784
|
this.active = false;
|
|
3615
3785
|
this.microAppWindow = {}; // Proxy target
|
|
@@ -3623,7 +3793,8 @@ class SandBox {
|
|
|
3623
3793
|
// inject global properties
|
|
3624
3794
|
this.initStaticGlobalKeys(this.microAppWindow, appName, url, useMemoryRouter);
|
|
3625
3795
|
}
|
|
3626
|
-
|
|
3796
|
+
// TODO: 重构
|
|
3797
|
+
start(umdMode = false, baseRoute = '', useMemoryRouter = true, defaultPage = '', disablePatchRequest = false) {
|
|
3627
3798
|
if (!this.active) {
|
|
3628
3799
|
this.active = true;
|
|
3629
3800
|
if (useMemoryRouter) {
|
|
@@ -3634,17 +3805,23 @@ class SandBox {
|
|
|
3634
3805
|
else {
|
|
3635
3806
|
this.microAppWindow.__MICRO_APP_BASE_ROUTE__ = this.microAppWindow.__MICRO_APP_BASE_URL__ = baseRoute;
|
|
3636
3807
|
}
|
|
3637
|
-
|
|
3638
|
-
|
|
3808
|
+
/**
|
|
3809
|
+
* 1. prevent the key deleted during sandBox.stop after rewrite
|
|
3810
|
+
* 2. umd mode will not delete any keys during sandBox.stop
|
|
3811
|
+
*/
|
|
3812
|
+
if (!umdMode) {
|
|
3813
|
+
this.initGlobalKeysWhenStart(this.microAppWindow, this.proxyWindow.__MICRO_APP_NAME__, this.proxyWindow.__MICRO_APP_URL__, disablePatchRequest);
|
|
3814
|
+
}
|
|
3639
3815
|
if (++SandBox.activeCount === 1) {
|
|
3640
3816
|
effectDocumentEvent();
|
|
3641
3817
|
patchElementPrototypeMethods();
|
|
3642
3818
|
initEnvOfNestedApp();
|
|
3819
|
+
patchHistory();
|
|
3643
3820
|
}
|
|
3644
3821
|
fixBabelPolyfill6();
|
|
3645
3822
|
}
|
|
3646
3823
|
}
|
|
3647
|
-
stop(keepRouteState, clearEventSource) {
|
|
3824
|
+
stop(umdMode, keepRouteState, clearEventSource) {
|
|
3648
3825
|
if (this.active) {
|
|
3649
3826
|
this.releaseEffect();
|
|
3650
3827
|
this.microAppWindow.microApp.clearDataListener();
|
|
@@ -3661,37 +3838,41 @@ class SandBox {
|
|
|
3661
3838
|
* NOTE:
|
|
3662
3839
|
* 1. injectedKeys and escapeKeys must be placed at the back
|
|
3663
3840
|
* 2. if key in initial microAppWindow, and then rewrite, this key will be delete from microAppWindow when stop, and lost when restart
|
|
3841
|
+
* 3. umd mode will not delete global keys
|
|
3664
3842
|
*/
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3843
|
+
if (!umdMode) {
|
|
3844
|
+
this.injectedKeys.forEach((key) => {
|
|
3845
|
+
Reflect.deleteProperty(this.microAppWindow, key);
|
|
3846
|
+
});
|
|
3847
|
+
this.injectedKeys.clear();
|
|
3848
|
+
this.escapeKeys.forEach((key) => {
|
|
3849
|
+
Reflect.deleteProperty(globalEnv.rawWindow, key);
|
|
3850
|
+
});
|
|
3851
|
+
this.escapeKeys.clear();
|
|
3852
|
+
}
|
|
3673
3853
|
if (--SandBox.activeCount === 0) {
|
|
3674
3854
|
releaseEffectDocumentEvent();
|
|
3675
3855
|
releasePatches();
|
|
3856
|
+
releasePatchHistory();
|
|
3676
3857
|
}
|
|
3677
3858
|
this.active = false;
|
|
3678
3859
|
}
|
|
3679
3860
|
}
|
|
3680
3861
|
// record umd snapshot before the first execution of umdHookMount
|
|
3681
3862
|
recordUmdSnapshot() {
|
|
3682
|
-
this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
3863
|
+
// this.microAppWindow.__MICRO_APP_UMD_MODE__ = true
|
|
3683
3864
|
this.recordUmdEffect();
|
|
3684
3865
|
recordDataCenterSnapshot(this.microAppWindow.microApp);
|
|
3685
|
-
this.recordUmdInjectedValues = new Map()
|
|
3686
|
-
this.injectedKeys.forEach((key) => {
|
|
3687
|
-
|
|
3688
|
-
})
|
|
3866
|
+
// this.recordUmdInjectedValues = new Map<PropertyKey, unknown>()
|
|
3867
|
+
// this.injectedKeys.forEach((key: PropertyKey) => {
|
|
3868
|
+
// this.recordUmdInjectedValues!.set(key, Reflect.get(this.microAppWindow, key))
|
|
3869
|
+
// })
|
|
3689
3870
|
}
|
|
3690
3871
|
// rebuild umd snapshot before remount umd app
|
|
3691
3872
|
rebuildUmdSnapshot() {
|
|
3692
|
-
this.recordUmdInjectedValues
|
|
3693
|
-
|
|
3694
|
-
})
|
|
3873
|
+
// this.recordUmdInjectedValues!.forEach((value: unknown, key: PropertyKey) => {
|
|
3874
|
+
// Reflect.set(this.proxyWindow, key, value)
|
|
3875
|
+
// })
|
|
3695
3876
|
this.rebuildUmdEffect();
|
|
3696
3877
|
rebuildDataCenterSnapshot(this.microAppWindow.microApp);
|
|
3697
3878
|
}
|
|
@@ -3841,15 +4022,26 @@ class SandBox {
|
|
|
3841
4022
|
this.setMicroAppRouter(microAppWindow, appName, url);
|
|
3842
4023
|
}
|
|
3843
4024
|
setProxyDocument(microAppWindow, appName) {
|
|
3844
|
-
const proxyDocument = this.createProxyDocument(appName);
|
|
3845
|
-
|
|
3846
|
-
|
|
3847
|
-
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
4025
|
+
const { proxyDocument, MicroDocument } = this.createProxyDocument(appName);
|
|
4026
|
+
rawDefineProperties(microAppWindow, {
|
|
4027
|
+
document: {
|
|
4028
|
+
configurable: false,
|
|
4029
|
+
enumerable: true,
|
|
4030
|
+
get() {
|
|
4031
|
+
throttleDeferForSetAppName(appName);
|
|
4032
|
+
// return globalEnv.rawDocument
|
|
4033
|
+
return proxyDocument;
|
|
4034
|
+
},
|
|
3852
4035
|
},
|
|
4036
|
+
Document: {
|
|
4037
|
+
configurable: false,
|
|
4038
|
+
enumerable: false,
|
|
4039
|
+
get() {
|
|
4040
|
+
throttleDeferForSetAppName(appName);
|
|
4041
|
+
// return globalEnv.rawRootDocument
|
|
4042
|
+
return MicroDocument;
|
|
4043
|
+
},
|
|
4044
|
+
}
|
|
3853
4045
|
});
|
|
3854
4046
|
}
|
|
3855
4047
|
// properties associated with the native window
|
|
@@ -3884,11 +4076,13 @@ class SandBox {
|
|
|
3884
4076
|
* @param microAppWindow micro window
|
|
3885
4077
|
* @param appName app name
|
|
3886
4078
|
* @param url app url
|
|
4079
|
+
* @param disablePatchRequest prevent rewrite request method of child app
|
|
3887
4080
|
*/
|
|
3888
|
-
initGlobalKeysWhenStart(microAppWindow, appName, url) {
|
|
4081
|
+
initGlobalKeysWhenStart(microAppWindow, appName, url, disablePatchRequest) {
|
|
3889
4082
|
microAppWindow.hasOwnProperty = (key) => rawHasOwnProperty.call(microAppWindow, key) || rawHasOwnProperty.call(globalEnv.rawWindow, key);
|
|
3890
4083
|
this.setHijackProperty(microAppWindow, appName);
|
|
3891
|
-
|
|
4084
|
+
if (!disablePatchRequest)
|
|
4085
|
+
this.patchRequestApi(microAppWindow, appName, url);
|
|
3892
4086
|
}
|
|
3893
4087
|
// set hijack Properties to microAppWindow
|
|
3894
4088
|
setHijackProperty(microAppWindow, appName) {
|
|
@@ -3991,23 +4185,75 @@ class SandBox {
|
|
|
3991
4185
|
removeRouteInfoForKeepAliveApp() {
|
|
3992
4186
|
removeStateAndPathFromBrowser(this.proxyWindow.__MICRO_APP_NAME__);
|
|
3993
4187
|
}
|
|
4188
|
+
/**
|
|
4189
|
+
* Create new document and Document
|
|
4190
|
+
*/
|
|
3994
4191
|
createProxyDocument(appName) {
|
|
4192
|
+
const rawDocument = globalEnv.rawDocument;
|
|
4193
|
+
const rawRootDocument = globalEnv.rawRootDocument;
|
|
3995
4194
|
const createElement = function (tagName, options) {
|
|
3996
|
-
const element = globalEnv.rawCreateElement.call(
|
|
4195
|
+
const element = globalEnv.rawCreateElement.call(rawDocument, tagName, options);
|
|
3997
4196
|
element.__MICRO_APP_NAME__ = appName;
|
|
3998
4197
|
return element;
|
|
3999
4198
|
};
|
|
4000
|
-
const proxyDocument = new Proxy(
|
|
4199
|
+
const proxyDocument = new Proxy(rawDocument, {
|
|
4001
4200
|
get(target, key) {
|
|
4002
4201
|
throttleDeferForSetAppName(appName);
|
|
4003
4202
|
throttleDeferForParentNode(proxyDocument);
|
|
4004
4203
|
if (key === 'createElement')
|
|
4005
4204
|
return createElement;
|
|
4205
|
+
if (key === Symbol.toStringTag)
|
|
4206
|
+
return 'ProxyDocument';
|
|
4006
4207
|
const rawValue = Reflect.get(target, key);
|
|
4007
|
-
return isFunction(rawValue) ? bindFunctionToRawObject(
|
|
4208
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4008
4209
|
},
|
|
4210
|
+
set(target, key, value) {
|
|
4211
|
+
// Fix TypeError: Illegal invocation when set document.title
|
|
4212
|
+
Reflect.set(target, key, value);
|
|
4213
|
+
/**
|
|
4214
|
+
* If the set method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown.
|
|
4215
|
+
*/
|
|
4216
|
+
return true;
|
|
4217
|
+
}
|
|
4009
4218
|
});
|
|
4010
|
-
|
|
4219
|
+
class MicroDocument {
|
|
4220
|
+
static [Symbol.hasInstance](target) {
|
|
4221
|
+
let proto = target;
|
|
4222
|
+
while (proto = Object.getPrototypeOf(proto)) {
|
|
4223
|
+
if (proto === MicroDocument.prototype) {
|
|
4224
|
+
return true;
|
|
4225
|
+
}
|
|
4226
|
+
}
|
|
4227
|
+
return (target === proxyDocument ||
|
|
4228
|
+
target instanceof rawRootDocument);
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
/**
|
|
4232
|
+
* TIP:
|
|
4233
|
+
* 1. child class __proto__, which represents the inherit of the constructor, always points to the parent class
|
|
4234
|
+
* 2. child class prototype.__proto__, which represents the inherit of methods, always points to parent class prototype
|
|
4235
|
+
* e.g.
|
|
4236
|
+
* class B extends A {}
|
|
4237
|
+
* B.__proto__ === A // true
|
|
4238
|
+
* B.prototype.__proto__ === A.prototype // true
|
|
4239
|
+
*/
|
|
4240
|
+
Object.setPrototypeOf(MicroDocument, rawRootDocument);
|
|
4241
|
+
// Object.create(rawRootDocument.prototype) will cause MicroDocument and proxyDocument methods not same when exec Document.prototype.xxx = xxx in child app
|
|
4242
|
+
Object.setPrototypeOf(MicroDocument.prototype, new Proxy(rawRootDocument.prototype, {
|
|
4243
|
+
get(target, key) {
|
|
4244
|
+
throttleDeferForSetAppName(appName);
|
|
4245
|
+
const rawValue = Reflect.get(target, key);
|
|
4246
|
+
return isFunction(rawValue) ? bindFunctionToRawObject(rawDocument, rawValue, 'DOCUMENT') : rawValue;
|
|
4247
|
+
},
|
|
4248
|
+
set(target, key, value) {
|
|
4249
|
+
Reflect.set(target, key, value);
|
|
4250
|
+
return true;
|
|
4251
|
+
}
|
|
4252
|
+
}));
|
|
4253
|
+
return {
|
|
4254
|
+
proxyDocument,
|
|
4255
|
+
MicroDocument,
|
|
4256
|
+
};
|
|
4011
4257
|
}
|
|
4012
4258
|
}
|
|
4013
4259
|
SandBox.activeCount = 0; // number of active sandbox
|
|
@@ -4076,7 +4322,7 @@ function dispatchCustomEventToMicroApp(eventName, appName, detail = {}) {
|
|
|
4076
4322
|
// micro app instances
|
|
4077
4323
|
const appInstanceMap = new Map();
|
|
4078
4324
|
class CreateApp {
|
|
4079
|
-
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, defaultPage, }) {
|
|
4325
|
+
constructor({ name, url, ssrUrl, container, inline, scopecss, useSandbox, useMemoryRouter, baseroute, keepRouteState, hiddenRouter, defaultPage, disablePatchRequest, }) {
|
|
4080
4326
|
this.state = appStates.CREATED;
|
|
4081
4327
|
this.keepAliveState = null;
|
|
4082
4328
|
this.keepAliveContainer = null;
|
|
@@ -4089,18 +4335,20 @@ class CreateApp {
|
|
|
4089
4335
|
this.prefetchResolve = null;
|
|
4090
4336
|
this.container = null;
|
|
4091
4337
|
this.sandBox = null;
|
|
4092
|
-
this.container = container !== null && container !== void 0 ? container : null;
|
|
4093
|
-
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
4094
|
-
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
4095
|
-
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
4096
|
-
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4097
|
-
// optional during init👆
|
|
4098
4338
|
this.name = name;
|
|
4099
4339
|
this.url = url;
|
|
4100
4340
|
this.useSandbox = useSandbox;
|
|
4101
4341
|
this.scopecss = this.useSandbox && scopecss;
|
|
4102
4342
|
this.useMemoryRouter = this.useSandbox && useMemoryRouter;
|
|
4343
|
+
// optional during init base on prefetch 👇
|
|
4344
|
+
this.container = container !== null && container !== void 0 ? container : null;
|
|
4345
|
+
this.ssrUrl = ssrUrl !== null && ssrUrl !== void 0 ? ssrUrl : '';
|
|
4346
|
+
this.inline = inline !== null && inline !== void 0 ? inline : false;
|
|
4347
|
+
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : '';
|
|
4348
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : false;
|
|
4349
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : false;
|
|
4103
4350
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : '';
|
|
4351
|
+
this.disablePatchRequest = disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : false;
|
|
4104
4352
|
this.source = {
|
|
4105
4353
|
links: new Map(),
|
|
4106
4354
|
scripts: new Map(),
|
|
@@ -4111,7 +4359,7 @@ class CreateApp {
|
|
|
4111
4359
|
// Load resources
|
|
4112
4360
|
loadSourceCode() {
|
|
4113
4361
|
this.state = appStates.LOADING;
|
|
4114
|
-
|
|
4362
|
+
HTMLLoader.getInstance().run(this, extractSourceDom);
|
|
4115
4363
|
}
|
|
4116
4364
|
/**
|
|
4117
4365
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
@@ -4151,17 +4399,17 @@ class CreateApp {
|
|
|
4151
4399
|
* @param inline js runs in inline mode
|
|
4152
4400
|
* @param baseroute route prefix, default is ''
|
|
4153
4401
|
* @param keepRouteState keep route state when unmount, default is false
|
|
4402
|
+
* @param disablePatchRequest prevent rewrite request method of child app
|
|
4154
4403
|
*/
|
|
4155
|
-
mount(container, inline, baseroute, keepRouteState, defaultPage) {
|
|
4404
|
+
mount(container, inline, baseroute, keepRouteState, defaultPage, hiddenRouter, disablePatchRequest) {
|
|
4156
4405
|
var _a, _b, _c;
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
// keepRouteState effective on unmount
|
|
4160
|
-
if (isBoolean(keepRouteState))
|
|
4161
|
-
this.keepRouteState = keepRouteState;
|
|
4406
|
+
this.inline = inline !== null && inline !== void 0 ? inline : this.inline;
|
|
4407
|
+
this.keepRouteState = keepRouteState !== null && keepRouteState !== void 0 ? keepRouteState : this.keepRouteState;
|
|
4162
4408
|
this.container = (_a = this.container) !== null && _a !== void 0 ? _a : container;
|
|
4163
4409
|
this.baseroute = baseroute !== null && baseroute !== void 0 ? baseroute : this.baseroute;
|
|
4164
4410
|
this.defaultPage = defaultPage !== null && defaultPage !== void 0 ? defaultPage : this.defaultPage;
|
|
4411
|
+
this.hiddenRouter = hiddenRouter !== null && hiddenRouter !== void 0 ? hiddenRouter : this.hiddenRouter;
|
|
4412
|
+
this.disablePatchRequest = disablePatchRequest !== null && disablePatchRequest !== void 0 ? disablePatchRequest : this.disablePatchRequest;
|
|
4165
4413
|
if (this.loadSourceLevel !== 2) {
|
|
4166
4414
|
this.state = appStates.LOADING;
|
|
4167
4415
|
return;
|
|
@@ -4169,21 +4417,26 @@ class CreateApp {
|
|
|
4169
4417
|
dispatchLifecyclesEvent(this.container, this.name, lifeCycles.BEFOREMOUNT);
|
|
4170
4418
|
this.state = appStates.MOUNTING;
|
|
4171
4419
|
cloneContainer(this.source.html, this.container, !this.umdMode);
|
|
4172
|
-
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.baseroute, this.useMemoryRouter, this.defaultPage);
|
|
4420
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.start(this.umdMode, this.baseroute, this.useMemoryRouter, this.defaultPage, this.disablePatchRequest);
|
|
4173
4421
|
let umdHookMountResult; // result of mount function
|
|
4174
4422
|
if (!this.umdMode) {
|
|
4175
4423
|
let hasDispatchMountedEvent = false;
|
|
4176
4424
|
// if all js are executed, param isFinished will be true
|
|
4177
4425
|
execScripts(this.source.scripts, this, (isFinished) => {
|
|
4178
|
-
var _a;
|
|
4179
4426
|
if (!this.umdMode) {
|
|
4180
4427
|
const { mount, unmount } = this.getUmdLibraryHooks();
|
|
4428
|
+
/**
|
|
4429
|
+
* umdHookUnmount can works in non UMD mode
|
|
4430
|
+
* register with window.unmount
|
|
4431
|
+
*/
|
|
4432
|
+
this.umdHookUnmount = unmount;
|
|
4181
4433
|
// if mount & unmount is function, the sub app is umd mode
|
|
4182
4434
|
if (isFunction(mount) && isFunction(unmount)) {
|
|
4183
4435
|
this.umdHookMount = mount;
|
|
4184
|
-
this.umdHookUnmount = unmount;
|
|
4185
4436
|
this.umdMode = true;
|
|
4186
|
-
(
|
|
4437
|
+
if (this.sandBox)
|
|
4438
|
+
this.sandBox.proxyWindow.__MICRO_APP_UMD_MODE__ = true;
|
|
4439
|
+
// this.sandBox?.recordUmdSnapshot()
|
|
4187
4440
|
try {
|
|
4188
4441
|
umdHookMountResult = this.umdHookMount();
|
|
4189
4442
|
}
|
|
@@ -4251,7 +4504,7 @@ class CreateApp {
|
|
|
4251
4504
|
* send an unmount event to the micro app or call umd unmount hook
|
|
4252
4505
|
* before the sandbox is cleared
|
|
4253
4506
|
*/
|
|
4254
|
-
if (this.umdHookUnmount) {
|
|
4507
|
+
if (isFunction(this.umdHookUnmount)) {
|
|
4255
4508
|
try {
|
|
4256
4509
|
umdHookUnmountResult = this.umdHookUnmount();
|
|
4257
4510
|
}
|
|
@@ -4285,20 +4538,23 @@ class CreateApp {
|
|
|
4285
4538
|
* @param unmountcb callback of unmount
|
|
4286
4539
|
*/
|
|
4287
4540
|
actionsForUnmount(destroy, unmountcb) {
|
|
4288
|
-
var _a;
|
|
4541
|
+
var _a, _b;
|
|
4289
4542
|
if (destroy) {
|
|
4290
4543
|
this.actionsForCompletelyDestroy();
|
|
4291
4544
|
}
|
|
4292
4545
|
else if (this.umdMode && this.container.childElementCount) {
|
|
4293
4546
|
cloneContainer(this.container, this.source.html, false);
|
|
4294
4547
|
}
|
|
4548
|
+
if (this.umdMode) {
|
|
4549
|
+
(_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.recordUmdSnapshot();
|
|
4550
|
+
}
|
|
4295
4551
|
/**
|
|
4296
4552
|
* this.container maybe contains micro-app element, stop sandbox should exec after cloneContainer
|
|
4297
4553
|
* NOTE:
|
|
4298
4554
|
* 1. if destroy is true, clear route state
|
|
4299
4555
|
* 2. umd mode and keep-alive will not clear EventSource
|
|
4300
4556
|
*/
|
|
4301
|
-
(
|
|
4557
|
+
(_b = this.sandBox) === null || _b === void 0 ? void 0 : _b.stop(this.umdMode, this.keepRouteState && !destroy, !this.umdMode || destroy);
|
|
4302
4558
|
if (!getActiveApps().length) {
|
|
4303
4559
|
releasePatchSetAttribute();
|
|
4304
4560
|
}
|
|
@@ -4370,13 +4626,18 @@ class CreateApp {
|
|
|
4370
4626
|
}
|
|
4371
4627
|
// get umd library, if it not exist, return empty object
|
|
4372
4628
|
getUmdLibraryHooks() {
|
|
4373
|
-
var _a, _b;
|
|
4629
|
+
var _a, _b, _c, _d;
|
|
4374
4630
|
// after execScripts, the app maybe unmounted
|
|
4375
4631
|
if (appStates.UNMOUNT !== this.state) {
|
|
4376
4632
|
const global = ((_b = (_a = this.sandBox) === null || _a === void 0 ? void 0 : _a.proxyWindow) !== null && _b !== void 0 ? _b : globalEnv.rawWindow);
|
|
4377
4633
|
this.libraryName = getRootContainer(this.container).getAttribute('library') || `micro-app-${this.name}`;
|
|
4378
|
-
|
|
4379
|
-
|
|
4634
|
+
if (isObject(global[this.libraryName])) {
|
|
4635
|
+
return global[this.libraryName];
|
|
4636
|
+
}
|
|
4637
|
+
return {
|
|
4638
|
+
mount: (_c = this.sandBox) === null || _c === void 0 ? void 0 : _c.proxyWindow.mount,
|
|
4639
|
+
unmount: (_d = this.sandBox) === null || _d === void 0 ? void 0 : _d.proxyWindow.unmount,
|
|
4640
|
+
};
|
|
4380
4641
|
}
|
|
4381
4642
|
return {};
|
|
4382
4643
|
}
|
|
@@ -4436,6 +4697,7 @@ function defineElement(tagName) {
|
|
|
4436
4697
|
this.setAttribute('name', this.appName);
|
|
4437
4698
|
}
|
|
4438
4699
|
};
|
|
4700
|
+
// patchSetAttribute hijiack data attribute, it needs exec first
|
|
4439
4701
|
patchSetAttribute();
|
|
4440
4702
|
}
|
|
4441
4703
|
static get observedAttributes() {
|
|
@@ -4612,7 +4874,7 @@ function defineElement(tagName) {
|
|
|
4612
4874
|
app.isPrefetch = false;
|
|
4613
4875
|
defer(() => {
|
|
4614
4876
|
var _a;
|
|
4615
|
-
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue());
|
|
4877
|
+
return app.mount((_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this, this.getDisposeResult('inline'), this.getBaseRouteCompatible(), this.getDisposeResult('keep-router-state'), this.getDefaultPageValue(), this.getDisposeResult('hidden-router'), this.getDisposeResult('disable-patch-request'));
|
|
4616
4878
|
});
|
|
4617
4879
|
}
|
|
4618
4880
|
// create app instance
|
|
@@ -4631,12 +4893,14 @@ function defineElement(tagName) {
|
|
|
4631
4893
|
ssrUrl: this.ssrUrl,
|
|
4632
4894
|
container: (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this,
|
|
4633
4895
|
inline: this.getDisposeResult('inline'),
|
|
4634
|
-
scopecss: !(this.getDisposeResult('
|
|
4635
|
-
useSandbox: !this.getDisposeResult('
|
|
4896
|
+
scopecss: !(this.getDisposeResult('disable-scopecss') || this.getDisposeResult('shadowDOM')),
|
|
4897
|
+
useSandbox: !this.getDisposeResult('disable-sandbox'),
|
|
4636
4898
|
useMemoryRouter: !this.getDisposeResult('disable-memory-router'),
|
|
4637
4899
|
baseroute: this.getBaseRouteCompatible(),
|
|
4638
4900
|
keepRouteState: this.getDisposeResult('keep-router-state'),
|
|
4639
4901
|
defaultPage: this.getDefaultPageValue(),
|
|
4902
|
+
hiddenRouter: this.getDisposeResult('hidden-router'),
|
|
4903
|
+
disablePatchRequest: this.getDisposeResult('disable-patch-request'),
|
|
4640
4904
|
});
|
|
4641
4905
|
appInstanceMap.set(this.appName, instance);
|
|
4642
4906
|
}
|
|
@@ -4671,25 +4935,25 @@ function defineElement(tagName) {
|
|
|
4671
4935
|
*/
|
|
4672
4936
|
getDisposeResult(name) {
|
|
4673
4937
|
// @ts-ignore
|
|
4674
|
-
return (this.compatibleSpecialProperties(name) || microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4938
|
+
return (this.compatibleSpecialProperties(name) || !!microApp[name]) && this.compatibleDisableSpecialProperties(name);
|
|
4675
4939
|
}
|
|
4676
4940
|
// compatible of disableScopecss & disableSandbox
|
|
4677
4941
|
compatibleSpecialProperties(name) {
|
|
4678
|
-
if (name === '
|
|
4679
|
-
return this.hasAttribute('
|
|
4942
|
+
if (name === 'disable-scopecss') {
|
|
4943
|
+
return this.hasAttribute('disable-scopecss') || this.hasAttribute('disableScopecss');
|
|
4680
4944
|
}
|
|
4681
|
-
else if (name === '
|
|
4682
|
-
return this.hasAttribute('
|
|
4945
|
+
else if (name === 'disable-sandbox') {
|
|
4946
|
+
return this.hasAttribute('disable-sandbox') || this.hasAttribute('disableSandbox');
|
|
4683
4947
|
}
|
|
4684
4948
|
return this.hasAttribute(name);
|
|
4685
4949
|
}
|
|
4686
4950
|
// compatible of disableScopecss & disableSandbox
|
|
4687
4951
|
compatibleDisableSpecialProperties(name) {
|
|
4688
|
-
if (name === '
|
|
4689
|
-
return this.getAttribute('
|
|
4952
|
+
if (name === 'disable-scopecss') {
|
|
4953
|
+
return this.getAttribute('disable-scopecss') !== 'false' && this.getAttribute('disableScopecss') !== 'false';
|
|
4690
4954
|
}
|
|
4691
|
-
else if (name === '
|
|
4692
|
-
return this.getAttribute('
|
|
4955
|
+
else if (name === 'disable-sandbox') {
|
|
4956
|
+
return this.getAttribute('disable-sandbox') !== 'false' && this.getAttribute('disableSandbox') !== 'false';
|
|
4693
4957
|
}
|
|
4694
4958
|
return this.getAttribute(name) !== 'false';
|
|
4695
4959
|
}
|
|
@@ -4801,7 +5065,7 @@ function preFetch(apps) {
|
|
|
4801
5065
|
function preFetchInSerial(prefetchApp) {
|
|
4802
5066
|
return new Promise((resolve) => {
|
|
4803
5067
|
requestIdleCallback(() => {
|
|
4804
|
-
var _a, _b, _c;
|
|
5068
|
+
var _a, _b, _c, _d, _e;
|
|
4805
5069
|
if (isPlainObject(prefetchApp) && navigator.onLine) {
|
|
4806
5070
|
prefetchApp.name = formatAppName(prefetchApp.name);
|
|
4807
5071
|
prefetchApp.url = formatAppURL(prefetchApp.url, prefetchApp.name);
|
|
@@ -4809,9 +5073,9 @@ function preFetchInSerial(prefetchApp) {
|
|
|
4809
5073
|
const app = new CreateApp({
|
|
4810
5074
|
name: prefetchApp.name,
|
|
4811
5075
|
url: prefetchApp.url,
|
|
4812
|
-
scopecss: !((_a = prefetchApp
|
|
4813
|
-
useSandbox: !((
|
|
4814
|
-
useMemoryRouter: !((
|
|
5076
|
+
scopecss: !((_b = (_a = prefetchApp['disable-scopecss']) !== null && _a !== void 0 ? _a : prefetchApp.disableScopecss) !== null && _b !== void 0 ? _b : microApp['disable-scopecss']),
|
|
5077
|
+
useSandbox: !((_d = (_c = prefetchApp['disable-sandbox']) !== null && _c !== void 0 ? _c : prefetchApp.disableSandbox) !== null && _d !== void 0 ? _d : microApp['disable-sandbox']),
|
|
5078
|
+
useMemoryRouter: !((_e = prefetchApp['disable-memory-router']) !== null && _e !== void 0 ? _e : microApp['disable-memory-router']),
|
|
4815
5079
|
});
|
|
4816
5080
|
app.isPrefetch = true;
|
|
4817
5081
|
app.prefetchResolve = resolve;
|
|
@@ -4861,7 +5125,7 @@ function fetchGlobalResources(resources, suffix, cache) {
|
|
|
4861
5125
|
* @param excludeHiddenApp exclude hidden keep-alive app, default is false
|
|
4862
5126
|
* @returns active apps
|
|
4863
5127
|
*/
|
|
4864
|
-
function getActiveApps(excludeHiddenApp) {
|
|
5128
|
+
function getActiveApps(excludeHiddenApp = false) {
|
|
4865
5129
|
const activeApps = [];
|
|
4866
5130
|
appInstanceMap.forEach((app, appName) => {
|
|
4867
5131
|
if (appStates.UNMOUNT !== app.getAppState() &&
|
|
@@ -4957,6 +5221,7 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4957
5221
|
this.router = router;
|
|
4958
5222
|
}
|
|
4959
5223
|
start(options) {
|
|
5224
|
+
var _a, _b;
|
|
4960
5225
|
if (!isBrowser || !window.customElements) {
|
|
4961
5226
|
return logError('micro-app is not supported in this environment');
|
|
4962
5227
|
}
|
|
@@ -4982,9 +5247,13 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
4982
5247
|
// @ts-ignore
|
|
4983
5248
|
this.destory = options.destory;
|
|
4984
5249
|
this.inline = options.inline;
|
|
4985
|
-
this
|
|
4986
|
-
this
|
|
4987
|
-
this
|
|
5250
|
+
this['disable-scopecss'] = (_a = options['disable-scopecss']) !== null && _a !== void 0 ? _a : options.disableScopecss;
|
|
5251
|
+
this['disable-sandbox'] = (_b = options['disable-sandbox']) !== null && _b !== void 0 ? _b : options.disableSandbox;
|
|
5252
|
+
this['disable-memory-router'] = options['disable-memory-router'];
|
|
5253
|
+
this['disable-patch-request'] = options['disable-patch-request'];
|
|
5254
|
+
this['keep-router-state'] = options['keep-router-state'];
|
|
5255
|
+
this['hidden-router'] = options['hidden-router'];
|
|
5256
|
+
this.esmodule = options.esmodule;
|
|
4988
5257
|
this.ssr = options.ssr;
|
|
4989
5258
|
isFunction(options.fetch) && (this.fetch = options.fetch);
|
|
4990
5259
|
isPlainObject(options.lifeCycles) && (this.lifeCycles = options.lifeCycles);
|