@micro-zoe/micro-app 0.8.3 → 0.8.6
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 +2 -2
- package/README.zh-cn.md +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.esm.js +220 -120
- 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 +4 -2
- package/typings/global.d.ts +16 -2
package/README.md
CHANGED
|
@@ -97,7 +97,7 @@ yarn bootstrap
|
|
|
97
97
|
yarn start
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
For more commands, see [
|
|
100
|
+
For more commands, see [DEVELOP](https://github.com/micro-zoe/micro-app/blob/master/DEVELOP.md)
|
|
101
101
|
|
|
102
102
|
# FAQ
|
|
103
103
|
<details>
|
|
@@ -152,7 +152,7 @@ For more commands, see [DEVELP](https://github.com/micro-zoe/micro-app/blob/mast
|
|
|
152
152
|
</details>
|
|
153
153
|
|
|
154
154
|
# Contributors
|
|
155
|
-
<a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://micro-zoe.com/contributors.svg?height=55&people=
|
|
155
|
+
<a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://micro-zoe.com/contributors.svg?height=55&people=13" /></a>
|
|
156
156
|
<!-- opencollective is inaccurate -->
|
|
157
157
|
<!-- <a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://opencollective.com/micro-app/contributors.svg?width=890&button=false" /></a> -->
|
|
158
158
|
|
package/README.zh-cn.md
CHANGED
|
@@ -153,7 +153,7 @@ yarn start # 访问 http://localhost:3000
|
|
|
153
153
|
</details>
|
|
154
154
|
|
|
155
155
|
# 贡献者们
|
|
156
|
-
<a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://micro-zoe.com/contributors.svg?height=55&people=
|
|
156
|
+
<a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://micro-zoe.com/contributors.svg?height=55&people=13" /></a>
|
|
157
157
|
<!-- opencollective is inaccurate -->
|
|
158
158
|
<!-- <a href="https://github.com/micro-zoe/micro-app/graphs/contributors"><img src="https://opencollective.com/micro-app/contributors.svg?width=890&button=false" /></a> -->
|
|
159
159
|
|
package/lib/index.d.ts
CHANGED
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.8.
|
|
1
|
+
const version = '0.8.6';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -303,6 +303,9 @@ function getRootContainer(target) {
|
|
|
303
303
|
function trim(str) {
|
|
304
304
|
return str ? str.replace(/^\s+|\s+$/g, '') : '';
|
|
305
305
|
}
|
|
306
|
+
function isFireFox() {
|
|
307
|
+
return navigator.userAgent.indexOf('Firefox') > -1;
|
|
308
|
+
}
|
|
306
309
|
|
|
307
310
|
var ObservedAttrName;
|
|
308
311
|
(function (ObservedAttrName) {
|
|
@@ -356,6 +359,66 @@ function fetchSource(url, appName = null, options = {}) {
|
|
|
356
359
|
});
|
|
357
360
|
}
|
|
358
361
|
|
|
362
|
+
class HTMLLoader {
|
|
363
|
+
static getInstance() {
|
|
364
|
+
if (!this.instance) {
|
|
365
|
+
this.instance = new HTMLLoader();
|
|
366
|
+
}
|
|
367
|
+
return this.instance;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* run logic of load and format html
|
|
371
|
+
* @param successCb success callback
|
|
372
|
+
* @param errorCb error callback, type: (err: Error, meetFetchErr: boolean) => void
|
|
373
|
+
*/
|
|
374
|
+
run(app, successCb) {
|
|
375
|
+
const appName = app.name;
|
|
376
|
+
const htmlUrl = app.ssrUrl || app.url;
|
|
377
|
+
fetchSource(htmlUrl, appName, { cache: 'no-cache' }).then((htmlStr) => {
|
|
378
|
+
if (!htmlStr) {
|
|
379
|
+
const msg = 'html is empty, please check in detail';
|
|
380
|
+
app.onerror(new Error(msg));
|
|
381
|
+
return logError(msg, appName);
|
|
382
|
+
}
|
|
383
|
+
htmlStr = this.formatHTML(htmlUrl, htmlStr, appName);
|
|
384
|
+
successCb(htmlStr, app);
|
|
385
|
+
}).catch((e) => {
|
|
386
|
+
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, appName, e);
|
|
387
|
+
app.onLoadError(e);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
formatHTML(htmlUrl, htmlStr, appName) {
|
|
391
|
+
return this.processHtml(htmlUrl, htmlStr, appName, microApp.plugins)
|
|
392
|
+
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
393
|
+
return match
|
|
394
|
+
.replace(/<head/i, '<micro-app-head')
|
|
395
|
+
.replace(/<\/head>/i, '</micro-app-head>');
|
|
396
|
+
})
|
|
397
|
+
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
398
|
+
return match
|
|
399
|
+
.replace(/<body/i, '<micro-app-body')
|
|
400
|
+
.replace(/<\/body>/i, '</micro-app-body>');
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
processHtml(url, code, appName, plugins) {
|
|
404
|
+
var _a;
|
|
405
|
+
if (!plugins)
|
|
406
|
+
return code;
|
|
407
|
+
const mergedPlugins = [];
|
|
408
|
+
plugins.global && mergedPlugins.push(...plugins.global);
|
|
409
|
+
((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName]) && mergedPlugins.push(...plugins.modules[appName]);
|
|
410
|
+
if (mergedPlugins.length > 0) {
|
|
411
|
+
return mergedPlugins.reduce((preCode, plugin) => {
|
|
412
|
+
if (isPlainObject(plugin) && isFunction(plugin.processHtml)) {
|
|
413
|
+
return plugin.processHtml(preCode, url, plugin.options);
|
|
414
|
+
}
|
|
415
|
+
return preCode;
|
|
416
|
+
}, code);
|
|
417
|
+
}
|
|
418
|
+
return code;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
359
422
|
// common reg
|
|
360
423
|
const rootSelectorREG = /(^|\s+)(html|:root)(?=[\s>~[.#:]+|$)/;
|
|
361
424
|
const bodySelectorREG = /(^|\s+)((html[\s>~]+body)|body)(?=[\s>~[.#:]+|$)/;
|
|
@@ -369,7 +432,7 @@ function parseError(msg, linkPath) {
|
|
|
369
432
|
throw err;
|
|
370
433
|
}
|
|
371
434
|
/**
|
|
372
|
-
* Reference
|
|
435
|
+
* Reference https://github.com/reworkcss/css
|
|
373
436
|
* CSSParser mainly deals with 3 scenes: styleRule, @, and comment
|
|
374
437
|
* And scopecss deals with 2 scenes: selector & url
|
|
375
438
|
* And can also disable scopecss with inline comments
|
|
@@ -403,7 +466,7 @@ class CSSParser {
|
|
|
403
466
|
this.baseURI = baseURI;
|
|
404
467
|
this.linkPath = linkPath || '';
|
|
405
468
|
this.matchRules();
|
|
406
|
-
return this.result;
|
|
469
|
+
return isFireFox() ? decodeURIComponent(this.result) : this.result;
|
|
407
470
|
}
|
|
408
471
|
reset() {
|
|
409
472
|
this.cssText = this.prefix = this.baseURI = this.linkPath = this.result = '';
|
|
@@ -422,17 +485,37 @@ class CSSParser {
|
|
|
422
485
|
}
|
|
423
486
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleRule
|
|
424
487
|
matchStyleRule() {
|
|
425
|
-
const
|
|
488
|
+
const selectors = this.formatSelector(true);
|
|
426
489
|
// reset scopecssDisableNextLine
|
|
427
490
|
this.scopecssDisableNextLine = false;
|
|
428
|
-
if (!
|
|
491
|
+
if (!selectors)
|
|
429
492
|
return parseError('selector missing', this.linkPath);
|
|
430
|
-
this.
|
|
493
|
+
this.recordResult(selectors);
|
|
431
494
|
this.matchComments();
|
|
432
495
|
this.styleDeclarations();
|
|
433
496
|
this.matchLeadingSpaces();
|
|
434
497
|
return true;
|
|
435
498
|
}
|
|
499
|
+
formatSelector(skip) {
|
|
500
|
+
const m = this.commonMatch(/^([^{]+)/, skip);
|
|
501
|
+
if (!m)
|
|
502
|
+
return false;
|
|
503
|
+
return m[0].replace(/(^|,[\n\s]*)([^,]+)/g, (_, separator, selector) => {
|
|
504
|
+
selector = trim(selector);
|
|
505
|
+
if (!(this.scopecssDisableNextLine ||
|
|
506
|
+
(this.scopecssDisable && (!this.scopecssDisableSelectors.length ||
|
|
507
|
+
this.scopecssDisableSelectors.includes(selector))) ||
|
|
508
|
+
rootSelectorREG.test(selector))) {
|
|
509
|
+
if (bodySelectorREG.test(selector)) {
|
|
510
|
+
selector = selector.replace(bodySelectorREG, this.prefix + ' micro-app-body');
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
selector = this.prefix + ' ' + selector;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return separator + selector;
|
|
517
|
+
});
|
|
518
|
+
}
|
|
436
519
|
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration
|
|
437
520
|
styleDeclarations() {
|
|
438
521
|
if (!this.matchOpenBrace())
|
|
@@ -458,7 +541,7 @@ class CSSParser {
|
|
|
458
541
|
return `url("${CompletionPath($1, this.baseURI)}")`;
|
|
459
542
|
});
|
|
460
543
|
}
|
|
461
|
-
this.
|
|
544
|
+
this.recordResult(cssValue);
|
|
462
545
|
}
|
|
463
546
|
// reset scopecssDisableNextLine
|
|
464
547
|
this.scopecssDisableNextLine = false;
|
|
@@ -473,39 +556,6 @@ class CSSParser {
|
|
|
473
556
|
}
|
|
474
557
|
return this.matchAllDeclarations();
|
|
475
558
|
}
|
|
476
|
-
formatSelector() {
|
|
477
|
-
const m = this.commonMatch(/^([^{]+)/, true);
|
|
478
|
-
if (!m)
|
|
479
|
-
return false;
|
|
480
|
-
return trim(m[0])
|
|
481
|
-
.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*\/+/g, '')
|
|
482
|
-
.replace(/"(?:\\"|[^"])*"|'(?:\\'|[^'])*'/g, (r) => {
|
|
483
|
-
return r.replace(/,/g, '\u200C');
|
|
484
|
-
})
|
|
485
|
-
.split(/\s*(?![^(]*\)),\s*/)
|
|
486
|
-
.map((s) => {
|
|
487
|
-
const selectorText = s.replace(/\u200C/g, ',');
|
|
488
|
-
if (this.scopecssDisableNextLine) {
|
|
489
|
-
return selectorText;
|
|
490
|
-
}
|
|
491
|
-
else if (this.scopecssDisable) {
|
|
492
|
-
if (!this.scopecssDisableSelectors.length ||
|
|
493
|
-
this.scopecssDisableSelectors.includes(selectorText)) {
|
|
494
|
-
return selectorText;
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
if (selectorText === '*') {
|
|
498
|
-
return this.prefix + ' *';
|
|
499
|
-
}
|
|
500
|
-
else if (bodySelectorREG.test(selectorText)) {
|
|
501
|
-
return selectorText.replace(bodySelectorREG, this.prefix + ' micro-app-body');
|
|
502
|
-
}
|
|
503
|
-
else if (rootSelectorREG.test(selectorText)) { // ignore root selector
|
|
504
|
-
return selectorText;
|
|
505
|
-
}
|
|
506
|
-
return this.prefix + ' ' + selectorText;
|
|
507
|
-
});
|
|
508
|
-
}
|
|
509
559
|
matchAtRule() {
|
|
510
560
|
if (this.cssText[0] !== '@')
|
|
511
561
|
return false;
|
|
@@ -565,7 +615,7 @@ class CSSParser {
|
|
|
565
615
|
pageRule() {
|
|
566
616
|
if (!this.commonMatch(/^@page */))
|
|
567
617
|
return false;
|
|
568
|
-
this.formatSelector();
|
|
618
|
+
this.formatSelector(false);
|
|
569
619
|
// reset scopecssDisableNextLine
|
|
570
620
|
this.scopecssDisableNextLine = false;
|
|
571
621
|
return this.commonHandlerForAtRuleWithSelfRule('page');
|
|
@@ -598,7 +648,7 @@ class CSSParser {
|
|
|
598
648
|
if (!this.commonMatch(reg))
|
|
599
649
|
return false;
|
|
600
650
|
this.matchLeadingSpaces();
|
|
601
|
-
return
|
|
651
|
+
return true;
|
|
602
652
|
};
|
|
603
653
|
}
|
|
604
654
|
// common handler for @font-face, @page
|
|
@@ -631,7 +681,7 @@ class CSSParser {
|
|
|
631
681
|
}
|
|
632
682
|
// get comment content
|
|
633
683
|
let commentText = this.cssText.slice(2, i - 2);
|
|
634
|
-
this.
|
|
684
|
+
this.recordResult(`/*${commentText}*/`);
|
|
635
685
|
commentText = trim(commentText.replace(/^\s*!/, ''));
|
|
636
686
|
// set ignore config
|
|
637
687
|
if (commentText === 'scopecss-disable-next-line') {
|
|
@@ -664,7 +714,7 @@ class CSSParser {
|
|
|
664
714
|
const matchStr = matchArray[0];
|
|
665
715
|
this.cssText = this.cssText.slice(matchStr.length);
|
|
666
716
|
if (!skip)
|
|
667
|
-
this.
|
|
717
|
+
this.recordResult(matchStr);
|
|
668
718
|
return matchArray;
|
|
669
719
|
}
|
|
670
720
|
matchOpenBrace() {
|
|
@@ -677,6 +727,16 @@ class CSSParser {
|
|
|
677
727
|
matchLeadingSpaces() {
|
|
678
728
|
this.commonMatch(/^\s*/);
|
|
679
729
|
}
|
|
730
|
+
// splice string
|
|
731
|
+
recordResult(strFragment) {
|
|
732
|
+
// Firefox is slow when string contain special characters, see https://github.com/micro-zoe/micro-app/issues/256
|
|
733
|
+
if (isFireFox()) {
|
|
734
|
+
this.result += encodeURIComponent(strFragment);
|
|
735
|
+
}
|
|
736
|
+
else {
|
|
737
|
+
this.result += strFragment;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
680
740
|
}
|
|
681
741
|
/**
|
|
682
742
|
* common method of bind CSS
|
|
@@ -921,12 +981,12 @@ function handleNewNode(parent, child, app) {
|
|
|
921
981
|
return child;
|
|
922
982
|
}
|
|
923
983
|
else if (child instanceof HTMLLinkElement) {
|
|
924
|
-
if (child.hasAttribute('exclude')) {
|
|
984
|
+
if (child.hasAttribute('exclude') || checkExcludeUrl(child.getAttribute('href'), app.name)) {
|
|
925
985
|
const linkReplaceComment = document.createComment('link element with exclude attribute ignored by micro-app');
|
|
926
986
|
dynamicElementInMicroAppMap.set(child, linkReplaceComment);
|
|
927
987
|
return linkReplaceComment;
|
|
928
988
|
}
|
|
929
|
-
else if (child.hasAttribute('ignore')) {
|
|
989
|
+
else if (child.hasAttribute('ignore') || checkIgnoreUrl(child.getAttribute('href'), app.name)) {
|
|
930
990
|
return child;
|
|
931
991
|
}
|
|
932
992
|
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
@@ -974,51 +1034,48 @@ function handleNewNode(parent, child, app) {
|
|
|
974
1034
|
* @param passiveChild second param of insertBefore and replaceChild
|
|
975
1035
|
*/
|
|
976
1036
|
function invokePrototypeMethod(app, rawMethod, parent, targetChild, passiveChild) {
|
|
1037
|
+
const container = getContainer(parent, app);
|
|
977
1038
|
/**
|
|
978
1039
|
* If passiveChild is not the child node, insertBefore replaceChild will have a problem, at this time, it will be degraded to appendChild
|
|
979
1040
|
* E.g: document.head.insertBefore(targetChild, document.head.childNodes[0])
|
|
980
1041
|
*/
|
|
981
|
-
if (
|
|
982
|
-
const microAppHead = app.container.querySelector('micro-app-head');
|
|
1042
|
+
if (container) {
|
|
983
1043
|
/**
|
|
984
1044
|
* 1. If passiveChild exists, it must be insertBefore or replaceChild
|
|
985
1045
|
* 2. When removeChild, targetChild may not be in microAppHead or head
|
|
986
1046
|
*/
|
|
987
|
-
if (passiveChild && !
|
|
988
|
-
return globalEnv.rawAppendChild.call(
|
|
1047
|
+
if (passiveChild && !container.contains(passiveChild)) {
|
|
1048
|
+
return globalEnv.rawAppendChild.call(container, targetChild);
|
|
989
1049
|
}
|
|
990
|
-
else if (rawMethod === globalEnv.rawRemoveChild && !
|
|
1050
|
+
else if (rawMethod === globalEnv.rawRemoveChild && !container.contains(targetChild)) {
|
|
991
1051
|
if (parent.contains(targetChild)) {
|
|
992
1052
|
return rawMethod.call(parent, targetChild);
|
|
993
1053
|
}
|
|
994
1054
|
return targetChild;
|
|
995
1055
|
}
|
|
996
|
-
|
|
997
|
-
return rawMethod.call(microAppHead, targetChild);
|
|
998
|
-
}
|
|
999
|
-
return rawMethod.call(microAppHead, targetChild, passiveChild);
|
|
1056
|
+
return invokeRawMethod(rawMethod, container, targetChild, passiveChild);
|
|
1000
1057
|
}
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
}
|
|
1006
|
-
else if (rawMethod === globalEnv.rawRemoveChild && !microAppBody.contains(targetChild)) {
|
|
1007
|
-
if (parent.contains(targetChild)) {
|
|
1008
|
-
return rawMethod.call(parent, targetChild);
|
|
1009
|
-
}
|
|
1010
|
-
return targetChild;
|
|
1011
|
-
}
|
|
1012
|
-
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1013
|
-
return rawMethod.call(microAppBody, targetChild);
|
|
1014
|
-
}
|
|
1015
|
-
return rawMethod.call(microAppBody, targetChild, passiveChild);
|
|
1016
|
-
}
|
|
1017
|
-
else if (rawMethod === globalEnv.rawAppend || rawMethod === globalEnv.rawPrepend) {
|
|
1058
|
+
return invokeRawMethod(rawMethod, parent, targetChild, passiveChild);
|
|
1059
|
+
}
|
|
1060
|
+
function invokeRawMethod(rawMethod, parent, targetChild, passiveChild) {
|
|
1061
|
+
if (isPendMethod(rawMethod)) {
|
|
1018
1062
|
return rawMethod.call(parent, targetChild);
|
|
1019
1063
|
}
|
|
1020
1064
|
return rawMethod.call(parent, targetChild, passiveChild);
|
|
1021
1065
|
}
|
|
1066
|
+
function isPendMethod(method) {
|
|
1067
|
+
return method === globalEnv.rawAppend || method === globalEnv.rawPrepend;
|
|
1068
|
+
}
|
|
1069
|
+
function getContainer(node, app) {
|
|
1070
|
+
var _a, _b;
|
|
1071
|
+
if (node === document.head) {
|
|
1072
|
+
return (_a = app === null || app === void 0 ? void 0 : app.container) === null || _a === void 0 ? void 0 : _a.querySelector('micro-app-head');
|
|
1073
|
+
}
|
|
1074
|
+
if (node === document.body) {
|
|
1075
|
+
return (_b = app === null || app === void 0 ? void 0 : app.container) === null || _b === void 0 ? void 0 : _b.querySelector('micro-app-body');
|
|
1076
|
+
}
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1022
1079
|
// Get the map element
|
|
1023
1080
|
function getMappingNode(node) {
|
|
1024
1081
|
var _a;
|
|
@@ -1134,7 +1191,8 @@ function patchElementPrototypeMethods() {
|
|
|
1134
1191
|
*/
|
|
1135
1192
|
function markElement(element) {
|
|
1136
1193
|
const appName = getCurrentAppName();
|
|
1137
|
-
|
|
1194
|
+
if (appName)
|
|
1195
|
+
element.__MICRO_APP_NAME__ = appName;
|
|
1138
1196
|
return element;
|
|
1139
1197
|
}
|
|
1140
1198
|
// methods of document
|
|
@@ -1307,13 +1365,39 @@ function rejectMicroAppStyle() {
|
|
|
1307
1365
|
}
|
|
1308
1366
|
}
|
|
1309
1367
|
|
|
1368
|
+
// 管理 app 的单例
|
|
1369
|
+
class AppManager {
|
|
1370
|
+
constructor() {
|
|
1371
|
+
// Todo: appInstanceMap 由 AppManager 来创建,不再由 create_app 管理
|
|
1372
|
+
this.appInstanceMap = appInstanceMap;
|
|
1373
|
+
}
|
|
1374
|
+
static getInstance() {
|
|
1375
|
+
if (!this.instance) {
|
|
1376
|
+
this.instance = new AppManager();
|
|
1377
|
+
}
|
|
1378
|
+
return this.instance;
|
|
1379
|
+
}
|
|
1380
|
+
get(appName) {
|
|
1381
|
+
return this.appInstanceMap.get(appName);
|
|
1382
|
+
}
|
|
1383
|
+
set(appName, app) {
|
|
1384
|
+
this.appInstanceMap.set(appName, app);
|
|
1385
|
+
}
|
|
1386
|
+
getAll() {
|
|
1387
|
+
return Array.from(this.appInstanceMap.values());
|
|
1388
|
+
}
|
|
1389
|
+
clear() {
|
|
1390
|
+
this.appInstanceMap.clear();
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1310
1394
|
function unmountNestedApp() {
|
|
1311
1395
|
releaseUnmountOfNestedApp();
|
|
1312
|
-
|
|
1396
|
+
AppManager.getInstance().getAll().forEach(app => {
|
|
1313
1397
|
// @ts-ignore
|
|
1314
1398
|
app.container && getRootContainer(app.container).disconnectedCallback();
|
|
1315
1399
|
});
|
|
1316
|
-
!window.__MICRO_APP_UMD_MODE__ &&
|
|
1400
|
+
!window.__MICRO_APP_UMD_MODE__ && AppManager.getInstance().clear();
|
|
1317
1401
|
}
|
|
1318
1402
|
// if micro-app run in micro application, delete all next generation application when unmount event received
|
|
1319
1403
|
function listenUmountOfNestedApp() {
|
|
@@ -1435,11 +1519,14 @@ const globalScripts = new Map();
|
|
|
1435
1519
|
function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
1436
1520
|
let replaceComment = null;
|
|
1437
1521
|
let src = script.getAttribute('src');
|
|
1438
|
-
if (
|
|
1522
|
+
if (src) {
|
|
1523
|
+
src = CompletionPath(src, app.url);
|
|
1524
|
+
}
|
|
1525
|
+
if (script.hasAttribute('exclude') || checkExcludeUrl(src, app.name)) {
|
|
1439
1526
|
replaceComment = document.createComment('script element with exclude attribute removed by micro-app');
|
|
1440
1527
|
}
|
|
1441
1528
|
else if ((script.type && !['text/javascript', 'text/ecmascript', 'application/javascript', 'application/ecmascript', 'module'].includes(script.type)) ||
|
|
1442
|
-
script.hasAttribute('ignore')) {
|
|
1529
|
+
script.hasAttribute('ignore') || checkIgnoreUrl(src, app.name)) {
|
|
1443
1530
|
return null;
|
|
1444
1531
|
}
|
|
1445
1532
|
else if ((globalEnv.supportModuleScript && script.noModule) ||
|
|
@@ -1447,7 +1534,6 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1447
1534
|
replaceComment = document.createComment(`${script.noModule ? 'noModule' : 'module'} script ignored by micro-app`);
|
|
1448
1535
|
}
|
|
1449
1536
|
else if (src) { // remote script
|
|
1450
|
-
src = CompletionPath(src, app.url);
|
|
1451
1537
|
const info = {
|
|
1452
1538
|
code: '',
|
|
1453
1539
|
isExternal: true,
|
|
@@ -1497,6 +1583,46 @@ function extractScriptElement(script, parent, app, isDynamic = false) {
|
|
|
1497
1583
|
return parent.replaceChild(replaceComment, script);
|
|
1498
1584
|
}
|
|
1499
1585
|
}
|
|
1586
|
+
/**
|
|
1587
|
+
* get assets plugins
|
|
1588
|
+
* @param appName app name
|
|
1589
|
+
*/
|
|
1590
|
+
function getAssetsPlugins(appName) {
|
|
1591
|
+
var _a, _b, _c;
|
|
1592
|
+
const globalPlugins = ((_a = microApp.plugins) === null || _a === void 0 ? void 0 : _a.global) || [];
|
|
1593
|
+
const modulePlugins = ((_c = (_b = microApp.plugins) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[appName]) || [];
|
|
1594
|
+
return [...globalPlugins, ...modulePlugins];
|
|
1595
|
+
}
|
|
1596
|
+
/**
|
|
1597
|
+
* whether the url needs to be excluded
|
|
1598
|
+
* @param url css or js link
|
|
1599
|
+
* @param plugins microApp plugins
|
|
1600
|
+
*/
|
|
1601
|
+
function checkExcludeUrl(url, appName) {
|
|
1602
|
+
if (!url)
|
|
1603
|
+
return false;
|
|
1604
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1605
|
+
return plugins.some(plugin => {
|
|
1606
|
+
if (!plugin.excludeChecker)
|
|
1607
|
+
return false;
|
|
1608
|
+
return plugin.excludeChecker(url);
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* whether the url needs to be ignore
|
|
1613
|
+
* @param url css or js link
|
|
1614
|
+
* @param plugins microApp plugins
|
|
1615
|
+
*/
|
|
1616
|
+
function checkIgnoreUrl(url, appName) {
|
|
1617
|
+
if (!url)
|
|
1618
|
+
return false;
|
|
1619
|
+
const plugins = getAssetsPlugins(appName) || [];
|
|
1620
|
+
return plugins.some(plugin => {
|
|
1621
|
+
if (!plugin.ignoreChecker)
|
|
1622
|
+
return false;
|
|
1623
|
+
return plugin.ignoreChecker(url);
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1500
1626
|
/**
|
|
1501
1627
|
* Get remote resources of script
|
|
1502
1628
|
* @param wrapElement htmlDom
|
|
@@ -1605,7 +1731,7 @@ function execScripts(scriptList, app, initHook) {
|
|
|
1605
1731
|
function runScript(url, app, info, isDynamic, callback) {
|
|
1606
1732
|
var _a;
|
|
1607
1733
|
try {
|
|
1608
|
-
const code = bindScope(url, app, info.code, info
|
|
1734
|
+
const code = bindScope(url, app, info.code, info);
|
|
1609
1735
|
if (app.inline || info.module) {
|
|
1610
1736
|
const scriptElement = pureCreateElement('script');
|
|
1611
1737
|
runCode2InlineScript(url, code, info.module, scriptElement, callback);
|
|
@@ -1658,7 +1784,7 @@ function runDynamicRemoteScript(url, info, app, originScript) {
|
|
|
1658
1784
|
app.source.scripts.set(url, info);
|
|
1659
1785
|
info.isGlobal && globalScripts.set(url, code);
|
|
1660
1786
|
try {
|
|
1661
|
-
code = bindScope(url, app, code, info
|
|
1787
|
+
code = bindScope(url, app, code, info);
|
|
1662
1788
|
if (app.inline || info.module) {
|
|
1663
1789
|
runCode2InlineScript(url, code, info.module, replaceElement, dispatchScriptOnLoadEvent);
|
|
1664
1790
|
}
|
|
@@ -1714,13 +1840,13 @@ function runCode2Function(code, info) {
|
|
|
1714
1840
|
* @param url script address
|
|
1715
1841
|
* @param app app
|
|
1716
1842
|
* @param code code
|
|
1717
|
-
* @param
|
|
1843
|
+
* @param info source script info
|
|
1718
1844
|
*/
|
|
1719
|
-
function bindScope(url, app, code,
|
|
1845
|
+
function bindScope(url, app, code, info) {
|
|
1720
1846
|
if (isPlainObject(microApp.plugins)) {
|
|
1721
|
-
code = usePlugins(url, code, app.name, microApp.plugins);
|
|
1847
|
+
code = usePlugins(url, code, app.name, microApp.plugins, info);
|
|
1722
1848
|
}
|
|
1723
|
-
if (app.sandBox && !module) {
|
|
1849
|
+
if (app.sandBox && !info.module) {
|
|
1724
1850
|
globalEnv.rawWindow.__MICRO_APP_PROXY_WINDOW__ = app.sandBox.proxyWindow;
|
|
1725
1851
|
return `;(function(proxyWindow){with(proxyWindow.__MICRO_APP_WINDOW__){(function(${globalKeyToBeCached}){;${code}\n}).call(proxyWindow,${globalKeyToBeCached})}})(window.__MICRO_APP_PROXY_WINDOW__);`;
|
|
1726
1852
|
}
|
|
@@ -1732,19 +1858,20 @@ function bindScope(url, app, code, module) {
|
|
|
1732
1858
|
* @param code code
|
|
1733
1859
|
* @param appName app name
|
|
1734
1860
|
* @param plugins plugin list
|
|
1861
|
+
* @param info source script info
|
|
1735
1862
|
*/
|
|
1736
|
-
function usePlugins(url, code, appName, plugins) {
|
|
1863
|
+
function usePlugins(url, code, appName, plugins, info) {
|
|
1737
1864
|
var _a;
|
|
1738
|
-
const newCode = processCode(plugins.global, code, url);
|
|
1739
|
-
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode, url);
|
|
1865
|
+
const newCode = processCode(plugins.global, code, url, info);
|
|
1866
|
+
return processCode((_a = plugins.modules) === null || _a === void 0 ? void 0 : _a[appName], newCode, url, info);
|
|
1740
1867
|
}
|
|
1741
|
-
function processCode(configs, code, url) {
|
|
1868
|
+
function processCode(configs, code, url, info) {
|
|
1742
1869
|
if (!isArray(configs)) {
|
|
1743
1870
|
return code;
|
|
1744
1871
|
}
|
|
1745
1872
|
return configs.reduce((preCode, config) => {
|
|
1746
1873
|
if (isPlainObject(config) && isFunction(config.loader)) {
|
|
1747
|
-
return config.loader(preCode, url, config.options);
|
|
1874
|
+
return config.loader(preCode, url, config.options, info);
|
|
1748
1875
|
}
|
|
1749
1876
|
return preCode;
|
|
1750
1877
|
}, code);
|
|
@@ -1772,10 +1899,10 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1772
1899
|
});
|
|
1773
1900
|
for (const dom of children) {
|
|
1774
1901
|
if (dom instanceof HTMLLinkElement) {
|
|
1775
|
-
if (dom.hasAttribute('exclude')) {
|
|
1902
|
+
if (dom.hasAttribute('exclude') || checkExcludeUrl(dom.getAttribute('href'), app.name)) {
|
|
1776
1903
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
1777
1904
|
}
|
|
1778
|
-
else if (!dom.hasAttribute('ignore')) {
|
|
1905
|
+
else if (!(dom.hasAttribute('ignore') || checkIgnoreUrl(dom.getAttribute('href'), app.name))) {
|
|
1779
1906
|
extractLinkFromHtml(dom, parent, app);
|
|
1780
1907
|
}
|
|
1781
1908
|
else if (dom.hasAttribute('href')) {
|
|
@@ -1829,34 +1956,6 @@ function extractSourceDom(htmlStr, app) {
|
|
|
1829
1956
|
app.onLoad(wrapElement);
|
|
1830
1957
|
}
|
|
1831
1958
|
}
|
|
1832
|
-
/**
|
|
1833
|
-
* Get and format html
|
|
1834
|
-
* @param app app
|
|
1835
|
-
*/
|
|
1836
|
-
function extractHtml(app) {
|
|
1837
|
-
fetchSource(app.ssrUrl || app.url, app.name, { cache: 'no-cache' }).then((htmlStr) => {
|
|
1838
|
-
if (!htmlStr) {
|
|
1839
|
-
const msg = 'html is empty, please check in detail';
|
|
1840
|
-
app.onerror(new Error(msg));
|
|
1841
|
-
return logError(msg, app.name);
|
|
1842
|
-
}
|
|
1843
|
-
htmlStr = htmlStr
|
|
1844
|
-
.replace(/<head[^>]*>[\s\S]*?<\/head>/i, (match) => {
|
|
1845
|
-
return match
|
|
1846
|
-
.replace(/<head/i, '<micro-app-head')
|
|
1847
|
-
.replace(/<\/head>/i, '</micro-app-head>');
|
|
1848
|
-
})
|
|
1849
|
-
.replace(/<body[^>]*>[\s\S]*?<\/body>/i, (match) => {
|
|
1850
|
-
return match
|
|
1851
|
-
.replace(/<body/i, '<micro-app-body')
|
|
1852
|
-
.replace(/<\/body>/i, '</micro-app-body>');
|
|
1853
|
-
});
|
|
1854
|
-
extractSourceDom(htmlStr, app);
|
|
1855
|
-
}).catch((e) => {
|
|
1856
|
-
logError(`Failed to fetch data from ${app.url}, micro-app stop rendering`, app.name, e);
|
|
1857
|
-
app.onLoadError(e);
|
|
1858
|
-
});
|
|
1859
|
-
}
|
|
1860
1959
|
|
|
1861
1960
|
class EventCenter {
|
|
1862
1961
|
constructor() {
|
|
@@ -2822,7 +2921,7 @@ class CreateApp {
|
|
|
2822
2921
|
// Load resources
|
|
2823
2922
|
loadSourceCode() {
|
|
2824
2923
|
this.state = appStates.LOADING_SOURCE_CODE;
|
|
2825
|
-
|
|
2924
|
+
HTMLLoader.getInstance().run(this, extractSourceDom);
|
|
2826
2925
|
}
|
|
2827
2926
|
/**
|
|
2828
2927
|
* When resource is loaded, mount app if it is not prefetch or unmount
|
|
@@ -3503,6 +3602,7 @@ function getGlobalAssets(assets) {
|
|
|
3503
3602
|
});
|
|
3504
3603
|
}
|
|
3505
3604
|
}
|
|
3605
|
+
// TODO: requestIdleCallback for every file
|
|
3506
3606
|
function fetchGlobalResources(resources, suffix, cache) {
|
|
3507
3607
|
if (isArray(resources)) {
|
|
3508
3608
|
const effectiveResource = resources.filter((path) => isString(path) && path.includes(`.${suffix}`) && !cache.has(path));
|