The Master package for the microup platform is the entry to the Micro-frontends code.
npm install @microup/mastermaster 包主要负责状态数据的存储,权限校验与重定向、顶层路由处理、多语言等工作。所有的 remote 模块都会经过 master 代码控制然后渲染。
> 目前未添加权限,多语言模块,如有需要可自行在master添加。
全局的事件触发,通用数据也都可以添加到 master 内,并且这些数据共享,可完成不同模块间数据通信。
masterStore 是通过 mobx 进行实现的状态数据池,它可以存储一些全局动态的状态数据,并且在所有 remote 模块中都可以访问到这些数据。
源码
masterStore 的核心代码如下,用于注册一个 Store
``tsx
import React from 'react';
import {observer, useLocalObservable} from 'mobx-react';
import {runInAction} from 'mobx';
import { Provider } from 'mobx-react';
interface IIssue {
// data
}
const useMainLocalStore = () => {
const masterStore = useLocalObservable(() => ({
data: {} as IIssue,
get(key: string) {
return masterStore.data[key]
},
set(key, value) {
runInAction(function () {
masterStore.data[key] = value
})
}
}));
return masterStore;
};
const MasterStoreProvider: React.FC
const {children} = props;
const masterStore = useMainLocalStore();
return
});
export {MasterStoreProvider};
`
包裹跟节点
`jsx
import React from 'react';
……
import {MasterStoreProvider} from './store';
……
const InnerIndex = (props) => {
const {match, AutoRouter} = props
return (
……
)
};
export default withRouter(InnerIndex);
`
使用
可以实现不同 remote 模块间数据通信,也可以使得一个模块触发另一个模块的视图渲染。
测试案例如下:
开启一个 app1 服务作为 host 模块,它可以以一下两种方式访问 remote 模块,一种访问其中 remote 模块注册的一个组件,第二种访问整个的 remote 模块,详情也可查看 app1 与 app2 包的代码。
app1 作为 host 模块
`jsx
import React from 'react';
import {ExternalComponent} from '@microup/utils';
import {inject, observer} from 'mobx-react';
export default inject('masterStore')(observer((props) => {
const {history, masterStore} = props
return (
app2 externalize 组件
`jsx
import React from 'react';
import {observer,inject} from 'mobx-react';export default inject('masterStore')(observer(({match, masterStore}) => {
return (
app2-externalize-components | app2Test: {String(!!masterStore.get('app2Test'))});
}))
/ externalize: App2EC /
`app2 根目录
`jsx
import React from 'react';
import {Route, Switch} from 'react-router-dom';
import {inject} from 'mobx-react';
import {ErrorPage} from '@microup/master';const Page1 = React.lazy(() => import('./routes/Page1'));
const Page2 = React.lazy(() => import('./routes/Page2'));
function Index({match, masterStore}) {
return (
${match.url}/page1} component={Page1}/>
${match.url}/page2} component={Page2}/>
${match.url}} component={Page1}/>
);
}
export default inject('masterStore')(Index);
`app2 page1
`jsx
import React from 'react';
import {inject, observer} from 'mobx-react';export default inject('masterStore')(observer((props) => {
const {match, masterStore} = props
return (
app2 page1 | app2Test: {String(!!masterStore.get('app2Test'))}
)
}));
`master router
moaster router 控制这整个项目的跟路由,路由优先判断是否是
/error_page或者/undefined进行全局的错误路由拦截,过滤后的路由会转入 AutoRouter,在 AutoRouter 组件中会处理一级路由并分发到对应 remote 模块master.jsx
`jsx
const InnerIndex = (props) => {
const {match, AutoRouter} = props
return (
${match.url}${match.url === '/' ? '' : '/'}error_page} component={ErrorPage}/>
${match.url}${match.url === '/' ? '' : '/'}undefined} component={Empty}/>
)
};
`> AutoRouter 组件位置在 routes.nunjucks.jsx 编译后在 tmp 目录中的 router.index.js 中,tmp 详情参考 boot 包文档。
一级路由处理
在 AutoRouter 中执行了这样代码,其作用是优先匹配 config.js 中设置的 routes 中的路由,如果匹配成功,则访问本地路由组件。
> routes 作用是一级路由与对应组件位置的描述
>
>
`bash
> # 只是本地开发
> routes: {
> a1: './src/exampleMaster/App1', # 路由为 http://192.168.20.133:9091/#/a1/
> a2: './src/exampleMaster/App2' # 路由为 http://192.168.20.133:9091/#/a2/
> }
> `
>`html
const AutoRouter = () => (
}>
{'{{ routes }}'}
);
`如果没有匹配成功,则执行
组件,匹配对应 remote 模块。
组件中,根据.env中配置的STATIC_URL作为基地址,后边拼接 url 地址中的一级路由与/importManifest.js生成一个新的地址,类似http://192.168.20.101:9095/a1/importManifest.js。然后创建一个新的
script标签src 填入上边生成的地址。远程拉取 importManifest.js 代码,实现 remote 模块间连接。(实现方案详情参考动态远程容器)> 通常我们会有很多 remote 模块,在 host 模块访问多个 remote 模块时,我们不想在代码中把所有地址都写出来( 类似 STATIC_URL-a1,STATIC_URL-a2 这样,会比较麻烦)。这时我可以创建一个独立的 nginx 帮我们代理。
>
> 例如所有模块都访问
http://192.168.20.101:9095/a1/importManifest.js ,而 192.168.20.133:9095 中设置 nginx 做对应的反向代理
>
> `
> # STATIC_URL 对应的 nginx
> location /a1/ { # app1 remote 模块
> proxy_pass http://192.168.20.101:9091/;
> }
> location /a2/ { # app2 remote 模块
> proxy_pass http://192.168.20.123:9092/;
> }
> `
>
> 这样我们访问 http://192.168.20.101:9095/a1/importManifest.js 他会根据一级路由 a1 判断访问 http://192.168.20.101:9091/a1/importManifest.js` 然后拿到 js 静态文件做对应渲染。##