@micro-zoe/micro-app 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -58
- package/README.zh-cn.md +11 -56
- package/lib/index.d.ts +5 -3
- package/lib/index.esm.js +28 -16
- 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 +1 -1
package/README.md
CHANGED
|
@@ -30,22 +30,22 @@ English|[简体中文](./README.zh-cn.md)|[Documentation](https://micro-zoe.
|
|
|
30
30
|
# 📖Introduction
|
|
31
31
|
micro-app is a micro front-end framework launched by JD Retail. It renders based on webcomponent-like and realizes the micro front-end from component thinking, it aiming to reduce the difficulty of getting started and improve work efficiency.
|
|
32
32
|
|
|
33
|
-
It is the lowest cost framework for accessing micro front-end,
|
|
33
|
+
It is the lowest cost framework for accessing micro front-end, and provides a series of perfect functions such as JS sandbox, style isolation, element isolation, preloading, resource address completion, plugin system, data communication and so on.
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
micro-app has no restrictions on the front-end framework, and any framework can be used as a base application to embed any type of micro application of the framework.
|
|
36
36
|
|
|
37
|
-
#
|
|
38
|
-
The micro front
|
|
37
|
+
# How to use
|
|
38
|
+
The micro front end is divided into a base application (also called main application) and a micro application.
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
> The base application takes the vue framework as an example
|
|
40
|
+
Here is a common example: the base application uses the Vue framework, uses history routing, the micro application uses the react framework, and uses hash routing. We list the modifications that need to be made by the base application and the micro application, and introduce the use of micro-app in detail.
|
|
42
41
|
|
|
43
|
-
|
|
42
|
+
## base application
|
|
43
|
+
**1、Install**
|
|
44
44
|
```bash
|
|
45
45
|
yarn add @micro-zoe/micro-app
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
2、import at the entrance
|
|
48
|
+
**2、import at the entrance**
|
|
49
49
|
```js
|
|
50
50
|
// main.js
|
|
51
51
|
import microApp from '@micro-zoe/micro-app'
|
|
@@ -53,63 +53,20 @@ import microApp from '@micro-zoe/micro-app'
|
|
|
53
53
|
microApp.start()
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
3、
|
|
57
|
-
```js
|
|
58
|
-
// router.js
|
|
59
|
-
import Vue from 'vue'
|
|
60
|
-
import VueRouter from 'vue-router' // vue-router@3.x
|
|
61
|
-
import MyPage from './my-page.vue'
|
|
62
|
-
|
|
63
|
-
Vue.use(VueRouter)
|
|
64
|
-
|
|
65
|
-
const routes = [
|
|
66
|
-
{
|
|
67
|
-
// 👇 Non-strict matching, /my-page/xxx will be matched to the MyPage component
|
|
68
|
-
path: '/my-page/*',
|
|
69
|
-
name: 'my-page',
|
|
70
|
-
component: MyPage,
|
|
71
|
-
},
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
export default routes
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
4、Use components in `my-page` pages
|
|
56
|
+
**3、Use components in page**
|
|
78
57
|
```html
|
|
79
58
|
<!-- my-page.vue -->
|
|
80
59
|
<template>
|
|
81
60
|
<div>
|
|
82
61
|
<h1>micro application</h1>
|
|
83
|
-
<!-- 👇 name is the application name,
|
|
84
|
-
<micro-app name='app1' url='http://localhost:3000/'
|
|
62
|
+
<!-- 👇 name is the application name, url is the html address -->
|
|
63
|
+
<micro-app name='app1' url='http://localhost:3000/'></micro-app>
|
|
85
64
|
</div>
|
|
86
65
|
</template>
|
|
87
66
|
```
|
|
88
67
|
|
|
89
|
-
> Please refer to [Routing Chapter](https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/route) for the relationship between url and micro application routing
|
|
90
|
-
|
|
91
68
|
## micro application
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
1、Add basename for route(If the base application is history route and the micro application is hash route, it is not necessary to set the baseroute, this step can be skipped)
|
|
95
|
-
|
|
96
|
-
```js
|
|
97
|
-
// router.js
|
|
98
|
-
import { BrowserRouter, Switch, Route } from 'react-router-dom'
|
|
99
|
-
|
|
100
|
-
export default function AppRoute () {
|
|
101
|
-
return (
|
|
102
|
-
// 👇 the micro application can get the baseroute issued by the base application through window.__MICRO_APP_BASE_ROUTE__
|
|
103
|
-
<BrowserRouter basename={window.__MICRO_APP_BASE_ROUTE__ || '/'}>
|
|
104
|
-
<Switch>
|
|
105
|
-
...
|
|
106
|
-
</Switch>
|
|
107
|
-
</BrowserRouter>
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
2、Set cross-domain support in the headers of webpack-dev-server.
|
|
69
|
+
**Set cross-domain support in the headers of webpack-dev-server**
|
|
113
70
|
```js
|
|
114
71
|
devServer: {
|
|
115
72
|
headers: {
|
|
@@ -118,12 +75,10 @@ devServer: {
|
|
|
118
75
|
},
|
|
119
76
|
```
|
|
120
77
|
|
|
121
|
-
|
|
78
|
+
The above micro front-end rendering is completed, and the effect is as follows:
|
|
122
79
|
|
|
123
80
|

|
|
124
81
|
|
|
125
|
-
The above lists the usage of react and Vue framework. They can be combined freely. For example, the base application is react, the micro application is Vue, or the base application is Vue, the micro application is react, or both the base application and the micro application are react and Vue. The micro-app has no restrictions on the front-end framework, and any framework can be used as a base application to embed any type of micro application of the framework.
|
|
126
|
-
|
|
127
82
|
More detailed configuration can be viewed [Documentation](https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/start).
|
|
128
83
|
|
|
129
84
|
# 🤝 Contribution
|
package/README.zh-cn.md
CHANGED
|
@@ -28,24 +28,23 @@
|
|
|
28
28
|
[English](https://github.com/micro-zoe/micro-app)|简体中文|[官网文档](https://micro-zoe.github.io/micro-app/)|[讨论组](https://github.com/micro-zoe/micro-app/discussions)|[Gitter群聊](https://gitter.im/microzoe/micro-app)
|
|
29
29
|
|
|
30
30
|
# 📖简介
|
|
31
|
-
micro-app是京东零售推出的一款微前端框架,它基于类WebComponent
|
|
31
|
+
micro-app是京东零售推出的一款微前端框架,它基于类WebComponent进行渲染,从组件化的思维实现微前端,旨在降低上手难度、提升工作效率。它是目前接入微前端成本最低的框架,并且提供了JS沙箱、样式隔离、元素隔离、预加载、资源地址补全、插件系统、数据通信等一系列完善的功能。
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
micro-app与技术栈无关,对前端框架没有限制,任何框架都可以作为基座应用嵌入任何类型的子应用。
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
# 如何使用
|
|
36
|
+
微前端分为基座应用(也可以叫做主应用)和子应用。
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
微前端分为基座应用和子应用,我们分别列出基座应用和子应用需要进行的修改,具体介绍micro-app的使用方式。
|
|
38
|
+
这里以一种比较常见的情况举例:基座应用使用vue框架,采用history路由,子应用使用react框架,采用hash路由,我们分别列出基座应用和子应用需要进行的修改,具体介绍micro-app的使用方式。
|
|
39
39
|
|
|
40
40
|
## 基座应用
|
|
41
|
-
> 基座应用以vue框架为例
|
|
42
41
|
|
|
43
|
-
1
|
|
42
|
+
**1、安装依赖**
|
|
44
43
|
```bash
|
|
45
44
|
yarn add @micro-zoe/micro-app
|
|
46
45
|
```
|
|
47
46
|
|
|
48
|
-
2
|
|
47
|
+
**2、在入口处引入依赖**
|
|
49
48
|
```js
|
|
50
49
|
// main.js
|
|
51
50
|
import microApp from '@micro-zoe/micro-app'
|
|
@@ -53,63 +52,21 @@ import microApp from '@micro-zoe/micro-app'
|
|
|
53
52
|
microApp.start()
|
|
54
53
|
```
|
|
55
54
|
|
|
56
|
-
3
|
|
57
|
-
```js
|
|
58
|
-
// router.js
|
|
59
|
-
import Vue from 'vue'
|
|
60
|
-
import VueRouter from 'vue-router' // vue-router@3.x
|
|
61
|
-
import MyPage from './my-page.vue'
|
|
62
|
-
|
|
63
|
-
Vue.use(VueRouter)
|
|
64
|
-
|
|
65
|
-
const routes = [
|
|
66
|
-
{
|
|
67
|
-
// 👇 非严格匹配,/my-page/xxx 都将匹配到 MyPage 页面
|
|
68
|
-
path: '/my-page/*',
|
|
69
|
-
name: 'my-page',
|
|
70
|
-
component: MyPage,
|
|
71
|
-
},
|
|
72
|
-
]
|
|
73
|
-
|
|
74
|
-
export default routes
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
4、在`MyPage`页面中嵌入微前端应用
|
|
55
|
+
**3、在页面中嵌入微前端应用**
|
|
78
56
|
```html
|
|
79
57
|
<!-- my-page.vue -->
|
|
80
58
|
<template>
|
|
81
59
|
<div>
|
|
82
60
|
<h1>子应用</h1>
|
|
83
61
|
<!-- 👇 name为应用名称,url为html地址 -->
|
|
84
|
-
<micro-app name='app1' url='http://localhost:3000/'
|
|
62
|
+
<micro-app name='app1' url='http://localhost:3000/'></micro-app>
|
|
85
63
|
</div>
|
|
86
64
|
</template>
|
|
87
65
|
```
|
|
88
66
|
|
|
89
|
-
> url和子应用路由的关系请查看[路由一章](https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/route)
|
|
90
|
-
|
|
91
67
|
## 子应用
|
|
92
|
-
> 子应用以react框架为例
|
|
93
|
-
|
|
94
|
-
1、设置基础路由(如果基座应用是history路由,子应用是hash路由,不需要设置基础路由,这一步可以省略)
|
|
95
68
|
|
|
96
|
-
|
|
97
|
-
// router.js
|
|
98
|
-
import { BrowserRouter, Switch, Route } from 'react-router-dom'
|
|
99
|
-
|
|
100
|
-
export default function AppRoute () {
|
|
101
|
-
return (
|
|
102
|
-
// 👇 设置基础路由,子应用可以通过window.__MICRO_APP_BASE_ROUTE__获取基座应用下发的baseroute
|
|
103
|
-
<BrowserRouter basename={window.__MICRO_APP_BASE_ROUTE__ || '/'}>
|
|
104
|
-
<Switch>
|
|
105
|
-
...
|
|
106
|
-
</Switch>
|
|
107
|
-
</BrowserRouter>
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
2、在webpack-dev-server的headers中设置跨域支持。
|
|
69
|
+
**在webpack-dev-server的headers中设置跨域支持。**
|
|
113
70
|
```js
|
|
114
71
|
devServer: {
|
|
115
72
|
headers: {
|
|
@@ -118,12 +75,10 @@ devServer: {
|
|
|
118
75
|
},
|
|
119
76
|
```
|
|
120
77
|
|
|
121
|
-
|
|
78
|
+
以上微前端基本渲染完成,效果如下:
|
|
122
79
|
|
|
123
80
|
<img src="https://img12.360buyimg.com/imagetools/jfs/t1/196940/34/1541/38365/610a14fcE46c21374/c321b9f8fa50a8fc.png" alt="result" width='900'/>
|
|
124
81
|
|
|
125
|
-
上面列出了react和vue框架的使用方式,它们是可以自由组合的,比如基座应用是react,子应用是vue,或者基座应用是vue,子应用是react,或者基座应用和子应用都是react、vue。 micro-app对前端框架没有限制,任何框架都可以作为基座应用嵌入任何类型框架的子应用。
|
|
126
|
-
|
|
127
82
|
更多详细配置可以查看[官网文档](https://micro-zoe.github.io/micro-app/docs.html#/zh-cn/start)
|
|
128
83
|
|
|
129
84
|
# 🤝 参与共建
|
package/lib/index.d.ts
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
declare module '@micro-zoe/micro-app' {
|
|
7
7
|
export { default } from '@micro-zoe/micro-app/micro_app';
|
|
8
|
-
export { default as preFetch } from '@micro-zoe/micro-app/prefetch';
|
|
9
|
-
export { removeDomScope, pureCreateElement, version } from '@micro-zoe/micro-app/libs/utils';
|
|
10
|
-
export { EventCenterForMicroApp } from '@micro-zoe/micro-app/interact';
|
|
8
|
+
export { default as preFetch, } from '@micro-zoe/micro-app/prefetch';
|
|
9
|
+
export { removeDomScope, pureCreateElement, version, } from '@micro-zoe/micro-app/libs/utils';
|
|
10
|
+
export { EventCenterForMicroApp, } from '@micro-zoe/micro-app/interact';
|
|
11
|
+
export { getActiveApps, // version >= 0.5.1
|
|
12
|
+
getAllApps, } from './create_app';
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
declare module '@micro-zoe/micro-app/micro_app' {
|
package/lib/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const version = '0.5.
|
|
1
|
+
const version = '0.5.1';
|
|
2
2
|
// do not use isUndefined
|
|
3
3
|
const isBrowser = typeof window !== 'undefined';
|
|
4
4
|
// do not use isUndefined
|
|
@@ -625,7 +625,7 @@ const globalLinks = new Map();
|
|
|
625
625
|
* @param microAppHead micro-app-head element
|
|
626
626
|
* @param isDynamic dynamic insert
|
|
627
627
|
*/
|
|
628
|
-
function extractLinkFromHtml(link, parent, app,
|
|
628
|
+
function extractLinkFromHtml(link, parent, app, isDynamic = false) {
|
|
629
629
|
const rel = link.getAttribute('rel');
|
|
630
630
|
let href = link.getAttribute('href');
|
|
631
631
|
let replaceComment = null;
|
|
@@ -633,12 +633,9 @@ function extractLinkFromHtml(link, parent, app, microAppHead, isDynamic = false)
|
|
|
633
633
|
href = CompletionPath(href, app.url);
|
|
634
634
|
if (!isDynamic) {
|
|
635
635
|
replaceComment = document.createComment(`link element with href=${href} move to micro-app-head as style element`);
|
|
636
|
-
const placeholderComment = document.createComment(`placeholder for link with href=${href}`);
|
|
637
|
-
// all style elements insert into microAppHead
|
|
638
|
-
microAppHead.appendChild(placeholderComment);
|
|
639
636
|
app.source.links.set(href, {
|
|
640
637
|
code: '',
|
|
641
|
-
placeholder:
|
|
638
|
+
placeholder: replaceComment,
|
|
642
639
|
isGlobal: link.hasAttribute('global'),
|
|
643
640
|
});
|
|
644
641
|
}
|
|
@@ -653,7 +650,7 @@ function extractLinkFromHtml(link, parent, app, microAppHead, isDynamic = false)
|
|
|
653
650
|
}
|
|
654
651
|
}
|
|
655
652
|
else if (rel && ['prefetch', 'preload', 'prerender', 'icon', 'apple-touch-icon'].includes(rel)) {
|
|
656
|
-
// preload prefetch
|
|
653
|
+
// preload prefetch icon ....
|
|
657
654
|
if (isDynamic) {
|
|
658
655
|
replaceComment = document.createComment(`link element with rel=${rel}${href ? ' & href=' + href : ''} removed by micro-app`);
|
|
659
656
|
}
|
|
@@ -708,6 +705,7 @@ function fetchLinkSuccess(url, info, data, microAppHead, app) {
|
|
|
708
705
|
const styleLink = pureCreateElement('style');
|
|
709
706
|
styleLink.textContent = data;
|
|
710
707
|
styleLink.__MICRO_APP_LINK_PATH__ = url;
|
|
708
|
+
styleLink.setAttribute('data-origin-href', url);
|
|
711
709
|
microAppHead.replaceChild(scopedCSS(styleLink, app), info.placeholder);
|
|
712
710
|
info.placeholder = null;
|
|
713
711
|
info.code = data;
|
|
@@ -1012,9 +1010,6 @@ function runCode2InlineScript(url, code, module, scriptElement, callback) {
|
|
|
1012
1010
|
const blob = new Blob([code], { type: 'text/javascript' });
|
|
1013
1011
|
scriptElement.src = URL.createObjectURL(blob);
|
|
1014
1012
|
scriptElement.setAttribute('type', 'module');
|
|
1015
|
-
if (!url.startsWith('inline-')) {
|
|
1016
|
-
scriptElement.setAttribute('originSrc', url);
|
|
1017
|
-
}
|
|
1018
1013
|
if (callback) {
|
|
1019
1014
|
callback.moduleCount && callback.moduleCount--;
|
|
1020
1015
|
scriptElement.onload = callback.bind(scriptElement, callback.moduleCount === 0);
|
|
@@ -1023,6 +1018,9 @@ function runCode2InlineScript(url, code, module, scriptElement, callback) {
|
|
|
1023
1018
|
else {
|
|
1024
1019
|
scriptElement.textContent = code;
|
|
1025
1020
|
}
|
|
1021
|
+
if (!url.startsWith('inline-')) {
|
|
1022
|
+
scriptElement.setAttribute('data-origin-src', url);
|
|
1023
|
+
}
|
|
1026
1024
|
}
|
|
1027
1025
|
// init & run code2Function
|
|
1028
1026
|
function runCode2Function(code, info) {
|
|
@@ -1092,7 +1090,7 @@ function getWrapElement(str) {
|
|
|
1092
1090
|
function flatChildren(parent, app, microAppHead) {
|
|
1093
1091
|
const children = Array.from(parent.children);
|
|
1094
1092
|
children.length && children.forEach((child) => {
|
|
1095
|
-
flatChildren(child, app
|
|
1093
|
+
flatChildren(child, app);
|
|
1096
1094
|
});
|
|
1097
1095
|
for (const dom of children) {
|
|
1098
1096
|
if (dom instanceof HTMLLinkElement) {
|
|
@@ -1100,7 +1098,7 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1100
1098
|
parent.replaceChild(document.createComment('link element with exclude attribute ignored by micro-app'), dom);
|
|
1101
1099
|
}
|
|
1102
1100
|
else if (!dom.hasAttribute('ignore')) {
|
|
1103
|
-
extractLinkFromHtml(dom, parent, app
|
|
1101
|
+
extractLinkFromHtml(dom, parent, app);
|
|
1104
1102
|
}
|
|
1105
1103
|
else if (dom.hasAttribute('href')) {
|
|
1106
1104
|
dom.setAttribute('href', CompletionPath(dom.getAttribute('href'), app.url));
|
|
@@ -1111,7 +1109,7 @@ function flatChildren(parent, app, microAppHead) {
|
|
|
1111
1109
|
parent.replaceChild(document.createComment('style element with exclude attribute ignored by micro-app'), dom);
|
|
1112
1110
|
}
|
|
1113
1111
|
else if (app.scopecss && !dom.hasAttribute('ignore')) {
|
|
1114
|
-
|
|
1112
|
+
scopedCSS(dom, app);
|
|
1115
1113
|
}
|
|
1116
1114
|
}
|
|
1117
1115
|
else if (dom instanceof HTMLScriptElement) {
|
|
@@ -1139,7 +1137,7 @@ function extractSourceDom(htmlStr, app) {
|
|
|
1139
1137
|
app.onerror(new Error(msg));
|
|
1140
1138
|
return logError(msg, app.name);
|
|
1141
1139
|
}
|
|
1142
|
-
flatChildren(wrapElement, app
|
|
1140
|
+
flatChildren(wrapElement, app);
|
|
1143
1141
|
if (app.source.links.size) {
|
|
1144
1142
|
fetchLinksFromHtml(wrapElement, app, microAppHead);
|
|
1145
1143
|
}
|
|
@@ -2315,6 +2313,20 @@ class CreateApp {
|
|
|
2315
2313
|
return {};
|
|
2316
2314
|
}
|
|
2317
2315
|
}
|
|
2316
|
+
// if app not prefetch & not unmount, then app is active
|
|
2317
|
+
function getActiveApps() {
|
|
2318
|
+
const activeApps = [];
|
|
2319
|
+
appInstanceMap.forEach((app, appName) => {
|
|
2320
|
+
if (appStatus.UNMOUNT !== app.getAppStatus() && !app.isPrefetch) {
|
|
2321
|
+
activeApps.push(appName);
|
|
2322
|
+
}
|
|
2323
|
+
});
|
|
2324
|
+
return activeApps;
|
|
2325
|
+
}
|
|
2326
|
+
// get all registered apps
|
|
2327
|
+
function getAllApps() {
|
|
2328
|
+
return Array.from(appInstanceMap.keys());
|
|
2329
|
+
}
|
|
2318
2330
|
|
|
2319
2331
|
// Record element and map element
|
|
2320
2332
|
const dynamicElementInMicroAppMap = new WeakMap();
|
|
@@ -2345,7 +2357,7 @@ function handleNewNode(parent, child, app) {
|
|
|
2345
2357
|
else if (child.hasAttribute('ignore')) {
|
|
2346
2358
|
return child;
|
|
2347
2359
|
}
|
|
2348
|
-
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app,
|
|
2360
|
+
const { url, info, replaceComment } = extractLinkFromHtml(child, parent, app, true);
|
|
2349
2361
|
if (url && info) {
|
|
2350
2362
|
const replaceStyle = pureCreateElement('style');
|
|
2351
2363
|
replaceStyle.__MICRO_APP_LINK_PATH__ = url;
|
|
@@ -3156,5 +3168,5 @@ class MicroApp extends EventCenterForBaseApp {
|
|
|
3156
3168
|
var microApp = new MicroApp();
|
|
3157
3169
|
|
|
3158
3170
|
export default microApp;
|
|
3159
|
-
export { EventCenterForMicroApp, preFetch, pureCreateElement, removeDomScope, version };
|
|
3171
|
+
export { EventCenterForMicroApp, getActiveApps, getAllApps, preFetch, pureCreateElement, removeDomScope, version };
|
|
3160
3172
|
//# sourceMappingURL=index.esm.js.map
|