准备阅读
本文对前端基础有一定要求,推荐先熟读以下文章
一、Usage Example
1.1 app1 的组件定义
// 依赖略去
export default inject('AppState')((props) => {
const { AppState: { currentLanguage: language } } = props;
const IntlProviderAsync = useMemo(() => asyncLocaleProvider(language, () => import(`../../locale/${language}`)), []);
return (
<IntlProviderAsync>
<StoreProvider {...props}>
<ModalProvider>
<MainView />
</ModalProvider>
</StoreProvider>
</IntlProviderAsync>
);
});
/* externalize: PageDesigner */
1.2 app2 的组件使用
<ExternalComponent
system={{
scope: 'lc',
module: 'PageDesigner',
}}
modelId={tableObjectId}
viewId={variableViewId}
variableFlag
/>
二、Key Code
1.loadComponent.js
import React from 'react';
function loadComponent(scope, module, onError) {
return async () => {
// Initializes the share scope. This fills it with known provided modules from this build and all remotes
await __webpack_init_sharing__('default');
const container = window[scope]; // or get the container somewhere else
// Initialize the container, it may provide shared modules
if (!container) {
throw new Error('加载了错误的importManifest.js,请检查服务版本');
}
try {
await container.init(__webpack_share_scopes__.default);
const factory = await window[scope].get(module);
const Module = factory();
return Module;
} catch (e) {
if (onError) {
return onError(e);
}
throw e;
}
};
}
export default loadComponent;
2. ExternalComponent.js
/* eslint-disable no-underscore-dangle */
import React from 'react';
import { loadComponent, useManifest } from './LoadComponent.js';
import Loading from '../loading';
const cache = new Map();
function getComponent({ scope, module }, ErrorComponent = null) {
const scopeItem = cache.get(scope) || new Map();
cache.set(scope, scopeItem);
const component = scopeItem.get(module);
if (component) {
return component;
}
const lazyComponent = React.lazy(
loadComponent(scope, module, (error) => {
console.error(error);
return {
default: () => ErrorComponent,
};
}),
);
scopeItem.set(module, lazyComponent);
return lazyComponent;
}
function ExternalComponent(props) {
const { system, NotFound = Loading, ErrorComponent } = props;
const { ready, failed } = useManifest(system);
if (!props.system) {
return <h2>Not system specified</h2>;
}
if (failed) {
return <NotFound />;
}
if (!ready) {
return <Loading />;
}
const Component = getComponent(system, ErrorComponent);
return (
<React.Suspense fallback={<Loading />}>
<Component {...props} />
</React.Suspense>
);
}
export default ExternalComponent;
三、如何实现
以下是封装的前端框架源码解读,本着学习的心态对核心点画圈圈;主要实现用注释标注的方式,实现跨应用组件加载
- 文件io读取
- 正则匹配
- 动态构建federation配置
3.1 代码简化对比
federation核心属性
- name
- library
- exposes/ remotes
- shared