@ice/mf-runtime 0.0.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 +15 -0
- package/es2017/FallBack.d.ts +62 -0
- package/es2017/FallBack.js +43 -0
- package/es2017/RemoteModule.d.ts +13 -0
- package/es2017/RemoteModule.js +63 -0
- package/es2017/index.d.ts +5 -0
- package/es2017/index.js +11 -0
- package/es2017/mf-global-store.d.ts +27 -0
- package/es2017/mf-global-store.js +66 -0
- package/es2017/runtime-plugin.d.ts +2 -0
- package/es2017/runtime-plugin.js +101 -0
- package/es2017/set-public-path.d.ts +2 -0
- package/es2017/set-public-path.js +28 -0
- package/es2017/types.d.ts +12 -0
- package/es2017/types.js +1 -0
- package/es2017/typings.d.ts +1 -0
- package/esm/FallBack.d.ts +62 -0
- package/esm/FallBack.js +87 -0
- package/esm/RemoteModule.d.ts +13 -0
- package/esm/RemoteModule.js +107 -0
- package/esm/index.d.ts +5 -0
- package/esm/index.js +11 -0
- package/esm/mf-global-store.d.ts +27 -0
- package/esm/mf-global-store.js +84 -0
- package/esm/runtime-plugin.d.ts +2 -0
- package/esm/runtime-plugin.js +215 -0
- package/esm/set-public-path.d.ts +2 -0
- package/esm/set-public-path.js +28 -0
- package/esm/types.d.ts +12 -0
- package/esm/types.js +1 -0
- package/esm/typings.d.ts +1 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface FallBackOptions {
|
|
3
|
+
Original: React.ComponentType<any>;
|
|
4
|
+
remoteVersion?: () => string;
|
|
5
|
+
hostVersion?: () => string;
|
|
6
|
+
remoteReactDOM: () => typeof import('react-dom');
|
|
7
|
+
remoteReact: () => typeof import('react');
|
|
8
|
+
}
|
|
9
|
+
export declare const FallBack: ({ Original, remoteReactDOM, remoteReact, }: FallBackOptions) => {
|
|
10
|
+
new (props: {}): {
|
|
11
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
12
|
+
componentDidMount(): void;
|
|
13
|
+
componentDidUpdate(): void;
|
|
14
|
+
componentWillUnmount(): void;
|
|
15
|
+
mountOriginalComponent(shouldRender?: boolean): void;
|
|
16
|
+
render(): React.JSX.Element;
|
|
17
|
+
context: unknown;
|
|
18
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K>) | Pick<{}, K>, callback?: () => void): void;
|
|
19
|
+
forceUpdate(callback?: () => void): void;
|
|
20
|
+
readonly props: Readonly<{}>;
|
|
21
|
+
state: Readonly<{}>;
|
|
22
|
+
refs: {
|
|
23
|
+
[key: string]: React.ReactInstance;
|
|
24
|
+
};
|
|
25
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
26
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
27
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
28
|
+
componentWillMount?(): void;
|
|
29
|
+
UNSAFE_componentWillMount?(): void;
|
|
30
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
31
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
32
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
33
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
34
|
+
};
|
|
35
|
+
new (props: {}, context: any): {
|
|
36
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
37
|
+
componentDidMount(): void;
|
|
38
|
+
componentDidUpdate(): void;
|
|
39
|
+
componentWillUnmount(): void;
|
|
40
|
+
mountOriginalComponent(shouldRender?: boolean): void;
|
|
41
|
+
render(): React.JSX.Element;
|
|
42
|
+
context: unknown;
|
|
43
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K>) | Pick<{}, K>, callback?: () => void): void;
|
|
44
|
+
forceUpdate(callback?: () => void): void;
|
|
45
|
+
readonly props: Readonly<{}>;
|
|
46
|
+
state: Readonly<{}>;
|
|
47
|
+
refs: {
|
|
48
|
+
[key: string]: React.ReactInstance;
|
|
49
|
+
};
|
|
50
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
51
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
52
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
53
|
+
componentWillMount?(): void;
|
|
54
|
+
UNSAFE_componentWillMount?(): void;
|
|
55
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
56
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
57
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
58
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
59
|
+
};
|
|
60
|
+
contextType?: React.Context<any>;
|
|
61
|
+
};
|
|
62
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
2
|
+
import { jsx as _jsx } from "@ice/jsx-runtime/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
class Component extends React.Component {
|
|
5
|
+
render() {
|
|
6
|
+
const { containerRef } = this.props;
|
|
7
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
8
|
+
ref: containerRef
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const FallBack = ({ Original, remoteReactDOM, remoteReact })=>{
|
|
13
|
+
const ReactDOM = remoteReactDOM();
|
|
14
|
+
const React = remoteReact();
|
|
15
|
+
class WrappedComponent extends React.Component {
|
|
16
|
+
componentDidMount() {
|
|
17
|
+
this.mountOriginalComponent(true);
|
|
18
|
+
}
|
|
19
|
+
componentDidUpdate() {
|
|
20
|
+
this.mountOriginalComponent();
|
|
21
|
+
}
|
|
22
|
+
componentWillUnmount() {
|
|
23
|
+
if (this.containerRef.current) {
|
|
24
|
+
ReactDOM.unmountComponentAtNode(this.containerRef.current);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
mountOriginalComponent(shouldRender = false) {
|
|
28
|
+
const element = React.createElement(Original, this.props);
|
|
29
|
+
const renderMethod = shouldRender ? ReactDOM.render : ReactDOM.hydrate;
|
|
30
|
+
renderMethod(element, this.containerRef.current);
|
|
31
|
+
}
|
|
32
|
+
render() {
|
|
33
|
+
return /*#__PURE__*/ _jsx(Component, {
|
|
34
|
+
containerRef: this.containerRef
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
constructor(...args){
|
|
38
|
+
super(...args);
|
|
39
|
+
_define_property(this, "containerRef", React.createRef());
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return WrappedComponent;
|
|
43
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface RemoteModuleOptions {
|
|
3
|
+
module: string;
|
|
4
|
+
scope: string;
|
|
5
|
+
runtime?: {
|
|
6
|
+
react: typeof import('react');
|
|
7
|
+
reactDOM: typeof import('react-dom');
|
|
8
|
+
};
|
|
9
|
+
publicPath?: string;
|
|
10
|
+
LoadingComponent?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare const RemoteModule: ({ module, scope, runtime, publicPath, LoadingComponent, }: RemoteModuleOptions) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx } from "@ice/jsx-runtime/jsx-runtime";
|
|
2
|
+
import { loadRemote } from '@module-federation/runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { useEffect, useState } from 'react';
|
|
5
|
+
import { FallBack } from './FallBack';
|
|
6
|
+
import { setFederatedModulePublicPath } from './set-public-path';
|
|
7
|
+
function useDynamicImport({ module, scope }) {
|
|
8
|
+
const [component, setComponent] = useState(null);
|
|
9
|
+
useEffect(()=>{
|
|
10
|
+
if (!module || !scope) return;
|
|
11
|
+
const loadComponent = async ()=>{
|
|
12
|
+
try {
|
|
13
|
+
const res = await loadRemote(`${scope}/${module}`);
|
|
14
|
+
setComponent(res);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error(`Error loading remote module ${scope}/${module}:`, error);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
loadComponent();
|
|
20
|
+
}, [
|
|
21
|
+
module,
|
|
22
|
+
scope
|
|
23
|
+
]);
|
|
24
|
+
return component;
|
|
25
|
+
}
|
|
26
|
+
export const RemoteModule = ({ module, scope, runtime, publicPath, LoadingComponent })=>{
|
|
27
|
+
var _remoteModule;
|
|
28
|
+
if (publicPath) {
|
|
29
|
+
setFederatedModulePublicPath(scope, publicPath);
|
|
30
|
+
}
|
|
31
|
+
const remoteModule = useDynamicImport({
|
|
32
|
+
module,
|
|
33
|
+
scope
|
|
34
|
+
});
|
|
35
|
+
let Component = null;
|
|
36
|
+
if ((_remoteModule = remoteModule) === null || _remoteModule === void 0 ? void 0 : _remoteModule.default) {
|
|
37
|
+
if (runtime) {
|
|
38
|
+
const { react, reactDOM } = runtime;
|
|
39
|
+
const w = FallBack({
|
|
40
|
+
Original: remoteModule.default,
|
|
41
|
+
remoteReact: ()=>react,
|
|
42
|
+
remoteReactDOM: ()=>reactDOM
|
|
43
|
+
});
|
|
44
|
+
Component = w;
|
|
45
|
+
} else {
|
|
46
|
+
Component = /*#__PURE__*/ React.lazy(()=>Promise.resolve({
|
|
47
|
+
default: remoteModule.default
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
Component = remoteModule;
|
|
52
|
+
}
|
|
53
|
+
const Loading = LoadingComponent || /*#__PURE__*/ _jsx("div", {
|
|
54
|
+
children: "Loading..."
|
|
55
|
+
});
|
|
56
|
+
if (Component) {
|
|
57
|
+
return /*#__PURE__*/ _jsx(React.Suspense, {
|
|
58
|
+
fallback: Loading,
|
|
59
|
+
children: /*#__PURE__*/ _jsx(Component, {})
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
return Loading;
|
|
63
|
+
};
|
package/es2017/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerPlugins, init as mfInit } from '@module-federation/runtime';
|
|
2
|
+
import { runtimePlugin } from './runtime-plugin';
|
|
3
|
+
export { loadRemote, registerPlugins } from '@module-federation/runtime';
|
|
4
|
+
export * from './FallBack';
|
|
5
|
+
export * from './RemoteModule';
|
|
6
|
+
export function init(options) {
|
|
7
|
+
mfInit(options);
|
|
8
|
+
registerPlugins([
|
|
9
|
+
runtimePlugin()
|
|
10
|
+
]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ExtraInfo, ExtendedUserOptions } from './types';
|
|
2
|
+
export interface RemoteModuleInfo {
|
|
3
|
+
key: string;
|
|
4
|
+
name: string;
|
|
5
|
+
entry: string;
|
|
6
|
+
hostName: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
extraInfo?: ExtraInfo;
|
|
9
|
+
}
|
|
10
|
+
export interface HostRemoteInfo {
|
|
11
|
+
keys: Set<string>;
|
|
12
|
+
nameKeyMap: Map<string, string>;
|
|
13
|
+
conflictingModules: Set<string>;
|
|
14
|
+
}
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
__MF_GLOBAL_STORE__: {
|
|
18
|
+
remotes: Map<string, RemoteModuleInfo>;
|
|
19
|
+
hostRemotes: Map<string, HostRemoteInfo>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export declare function initGlobalStore(options: ExtendedUserOptions): void;
|
|
24
|
+
export declare function generateRemoteKey(name: string, entry: string): string;
|
|
25
|
+
export declare function getRemoteInfoFromStore(hostName: string, remoteName: string): RemoteModuleInfo | undefined;
|
|
26
|
+
export declare function hasConflict(hostName: string, remoteName: string): boolean;
|
|
27
|
+
export declare function getExtraInfo(hostName: string, remoteName: string): ExtraInfo;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export function initGlobalStore(options) {
|
|
2
|
+
if (!window.__MF_GLOBAL_STORE__) {
|
|
3
|
+
window.__MF_GLOBAL_STORE__ = {
|
|
4
|
+
remotes: new Map(),
|
|
5
|
+
hostRemotes: new Map()
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
const store = window.__MF_GLOBAL_STORE__;
|
|
9
|
+
const hostInfo = {
|
|
10
|
+
keys: new Set(),
|
|
11
|
+
nameKeyMap: new Map(),
|
|
12
|
+
conflictingModules: new Set()
|
|
13
|
+
};
|
|
14
|
+
// 更新每个 remote 模块的信息
|
|
15
|
+
options.remotes.forEach((remote)=>{
|
|
16
|
+
if (!remote.name) return;
|
|
17
|
+
const { entry } = remote;
|
|
18
|
+
const remoteKey = generateRemoteKey(remote.name, entry);
|
|
19
|
+
const newInfo = {
|
|
20
|
+
key: remoteKey,
|
|
21
|
+
name: remote.name,
|
|
22
|
+
entry,
|
|
23
|
+
hostName: options.name,
|
|
24
|
+
extraInfo: remote.extraInfo
|
|
25
|
+
};
|
|
26
|
+
// 记录这个 host 使用的 remote key 和 name 到 key 的映射
|
|
27
|
+
hostInfo.keys.add(remoteKey);
|
|
28
|
+
hostInfo.nameKeyMap.set(remote.name, remoteKey);
|
|
29
|
+
// 检查是否与现有模块冲突
|
|
30
|
+
for (const [, info] of store.remotes.entries()){
|
|
31
|
+
if (info.name === remote.name && info.entry !== entry) {
|
|
32
|
+
console.warn(`[Module Federation] Remote module "${remote.name}" has multiple versions:`, `\nHost "${info.hostName}": ${info.entry}`, `\nHost "${options.name}": ${entry}`);
|
|
33
|
+
// 在 host 环境中标记该模块存在冲突
|
|
34
|
+
hostInfo.conflictingModules.add(remote.name);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
store.remotes.set(remoteKey, newInfo);
|
|
38
|
+
});
|
|
39
|
+
// 更新 host 的 remote 信息
|
|
40
|
+
store.hostRemotes.set(options.name, hostInfo);
|
|
41
|
+
}
|
|
42
|
+
// 生成 remote 模块的唯一标识
|
|
43
|
+
export function generateRemoteKey(name, entry) {
|
|
44
|
+
return `${name}@${entry}`;
|
|
45
|
+
}
|
|
46
|
+
export function getRemoteInfoFromStore(hostName, remoteName) {
|
|
47
|
+
const store = window.__MF_GLOBAL_STORE__;
|
|
48
|
+
const hostInfo = store.hostRemotes.get(hostName);
|
|
49
|
+
if (!hostInfo) return undefined;
|
|
50
|
+
const remoteKey = hostInfo.nameKeyMap.get(remoteName);
|
|
51
|
+
if (!remoteKey) return undefined;
|
|
52
|
+
return store.remotes.get(remoteKey);
|
|
53
|
+
}
|
|
54
|
+
// 检查指定的 remote 模块在当前 host 环境中是否存在冲突
|
|
55
|
+
export function hasConflict(hostName, remoteName) {
|
|
56
|
+
var _hostInfo;
|
|
57
|
+
const store = window.__MF_GLOBAL_STORE__;
|
|
58
|
+
const hostInfo = store.hostRemotes.get(hostName);
|
|
59
|
+
var _hostInfo_conflictingModules_has;
|
|
60
|
+
return (_hostInfo_conflictingModules_has = (_hostInfo = hostInfo) === null || _hostInfo === void 0 ? void 0 : _hostInfo.conflictingModules.has(remoteName)) !== null && _hostInfo_conflictingModules_has !== void 0 ? _hostInfo_conflictingModules_has : false;
|
|
61
|
+
}
|
|
62
|
+
export function getExtraInfo(hostName, remoteName) {
|
|
63
|
+
var _remoteInfo;
|
|
64
|
+
const remoteInfo = getRemoteInfoFromStore(hostName, remoteName);
|
|
65
|
+
return (_remoteInfo = remoteInfo) === null || _remoteInfo === void 0 ? void 0 : _remoteInfo.extraInfo;
|
|
66
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { getExtraInfo, getRemoteInfoFromStore, hasConflict } from './mf-global-store';
|
|
3
|
+
const loadRemotePackagedReactAndRender = async (args)=>{
|
|
4
|
+
var _args_origin_options_shared_reactdom_, _args_origin_options_shared_reactdom, _args_origin_options_shared, _args_origin_options, _remoteInstance_options_shared_reactdom_, _remoteInstance_options_shared_reactdom, _remoteInstance_options_shared, _remoteInstance_options;
|
|
5
|
+
const hostVersion = ((_args_origin_options = args.origin.options) === null || _args_origin_options === void 0 ? void 0 : (_args_origin_options_shared = _args_origin_options.shared) === null || _args_origin_options_shared === void 0 ? void 0 : (_args_origin_options_shared_reactdom = _args_origin_options_shared['react-dom']) === null || _args_origin_options_shared_reactdom === void 0 ? void 0 : (_args_origin_options_shared_reactdom_ = _args_origin_options_shared_reactdom[0]) === null || _args_origin_options_shared_reactdom_ === void 0 ? void 0 : _args_origin_options_shared_reactdom_.version) || React.version;
|
|
6
|
+
const remoteInstance = __FEDERATION__.__INSTANCES__.find(// @ts-expect-error wrong type
|
|
7
|
+
(instance)=>instance.name === args.remote.name);
|
|
8
|
+
const remoteVersion = remoteInstance ? (_remoteInstance_options = remoteInstance.options) === null || _remoteInstance_options === void 0 ? void 0 : (_remoteInstance_options_shared = _remoteInstance_options.shared) === null || _remoteInstance_options_shared === void 0 ? void 0 : (_remoteInstance_options_shared_reactdom = _remoteInstance_options_shared['react-dom']) === null || _remoteInstance_options_shared_reactdom === void 0 ? void 0 : (_remoteInstance_options_shared_reactdom_ = _remoteInstance_options_shared_reactdom[0]) === null || _remoteInstance_options_shared_reactdom_ === void 0 ? void 0 : _remoteInstance_options_shared_reactdom_.version : false;
|
|
9
|
+
if (remoteVersion && hostVersion && remoteVersion !== hostVersion) {
|
|
10
|
+
var _sharedOptions_find;
|
|
11
|
+
const remoteReactDOM = await remoteInstance.loadShare('react-dom', {
|
|
12
|
+
resolver: (sharedOptions)=>(_sharedOptions_find = sharedOptions.find((i)=>i.version === remoteVersion)) !== null && _sharedOptions_find !== void 0 ? _sharedOptions_find : sharedOptions[0]
|
|
13
|
+
});
|
|
14
|
+
var _sharedOptions_find1;
|
|
15
|
+
const remoteReact = await remoteInstance.loadShare('react', {
|
|
16
|
+
resolver: (sharedOptions)=>(_sharedOptions_find1 = sharedOptions.find((i)=>i.version === remoteVersion)) !== null && _sharedOptions_find1 !== void 0 ? _sharedOptions_find1 : sharedOptions[0]
|
|
17
|
+
});
|
|
18
|
+
if (!remoteReact || !remoteReactDOM) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const res = (await import('./FallBack')).FallBack;
|
|
22
|
+
return ()=>res({
|
|
23
|
+
Original: args.exposeModule.default,
|
|
24
|
+
remoteVersion: ()=>remoteVersion,
|
|
25
|
+
hostVersion: ()=>hostVersion,
|
|
26
|
+
remoteReactDOM: remoteReactDOM,
|
|
27
|
+
remoteReact: remoteReact
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
};
|
|
32
|
+
export const runtimePlugin = ()=>({
|
|
33
|
+
name: 'ice-runtime-plugin',
|
|
34
|
+
afterResolve (args) {
|
|
35
|
+
var _extraInfo;
|
|
36
|
+
const hostName = args.options.name;
|
|
37
|
+
const remoteName = args.remote.name;
|
|
38
|
+
const extraInfo = getExtraInfo(hostName, remoteName);
|
|
39
|
+
if ((_extraInfo = extraInfo) === null || _extraInfo === void 0 ? void 0 : _extraInfo.legacy) {
|
|
40
|
+
if (args.expose.startsWith('./')) {
|
|
41
|
+
args.expose = args.expose.slice(2);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return args;
|
|
45
|
+
},
|
|
46
|
+
async onLoad (args) {
|
|
47
|
+
var _args_origin_options_shared_reactdom_, _args_origin_options_shared_reactdom, _args_origin_options_shared, _args_origin_options, _extraInfo;
|
|
48
|
+
const hostName = args.origin.name;
|
|
49
|
+
const remoteName = args.remote.name;
|
|
50
|
+
const hostVersion = ((_args_origin_options = args.origin.options) === null || _args_origin_options === void 0 ? void 0 : (_args_origin_options_shared = _args_origin_options.shared) === null || _args_origin_options_shared === void 0 ? void 0 : (_args_origin_options_shared_reactdom = _args_origin_options_shared['react-dom']) === null || _args_origin_options_shared_reactdom === void 0 ? void 0 : (_args_origin_options_shared_reactdom_ = _args_origin_options_shared_reactdom[0]) === null || _args_origin_options_shared_reactdom_ === void 0 ? void 0 : _args_origin_options_shared_reactdom_.version) || React.version;
|
|
51
|
+
const extraInfo = getExtraInfo(hostName, remoteName);
|
|
52
|
+
if ((_extraInfo = extraInfo) === null || _extraInfo === void 0 ? void 0 : _extraInfo.external) {
|
|
53
|
+
const externalReact = extraInfo.external['react'];
|
|
54
|
+
const externalReactDOM = extraInfo.external['react-dom'];
|
|
55
|
+
if (externalReact && externalReactDOM) {
|
|
56
|
+
const remoteReact = ()=>window[externalReact];
|
|
57
|
+
const remoteReactDOM = ()=>window[externalReactDOM];
|
|
58
|
+
if (remoteReactDOM().version === hostVersion) {
|
|
59
|
+
console.log('[runtime Plugin onLoad] use same external react');
|
|
60
|
+
return args;
|
|
61
|
+
}
|
|
62
|
+
// 当 external 版本不一致,走降级渲染
|
|
63
|
+
const res = (await import('./FallBack')).FallBack;
|
|
64
|
+
return ()=>res({
|
|
65
|
+
Original: args.exposeModule.default,
|
|
66
|
+
remoteReactDOM: remoteReactDOM,
|
|
67
|
+
remoteReact: remoteReact
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const fallBackRender = await loadRemotePackagedReactAndRender(args);
|
|
72
|
+
if (fallBackRender) {
|
|
73
|
+
return fallBackRender;
|
|
74
|
+
}
|
|
75
|
+
return args;
|
|
76
|
+
},
|
|
77
|
+
async beforeRequest (args) {
|
|
78
|
+
const remoteName = args.id.split('/')[0];
|
|
79
|
+
const hostName = args.options.name;
|
|
80
|
+
if (!hasConflict(hostName, remoteName)) {
|
|
81
|
+
return args;
|
|
82
|
+
}
|
|
83
|
+
const newRemoteInfo = getRemoteInfoFromStore(hostName, remoteName);
|
|
84
|
+
if (!newRemoteInfo) {
|
|
85
|
+
return args;
|
|
86
|
+
}
|
|
87
|
+
const requestRemote = args.options.remotes.find((remote)=>remote.name === remoteName);
|
|
88
|
+
if (requestRemote) {
|
|
89
|
+
requestRemote.entry = newRemoteInfo.entry;
|
|
90
|
+
}
|
|
91
|
+
const hostInstance = __FEDERATION__.__INSTANCES__.find((instance)=>instance.name === hostName);
|
|
92
|
+
if (hostInstance) {
|
|
93
|
+
hostInstance.moduleCache.delete(remoteName);
|
|
94
|
+
hostInstance.options.remotes.find((remote)=>remote.name === remoteName).entry = newRemoteInfo.entry;
|
|
95
|
+
}
|
|
96
|
+
args.origin.moduleCache.delete(remoteName);
|
|
97
|
+
// @ts-expect-error for global module
|
|
98
|
+
window[remoteName] = null;
|
|
99
|
+
return args;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const ensureSlash = (input, needSlash, position)=>{
|
|
2
|
+
if (input == null) return input;
|
|
3
|
+
if (position === 'head') {
|
|
4
|
+
const startWithSlash = input.startsWith('/');
|
|
5
|
+
if (startWithSlash && !needSlash) {
|
|
6
|
+
return input.slice(1);
|
|
7
|
+
} else if (!startWithSlash && needSlash) {
|
|
8
|
+
return `/${input}`;
|
|
9
|
+
}
|
|
10
|
+
return input;
|
|
11
|
+
} else if (position === 'tail') {
|
|
12
|
+
const endsWithSlash = input.endsWith('/');
|
|
13
|
+
if (endsWithSlash && !needSlash) {
|
|
14
|
+
return input.substr(0, input.length - 1);
|
|
15
|
+
} else if (!endsWithSlash && needSlash) {
|
|
16
|
+
return `${input}/`;
|
|
17
|
+
} else {
|
|
18
|
+
return input;
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
return input;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const setFederatedModulePublicPath = (scope, publicPath)=>{
|
|
25
|
+
const publicPathReference = `${scope}_public_path`;
|
|
26
|
+
// @ts-expect-error for global public path
|
|
27
|
+
window[publicPathReference] = ensureSlash(publicPath, true, 'tail');
|
|
28
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { UserOptions } from '@module-federation/runtime-core';
|
|
2
|
+
import type { Remote } from '@module-federation/runtime-core/dist/src/types';
|
|
3
|
+
export interface ExtraInfo {
|
|
4
|
+
external?: Record<string, string>;
|
|
5
|
+
legacy?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type ExtendedRemote = Remote & {
|
|
8
|
+
extraInfo?: ExtraInfo;
|
|
9
|
+
};
|
|
10
|
+
export interface ExtendedUserOptions extends Omit<UserOptions, 'remotes'> {
|
|
11
|
+
remotes: ExtendedRemote[];
|
|
12
|
+
}
|
package/es2017/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="@ice/pkg/types" />
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface FallBackOptions {
|
|
3
|
+
Original: React.ComponentType<any>;
|
|
4
|
+
remoteVersion?: () => string;
|
|
5
|
+
hostVersion?: () => string;
|
|
6
|
+
remoteReactDOM: () => typeof import('react-dom');
|
|
7
|
+
remoteReact: () => typeof import('react');
|
|
8
|
+
}
|
|
9
|
+
export declare const FallBack: ({ Original, remoteReactDOM, remoteReact, }: FallBackOptions) => {
|
|
10
|
+
new (props: {}): {
|
|
11
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
12
|
+
componentDidMount(): void;
|
|
13
|
+
componentDidUpdate(): void;
|
|
14
|
+
componentWillUnmount(): void;
|
|
15
|
+
mountOriginalComponent(shouldRender?: boolean): void;
|
|
16
|
+
render(): React.JSX.Element;
|
|
17
|
+
context: unknown;
|
|
18
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K>) | Pick<{}, K>, callback?: () => void): void;
|
|
19
|
+
forceUpdate(callback?: () => void): void;
|
|
20
|
+
readonly props: Readonly<{}>;
|
|
21
|
+
state: Readonly<{}>;
|
|
22
|
+
refs: {
|
|
23
|
+
[key: string]: React.ReactInstance;
|
|
24
|
+
};
|
|
25
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
26
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
27
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
28
|
+
componentWillMount?(): void;
|
|
29
|
+
UNSAFE_componentWillMount?(): void;
|
|
30
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
31
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
32
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
33
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
34
|
+
};
|
|
35
|
+
new (props: {}, context: any): {
|
|
36
|
+
containerRef: React.RefObject<HTMLDivElement>;
|
|
37
|
+
componentDidMount(): void;
|
|
38
|
+
componentDidUpdate(): void;
|
|
39
|
+
componentWillUnmount(): void;
|
|
40
|
+
mountOriginalComponent(shouldRender?: boolean): void;
|
|
41
|
+
render(): React.JSX.Element;
|
|
42
|
+
context: unknown;
|
|
43
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K>) | Pick<{}, K>, callback?: () => void): void;
|
|
44
|
+
forceUpdate(callback?: () => void): void;
|
|
45
|
+
readonly props: Readonly<{}>;
|
|
46
|
+
state: Readonly<{}>;
|
|
47
|
+
refs: {
|
|
48
|
+
[key: string]: React.ReactInstance;
|
|
49
|
+
};
|
|
50
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
51
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
52
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
53
|
+
componentWillMount?(): void;
|
|
54
|
+
UNSAFE_componentWillMount?(): void;
|
|
55
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
56
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
57
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
58
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
59
|
+
};
|
|
60
|
+
contextType?: React.Context<any>;
|
|
61
|
+
};
|
|
62
|
+
export {};
|
package/esm/FallBack.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { _ as _assert_this_initialized } from "@swc/helpers/_/_assert_this_initialized";
|
|
2
|
+
import { _ as _class_call_check } from "@swc/helpers/_/_class_call_check";
|
|
3
|
+
import { _ as _create_class } from "@swc/helpers/_/_create_class";
|
|
4
|
+
import { _ as _define_property } from "@swc/helpers/_/_define_property";
|
|
5
|
+
import { _ as _inherits } from "@swc/helpers/_/_inherits";
|
|
6
|
+
import { _ as _create_super } from "@swc/helpers/_/_create_super";
|
|
7
|
+
import { jsx as _jsx } from "@ice/jsx-runtime/jsx-runtime";
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
var Component = /*#__PURE__*/ function(_React_Component) {
|
|
10
|
+
"use strict";
|
|
11
|
+
_inherits(Component, _React_Component);
|
|
12
|
+
var _super = _create_super(Component);
|
|
13
|
+
function Component() {
|
|
14
|
+
_class_call_check(this, Component);
|
|
15
|
+
return _super.apply(this, arguments);
|
|
16
|
+
}
|
|
17
|
+
_create_class(Component, [
|
|
18
|
+
{
|
|
19
|
+
key: "render",
|
|
20
|
+
value: function render() {
|
|
21
|
+
var containerRef = this.props.containerRef;
|
|
22
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
23
|
+
ref: containerRef
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
]);
|
|
28
|
+
return Component;
|
|
29
|
+
}(React.Component);
|
|
30
|
+
export var FallBack = function(param) {
|
|
31
|
+
var Original = param.Original, remoteReactDOM = param.remoteReactDOM, remoteReact = param.remoteReact;
|
|
32
|
+
var ReactDOM = remoteReactDOM();
|
|
33
|
+
var _$React = remoteReact();
|
|
34
|
+
var WrappedComponent = /*#__PURE__*/ function(_React_Component) {
|
|
35
|
+
"use strict";
|
|
36
|
+
_inherits(WrappedComponent, _React_Component);
|
|
37
|
+
var _super = _create_super(WrappedComponent);
|
|
38
|
+
function WrappedComponent() {
|
|
39
|
+
_class_call_check(this, WrappedComponent);
|
|
40
|
+
var _this;
|
|
41
|
+
_this = _super.apply(this, arguments);
|
|
42
|
+
_define_property(_assert_this_initialized(_this), "containerRef", _$React.createRef());
|
|
43
|
+
return _this;
|
|
44
|
+
}
|
|
45
|
+
_create_class(WrappedComponent, [
|
|
46
|
+
{
|
|
47
|
+
key: "componentDidMount",
|
|
48
|
+
value: function componentDidMount() {
|
|
49
|
+
this.mountOriginalComponent(true);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: "componentDidUpdate",
|
|
54
|
+
value: function componentDidUpdate() {
|
|
55
|
+
this.mountOriginalComponent();
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
key: "componentWillUnmount",
|
|
60
|
+
value: function componentWillUnmount() {
|
|
61
|
+
if (this.containerRef.current) {
|
|
62
|
+
ReactDOM.unmountComponentAtNode(this.containerRef.current);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
key: "mountOriginalComponent",
|
|
68
|
+
value: function mountOriginalComponent() {
|
|
69
|
+
var shouldRender = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
|
|
70
|
+
var element = _$React.createElement(Original, this.props);
|
|
71
|
+
var renderMethod = shouldRender ? ReactDOM.render : ReactDOM.hydrate;
|
|
72
|
+
renderMethod(element, this.containerRef.current);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
key: "render",
|
|
77
|
+
value: function render() {
|
|
78
|
+
return /*#__PURE__*/ _jsx(Component, {
|
|
79
|
+
containerRef: this.containerRef
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
]);
|
|
84
|
+
return WrappedComponent;
|
|
85
|
+
}(_$React.Component);
|
|
86
|
+
return WrappedComponent;
|
|
87
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface RemoteModuleOptions {
|
|
3
|
+
module: string;
|
|
4
|
+
scope: string;
|
|
5
|
+
runtime?: {
|
|
6
|
+
react: typeof import('react');
|
|
7
|
+
reactDOM: typeof import('react-dom');
|
|
8
|
+
};
|
|
9
|
+
publicPath?: string;
|
|
10
|
+
LoadingComponent?: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
export declare const RemoteModule: ({ module, scope, runtime, publicPath, LoadingComponent, }: RemoteModuleOptions) => string | number | true | Iterable<React.ReactNode> | React.JSX.Element;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
2
|
+
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
|
|
3
|
+
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
4
|
+
import { jsx as _jsx } from "@ice/jsx-runtime/jsx-runtime";
|
|
5
|
+
import { loadRemote } from "@module-federation/runtime";
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import { useEffect, useState } from "react";
|
|
8
|
+
import { FallBack } from "./FallBack";
|
|
9
|
+
import { setFederatedModulePublicPath } from "./set-public-path";
|
|
10
|
+
function useDynamicImport(param) {
|
|
11
|
+
var module = param.module, scope = param.scope;
|
|
12
|
+
var _useState = _sliced_to_array(useState(null), 2), component = _useState[0], setComponent = _useState[1];
|
|
13
|
+
useEffect(function() {
|
|
14
|
+
if (!module || !scope) return;
|
|
15
|
+
var loadComponent = function() {
|
|
16
|
+
var _ref = _async_to_generator(function() {
|
|
17
|
+
var res, error;
|
|
18
|
+
return _ts_generator(this, function(_state) {
|
|
19
|
+
switch(_state.label){
|
|
20
|
+
case 0:
|
|
21
|
+
_state.trys.push([
|
|
22
|
+
0,
|
|
23
|
+
2,
|
|
24
|
+
,
|
|
25
|
+
3
|
|
26
|
+
]);
|
|
27
|
+
return [
|
|
28
|
+
4,
|
|
29
|
+
loadRemote("".concat(scope, "/").concat(module))
|
|
30
|
+
];
|
|
31
|
+
case 1:
|
|
32
|
+
res = _state.sent();
|
|
33
|
+
setComponent(res);
|
|
34
|
+
return [
|
|
35
|
+
3,
|
|
36
|
+
3
|
|
37
|
+
];
|
|
38
|
+
case 2:
|
|
39
|
+
error = _state.sent();
|
|
40
|
+
console.error("Error loading remote module ".concat(scope, "/").concat(module, ":"), error);
|
|
41
|
+
return [
|
|
42
|
+
3,
|
|
43
|
+
3
|
|
44
|
+
];
|
|
45
|
+
case 3:
|
|
46
|
+
return [
|
|
47
|
+
2
|
|
48
|
+
];
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return function loadComponent() {
|
|
53
|
+
return _ref.apply(this, arguments);
|
|
54
|
+
};
|
|
55
|
+
}();
|
|
56
|
+
loadComponent();
|
|
57
|
+
}, [
|
|
58
|
+
module,
|
|
59
|
+
scope
|
|
60
|
+
]);
|
|
61
|
+
return component;
|
|
62
|
+
}
|
|
63
|
+
export var RemoteModule = function(param) {
|
|
64
|
+
var module = param.module, scope = param.scope, runtime = param.runtime, publicPath = param.publicPath, LoadingComponent = param.LoadingComponent;
|
|
65
|
+
var _remoteModule;
|
|
66
|
+
if (publicPath) {
|
|
67
|
+
setFederatedModulePublicPath(scope, publicPath);
|
|
68
|
+
}
|
|
69
|
+
var remoteModule = useDynamicImport({
|
|
70
|
+
module: module,
|
|
71
|
+
scope: scope
|
|
72
|
+
});
|
|
73
|
+
var Component = null;
|
|
74
|
+
if ((_remoteModule = remoteModule) === null || _remoteModule === void 0 ? void 0 : _remoteModule.default) {
|
|
75
|
+
if (runtime) {
|
|
76
|
+
var react = runtime.react, reactDOM = runtime.reactDOM;
|
|
77
|
+
var w = FallBack({
|
|
78
|
+
Original: remoteModule.default,
|
|
79
|
+
remoteReact: function() {
|
|
80
|
+
return react;
|
|
81
|
+
},
|
|
82
|
+
remoteReactDOM: function() {
|
|
83
|
+
return reactDOM;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
Component = w;
|
|
87
|
+
} else {
|
|
88
|
+
Component = /*#__PURE__*/ React.lazy(function() {
|
|
89
|
+
return Promise.resolve({
|
|
90
|
+
default: remoteModule.default
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
Component = remoteModule;
|
|
96
|
+
}
|
|
97
|
+
var Loading = LoadingComponent || /*#__PURE__*/ _jsx("div", {
|
|
98
|
+
children: "Loading..."
|
|
99
|
+
});
|
|
100
|
+
if (Component) {
|
|
101
|
+
return /*#__PURE__*/ _jsx(React.Suspense, {
|
|
102
|
+
fallback: Loading,
|
|
103
|
+
children: /*#__PURE__*/ _jsx(Component, {})
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return Loading;
|
|
107
|
+
};
|
package/esm/index.d.ts
ADDED
package/esm/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { registerPlugins, init as mfInit } from "@module-federation/runtime";
|
|
2
|
+
import { runtimePlugin } from "./runtime-plugin";
|
|
3
|
+
export { loadRemote, registerPlugins } from "@module-federation/runtime";
|
|
4
|
+
export * from "./FallBack";
|
|
5
|
+
export * from "./RemoteModule";
|
|
6
|
+
export function init(options) {
|
|
7
|
+
mfInit(options);
|
|
8
|
+
registerPlugins([
|
|
9
|
+
runtimePlugin()
|
|
10
|
+
]);
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ExtraInfo, ExtendedUserOptions } from './types';
|
|
2
|
+
export interface RemoteModuleInfo {
|
|
3
|
+
key: string;
|
|
4
|
+
name: string;
|
|
5
|
+
entry: string;
|
|
6
|
+
hostName: string;
|
|
7
|
+
version?: string;
|
|
8
|
+
extraInfo?: ExtraInfo;
|
|
9
|
+
}
|
|
10
|
+
export interface HostRemoteInfo {
|
|
11
|
+
keys: Set<string>;
|
|
12
|
+
nameKeyMap: Map<string, string>;
|
|
13
|
+
conflictingModules: Set<string>;
|
|
14
|
+
}
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
__MF_GLOBAL_STORE__: {
|
|
18
|
+
remotes: Map<string, RemoteModuleInfo>;
|
|
19
|
+
hostRemotes: Map<string, HostRemoteInfo>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export declare function initGlobalStore(options: ExtendedUserOptions): void;
|
|
24
|
+
export declare function generateRemoteKey(name: string, entry: string): string;
|
|
25
|
+
export declare function getRemoteInfoFromStore(hostName: string, remoteName: string): RemoteModuleInfo | undefined;
|
|
26
|
+
export declare function hasConflict(hostName: string, remoteName: string): boolean;
|
|
27
|
+
export declare function getExtraInfo(hostName: string, remoteName: string): ExtraInfo;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array";
|
|
2
|
+
export function initGlobalStore(options) {
|
|
3
|
+
if (!window.__MF_GLOBAL_STORE__) {
|
|
4
|
+
window.__MF_GLOBAL_STORE__ = {
|
|
5
|
+
remotes: new Map(),
|
|
6
|
+
hostRemotes: new Map()
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
var store = window.__MF_GLOBAL_STORE__;
|
|
10
|
+
var hostInfo = {
|
|
11
|
+
keys: new Set(),
|
|
12
|
+
nameKeyMap: new Map(),
|
|
13
|
+
conflictingModules: new Set()
|
|
14
|
+
};
|
|
15
|
+
// 更新每个 remote 模块的信息
|
|
16
|
+
options.remotes.forEach(function(remote) {
|
|
17
|
+
if (!remote.name) return;
|
|
18
|
+
var entry = remote.entry;
|
|
19
|
+
var remoteKey = generateRemoteKey(remote.name, entry);
|
|
20
|
+
var newInfo = {
|
|
21
|
+
key: remoteKey,
|
|
22
|
+
name: remote.name,
|
|
23
|
+
entry: entry,
|
|
24
|
+
hostName: options.name,
|
|
25
|
+
extraInfo: remote.extraInfo
|
|
26
|
+
};
|
|
27
|
+
// 记录这个 host 使用的 remote key 和 name 到 key 的映射
|
|
28
|
+
hostInfo.keys.add(remoteKey);
|
|
29
|
+
hostInfo.nameKeyMap.set(remote.name, remoteKey);
|
|
30
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
31
|
+
try {
|
|
32
|
+
// 检查是否与现有模块冲突
|
|
33
|
+
for(var _iterator = store.remotes.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
34
|
+
var _step_value = _sliced_to_array(_step.value, 2), info = _step_value[1];
|
|
35
|
+
if (info.name === remote.name && info.entry !== entry) {
|
|
36
|
+
console.warn('[Module Federation] Remote module "'.concat(remote.name, '" has multiple versions:'), '\nHost "'.concat(info.hostName, '": ').concat(info.entry), '\nHost "'.concat(options.name, '": ').concat(entry));
|
|
37
|
+
// 在 host 环境中标记该模块存在冲突
|
|
38
|
+
hostInfo.conflictingModules.add(remote.name);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch (err) {
|
|
42
|
+
_didIteratorError = true;
|
|
43
|
+
_iteratorError = err;
|
|
44
|
+
} finally{
|
|
45
|
+
try {
|
|
46
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
47
|
+
_iterator.return();
|
|
48
|
+
}
|
|
49
|
+
} finally{
|
|
50
|
+
if (_didIteratorError) {
|
|
51
|
+
throw _iteratorError;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
store.remotes.set(remoteKey, newInfo);
|
|
56
|
+
});
|
|
57
|
+
// 更新 host 的 remote 信息
|
|
58
|
+
store.hostRemotes.set(options.name, hostInfo);
|
|
59
|
+
}
|
|
60
|
+
// 生成 remote 模块的唯一标识
|
|
61
|
+
export function generateRemoteKey(name, entry) {
|
|
62
|
+
return "".concat(name, "@").concat(entry);
|
|
63
|
+
}
|
|
64
|
+
export function getRemoteInfoFromStore(hostName, remoteName) {
|
|
65
|
+
var store = window.__MF_GLOBAL_STORE__;
|
|
66
|
+
var hostInfo = store.hostRemotes.get(hostName);
|
|
67
|
+
if (!hostInfo) return undefined;
|
|
68
|
+
var remoteKey = hostInfo.nameKeyMap.get(remoteName);
|
|
69
|
+
if (!remoteKey) return undefined;
|
|
70
|
+
return store.remotes.get(remoteKey);
|
|
71
|
+
}
|
|
72
|
+
// 检查指定的 remote 模块在当前 host 环境中是否存在冲突
|
|
73
|
+
export function hasConflict(hostName, remoteName) {
|
|
74
|
+
var _hostInfo;
|
|
75
|
+
var store = window.__MF_GLOBAL_STORE__;
|
|
76
|
+
var hostInfo = store.hostRemotes.get(hostName);
|
|
77
|
+
var _hostInfo_conflictingModules_has;
|
|
78
|
+
return (_hostInfo_conflictingModules_has = (_hostInfo = hostInfo) === null || _hostInfo === void 0 ? void 0 : _hostInfo.conflictingModules.has(remoteName)) !== null && _hostInfo_conflictingModules_has !== void 0 ? _hostInfo_conflictingModules_has : false;
|
|
79
|
+
}
|
|
80
|
+
export function getExtraInfo(hostName, remoteName) {
|
|
81
|
+
var _remoteInfo;
|
|
82
|
+
var remoteInfo = getRemoteInfoFromStore(hostName, remoteName);
|
|
83
|
+
return (_remoteInfo = remoteInfo) === null || _remoteInfo === void 0 ? void 0 : _remoteInfo.extraInfo;
|
|
84
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator";
|
|
2
|
+
import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { getExtraInfo, getRemoteInfoFromStore, hasConflict } from "./mf-global-store";
|
|
5
|
+
var loadRemotePackagedReactAndRender = function() {
|
|
6
|
+
var _ref = _async_to_generator(function(args) {
|
|
7
|
+
var _args_origin_options_shared_reactdom_, _args_origin_options_shared_reactdom, _args_origin_options_shared, _args_origin_options, _remoteInstance_options_shared_reactdom_, _remoteInstance_options_shared_reactdom, _remoteInstance_options_shared, _remoteInstance_options, hostVersion, remoteInstance, remoteVersion, _sharedOptions_find, remoteReactDOM, _sharedOptions_find1, remoteReact, res;
|
|
8
|
+
return _ts_generator(this, function(_state) {
|
|
9
|
+
switch(_state.label){
|
|
10
|
+
case 0:
|
|
11
|
+
hostVersion = ((_args_origin_options = args.origin.options) === null || _args_origin_options === void 0 ? void 0 : (_args_origin_options_shared = _args_origin_options.shared) === null || _args_origin_options_shared === void 0 ? void 0 : (_args_origin_options_shared_reactdom = _args_origin_options_shared["react-dom"]) === null || _args_origin_options_shared_reactdom === void 0 ? void 0 : (_args_origin_options_shared_reactdom_ = _args_origin_options_shared_reactdom[0]) === null || _args_origin_options_shared_reactdom_ === void 0 ? void 0 : _args_origin_options_shared_reactdom_.version) || React.version;
|
|
12
|
+
remoteInstance = __FEDERATION__.__INSTANCES__.find(// @ts-expect-error wrong type
|
|
13
|
+
function(instance) {
|
|
14
|
+
return instance.name === args.remote.name;
|
|
15
|
+
});
|
|
16
|
+
remoteVersion = remoteInstance ? (_remoteInstance_options = remoteInstance.options) === null || _remoteInstance_options === void 0 ? void 0 : (_remoteInstance_options_shared = _remoteInstance_options.shared) === null || _remoteInstance_options_shared === void 0 ? void 0 : (_remoteInstance_options_shared_reactdom = _remoteInstance_options_shared["react-dom"]) === null || _remoteInstance_options_shared_reactdom === void 0 ? void 0 : (_remoteInstance_options_shared_reactdom_ = _remoteInstance_options_shared_reactdom[0]) === null || _remoteInstance_options_shared_reactdom_ === void 0 ? void 0 : _remoteInstance_options_shared_reactdom_.version : false;
|
|
17
|
+
if (!(remoteVersion && hostVersion && remoteVersion !== hostVersion)) return [
|
|
18
|
+
3,
|
|
19
|
+
4
|
|
20
|
+
];
|
|
21
|
+
return [
|
|
22
|
+
4,
|
|
23
|
+
remoteInstance.loadShare("react-dom", {
|
|
24
|
+
resolver: function(sharedOptions) {
|
|
25
|
+
return (_sharedOptions_find = sharedOptions.find(function(i) {
|
|
26
|
+
return i.version === remoteVersion;
|
|
27
|
+
})) !== null && _sharedOptions_find !== void 0 ? _sharedOptions_find : sharedOptions[0];
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
];
|
|
31
|
+
case 1:
|
|
32
|
+
remoteReactDOM = _state.sent();
|
|
33
|
+
return [
|
|
34
|
+
4,
|
|
35
|
+
remoteInstance.loadShare("react", {
|
|
36
|
+
resolver: function(sharedOptions) {
|
|
37
|
+
return (_sharedOptions_find1 = sharedOptions.find(function(i) {
|
|
38
|
+
return i.version === remoteVersion;
|
|
39
|
+
})) !== null && _sharedOptions_find1 !== void 0 ? _sharedOptions_find1 : sharedOptions[0];
|
|
40
|
+
}
|
|
41
|
+
})
|
|
42
|
+
];
|
|
43
|
+
case 2:
|
|
44
|
+
remoteReact = _state.sent();
|
|
45
|
+
if (!remoteReact || !remoteReactDOM) {
|
|
46
|
+
return [
|
|
47
|
+
2,
|
|
48
|
+
null
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
return [
|
|
52
|
+
4,
|
|
53
|
+
import("./FallBack")
|
|
54
|
+
];
|
|
55
|
+
case 3:
|
|
56
|
+
res = _state.sent().FallBack;
|
|
57
|
+
return [
|
|
58
|
+
2,
|
|
59
|
+
function() {
|
|
60
|
+
return res({
|
|
61
|
+
Original: args.exposeModule.default,
|
|
62
|
+
remoteVersion: function() {
|
|
63
|
+
return remoteVersion;
|
|
64
|
+
},
|
|
65
|
+
hostVersion: function() {
|
|
66
|
+
return hostVersion;
|
|
67
|
+
},
|
|
68
|
+
remoteReactDOM: remoteReactDOM,
|
|
69
|
+
remoteReact: remoteReact
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
];
|
|
73
|
+
case 4:
|
|
74
|
+
return [
|
|
75
|
+
2,
|
|
76
|
+
null
|
|
77
|
+
];
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
return function loadRemotePackagedReactAndRender(args) {
|
|
82
|
+
return _ref.apply(this, arguments);
|
|
83
|
+
};
|
|
84
|
+
}();
|
|
85
|
+
export var runtimePlugin = function() {
|
|
86
|
+
return {
|
|
87
|
+
name: "ice-runtime-plugin",
|
|
88
|
+
afterResolve: function afterResolve(args) {
|
|
89
|
+
var _extraInfo;
|
|
90
|
+
var hostName = args.options.name;
|
|
91
|
+
var remoteName = args.remote.name;
|
|
92
|
+
var extraInfo = getExtraInfo(hostName, remoteName);
|
|
93
|
+
if ((_extraInfo = extraInfo) === null || _extraInfo === void 0 ? void 0 : _extraInfo.legacy) {
|
|
94
|
+
if (args.expose.startsWith("./")) {
|
|
95
|
+
args.expose = args.expose.slice(2);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return args;
|
|
99
|
+
},
|
|
100
|
+
onLoad: function onLoad(args) {
|
|
101
|
+
return _async_to_generator(function() {
|
|
102
|
+
var _args_origin_options_shared_reactdom_, _args_origin_options_shared_reactdom, _args_origin_options_shared, _args_origin_options, _extraInfo, hostName, remoteName, hostVersion, extraInfo, externalReact, externalReactDOM, remoteReact, remoteReactDOM, res, fallBackRender;
|
|
103
|
+
return _ts_generator(this, function(_state) {
|
|
104
|
+
switch(_state.label){
|
|
105
|
+
case 0:
|
|
106
|
+
hostName = args.origin.name;
|
|
107
|
+
remoteName = args.remote.name;
|
|
108
|
+
hostVersion = ((_args_origin_options = args.origin.options) === null || _args_origin_options === void 0 ? void 0 : (_args_origin_options_shared = _args_origin_options.shared) === null || _args_origin_options_shared === void 0 ? void 0 : (_args_origin_options_shared_reactdom = _args_origin_options_shared["react-dom"]) === null || _args_origin_options_shared_reactdom === void 0 ? void 0 : (_args_origin_options_shared_reactdom_ = _args_origin_options_shared_reactdom[0]) === null || _args_origin_options_shared_reactdom_ === void 0 ? void 0 : _args_origin_options_shared_reactdom_.version) || React.version;
|
|
109
|
+
extraInfo = getExtraInfo(hostName, remoteName);
|
|
110
|
+
if (!((_extraInfo = extraInfo) === null || _extraInfo === void 0 ? void 0 : _extraInfo.external)) return [
|
|
111
|
+
3,
|
|
112
|
+
2
|
|
113
|
+
];
|
|
114
|
+
externalReact = extraInfo.external["react"];
|
|
115
|
+
externalReactDOM = extraInfo.external["react-dom"];
|
|
116
|
+
if (!(externalReact && externalReactDOM)) return [
|
|
117
|
+
3,
|
|
118
|
+
2
|
|
119
|
+
];
|
|
120
|
+
remoteReact = function() {
|
|
121
|
+
return window[externalReact];
|
|
122
|
+
};
|
|
123
|
+
remoteReactDOM = function() {
|
|
124
|
+
return window[externalReactDOM];
|
|
125
|
+
};
|
|
126
|
+
if (remoteReactDOM().version === hostVersion) {
|
|
127
|
+
console.log("[runtime Plugin onLoad] use same external react");
|
|
128
|
+
return [
|
|
129
|
+
2,
|
|
130
|
+
args
|
|
131
|
+
];
|
|
132
|
+
}
|
|
133
|
+
return [
|
|
134
|
+
4,
|
|
135
|
+
import("./FallBack")
|
|
136
|
+
];
|
|
137
|
+
case 1:
|
|
138
|
+
res = _state.sent().FallBack;
|
|
139
|
+
return [
|
|
140
|
+
2,
|
|
141
|
+
function() {
|
|
142
|
+
return res({
|
|
143
|
+
Original: args.exposeModule.default,
|
|
144
|
+
remoteReactDOM: remoteReactDOM,
|
|
145
|
+
remoteReact: remoteReact
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
];
|
|
149
|
+
case 2:
|
|
150
|
+
return [
|
|
151
|
+
4,
|
|
152
|
+
loadRemotePackagedReactAndRender(args)
|
|
153
|
+
];
|
|
154
|
+
case 3:
|
|
155
|
+
fallBackRender = _state.sent();
|
|
156
|
+
if (fallBackRender) {
|
|
157
|
+
return [
|
|
158
|
+
2,
|
|
159
|
+
fallBackRender
|
|
160
|
+
];
|
|
161
|
+
}
|
|
162
|
+
return [
|
|
163
|
+
2,
|
|
164
|
+
args
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
})();
|
|
169
|
+
},
|
|
170
|
+
beforeRequest: function beforeRequest(args) {
|
|
171
|
+
return _async_to_generator(function() {
|
|
172
|
+
var remoteName, hostName, newRemoteInfo, requestRemote, hostInstance;
|
|
173
|
+
return _ts_generator(this, function(_state) {
|
|
174
|
+
remoteName = args.id.split("/")[0];
|
|
175
|
+
hostName = args.options.name;
|
|
176
|
+
if (!hasConflict(hostName, remoteName)) {
|
|
177
|
+
return [
|
|
178
|
+
2,
|
|
179
|
+
args
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
newRemoteInfo = getRemoteInfoFromStore(hostName, remoteName);
|
|
183
|
+
if (!newRemoteInfo) {
|
|
184
|
+
return [
|
|
185
|
+
2,
|
|
186
|
+
args
|
|
187
|
+
];
|
|
188
|
+
}
|
|
189
|
+
requestRemote = args.options.remotes.find(function(remote) {
|
|
190
|
+
return remote.name === remoteName;
|
|
191
|
+
});
|
|
192
|
+
if (requestRemote) {
|
|
193
|
+
requestRemote.entry = newRemoteInfo.entry;
|
|
194
|
+
}
|
|
195
|
+
hostInstance = __FEDERATION__.__INSTANCES__.find(function(instance) {
|
|
196
|
+
return instance.name === hostName;
|
|
197
|
+
});
|
|
198
|
+
if (hostInstance) {
|
|
199
|
+
hostInstance.moduleCache.delete(remoteName);
|
|
200
|
+
hostInstance.options.remotes.find(function(remote) {
|
|
201
|
+
return remote.name === remoteName;
|
|
202
|
+
}).entry = newRemoteInfo.entry;
|
|
203
|
+
}
|
|
204
|
+
args.origin.moduleCache.delete(remoteName);
|
|
205
|
+
// @ts-expect-error for global module
|
|
206
|
+
window[remoteName] = null;
|
|
207
|
+
return [
|
|
208
|
+
2,
|
|
209
|
+
args
|
|
210
|
+
];
|
|
211
|
+
});
|
|
212
|
+
})();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export var ensureSlash = function(input, needSlash, position) {
|
|
2
|
+
if (input == null) return input;
|
|
3
|
+
if (position === "head") {
|
|
4
|
+
var startWithSlash = input.startsWith("/");
|
|
5
|
+
if (startWithSlash && !needSlash) {
|
|
6
|
+
return input.slice(1);
|
|
7
|
+
} else if (!startWithSlash && needSlash) {
|
|
8
|
+
return "/".concat(input);
|
|
9
|
+
}
|
|
10
|
+
return input;
|
|
11
|
+
} else if (position === "tail") {
|
|
12
|
+
var endsWithSlash = input.endsWith("/");
|
|
13
|
+
if (endsWithSlash && !needSlash) {
|
|
14
|
+
return input.substr(0, input.length - 1);
|
|
15
|
+
} else if (!endsWithSlash && needSlash) {
|
|
16
|
+
return "".concat(input, "/");
|
|
17
|
+
} else {
|
|
18
|
+
return input;
|
|
19
|
+
}
|
|
20
|
+
} else {
|
|
21
|
+
return input;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export var setFederatedModulePublicPath = function(scope, publicPath) {
|
|
25
|
+
var publicPathReference = "".concat(scope, "_public_path");
|
|
26
|
+
// @ts-expect-error for global public path
|
|
27
|
+
window[publicPathReference] = ensureSlash(publicPath, true, "tail");
|
|
28
|
+
};
|
package/esm/types.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { UserOptions } from '@module-federation/runtime-core';
|
|
2
|
+
import type { Remote } from '@module-federation/runtime-core/dist/src/types';
|
|
3
|
+
export interface ExtraInfo {
|
|
4
|
+
external?: Record<string, string>;
|
|
5
|
+
legacy?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export type ExtendedRemote = Remote & {
|
|
8
|
+
extraInfo?: ExtraInfo;
|
|
9
|
+
};
|
|
10
|
+
export interface ExtendedUserOptions extends Omit<UserOptions, 'remotes'> {
|
|
11
|
+
remotes: ExtendedRemote[];
|
|
12
|
+
}
|
package/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/esm/typings.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="@ice/pkg/types" />
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ice/mf-runtime",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "组件功能描述",
|
|
5
|
+
"files": [
|
|
6
|
+
"esm",
|
|
7
|
+
"es2017",
|
|
8
|
+
"cjs",
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"main": "esm/index.js",
|
|
12
|
+
"module": "esm/index.js",
|
|
13
|
+
"types": "esm/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"es2017": {
|
|
17
|
+
"types": "./es2017/index.d.ts",
|
|
18
|
+
"default": "./es2017/index.js"
|
|
19
|
+
},
|
|
20
|
+
"default": {
|
|
21
|
+
"types": "./esm/index.d.ts",
|
|
22
|
+
"default": "./esm/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"./*": "./*"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": [
|
|
28
|
+
"dist/*",
|
|
29
|
+
"*.scss",
|
|
30
|
+
"*.less",
|
|
31
|
+
"*.css"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"start": "ice-pkg start",
|
|
35
|
+
"build": "ice-pkg build",
|
|
36
|
+
"prepublishOnly": "npm run build",
|
|
37
|
+
"eslint": "eslint --cache --ext .js,.jsx,.ts,.tsx ./",
|
|
38
|
+
"eslint:fix": "npm run eslint -- --fix",
|
|
39
|
+
"stylelint": "stylelint \"**/*.{css,scss,less}\"",
|
|
40
|
+
"lint": "npm run eslint && npm run stylelint"
|
|
41
|
+
},
|
|
42
|
+
"keywords": [
|
|
43
|
+
"ice",
|
|
44
|
+
"react",
|
|
45
|
+
"component"
|
|
46
|
+
],
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@ice/jsx-runtime": "^0.2.0",
|
|
49
|
+
"@module-federation/runtime": "^0.11.2",
|
|
50
|
+
"@module-federation/runtime-core": "^0.11.2",
|
|
51
|
+
"@swc/helpers": "^0.5.1"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@ali/pkg-plugin-dev": "^1.0.0",
|
|
55
|
+
"@ali/pkg-plugin-dev-client": "^1.0.0",
|
|
56
|
+
"@applint/spec": "^1.2.3",
|
|
57
|
+
"@ice/pkg": "^1.0.0",
|
|
58
|
+
"@ice/runtime": "^1.0.0",
|
|
59
|
+
"@types/react": "^18.0.0",
|
|
60
|
+
"@types/react-dom": "^18.0.0",
|
|
61
|
+
"eslint": "^8.0.0",
|
|
62
|
+
"react": "^18.0.0",
|
|
63
|
+
"react-dom": "^18.0.0",
|
|
64
|
+
"stylelint": "^15.0.0"
|
|
65
|
+
},
|
|
66
|
+
"publishConfig": {
|
|
67
|
+
"access": "public"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"react": "^16 || ^17 || ^18"
|
|
71
|
+
},
|
|
72
|
+
"license": "MIT"
|
|
73
|
+
}
|