@module-federation/bridge-react 0.0.0-fix-lazy-comile-20250925082726
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/CHANGELOG.md +657 -0
- package/LICENSE +21 -0
- package/README.md +131 -0
- package/__tests__/bridge.spec.tsx +137 -0
- package/__tests__/createLazyComponent.spec.tsx +209 -0
- package/__tests__/prefetch.spec.ts +156 -0
- package/__tests__/router.spec.tsx +82 -0
- package/__tests__/setupTests.ts +8 -0
- package/__tests__/util.ts +36 -0
- package/dist/bridge-base-BwHtOqw_.mjs +199 -0
- package/dist/bridge-base-Ds850AOx.js +214 -0
- package/dist/data-fetch-server-middleware.cjs.js +163 -0
- package/dist/data-fetch-server-middleware.d.ts +15 -0
- package/dist/data-fetch-server-middleware.es.js +164 -0
- package/dist/data-fetch-utils.cjs.js +24 -0
- package/dist/data-fetch-utils.d.ts +81 -0
- package/dist/data-fetch-utils.es.js +26 -0
- package/dist/index-eN2xRRXs.js +45 -0
- package/dist/index-rAO0Wr0M.mjs +46 -0
- package/dist/index.cjs.js +293 -0
- package/dist/index.d.ts +274 -0
- package/dist/index.es.js +276 -0
- package/dist/index.esm-CtI0uQUR.mjs +430 -0
- package/dist/index.esm-Ju4RY-yW.js +429 -0
- package/dist/lazy-load-component-plugin-BLfwTMtM.mjs +522 -0
- package/dist/lazy-load-component-plugin-C0zAoMq3.js +521 -0
- package/dist/lazy-load-component-plugin.cjs.js +6 -0
- package/dist/lazy-load-component-plugin.d.ts +16 -0
- package/dist/lazy-load-component-plugin.es.js +6 -0
- package/dist/lazy-utils.cjs.js +24 -0
- package/dist/lazy-utils.d.ts +149 -0
- package/dist/lazy-utils.es.js +24 -0
- package/dist/plugin.cjs.js +14 -0
- package/dist/plugin.d.ts +22 -0
- package/dist/plugin.es.js +14 -0
- package/dist/prefetch-BkgTf4W6.mjs +1371 -0
- package/dist/prefetch-DX29k_gH.js +1370 -0
- package/dist/router-v5.cjs.js +55 -0
- package/dist/router-v5.d.ts +18 -0
- package/dist/router-v5.es.js +32 -0
- package/dist/router-v6.cjs.js +84 -0
- package/dist/router-v6.d.ts +20 -0
- package/dist/router-v6.es.js +61 -0
- package/dist/router.cjs.js +82 -0
- package/dist/router.d.ts +20 -0
- package/dist/router.es.js +60 -0
- package/dist/utils-VSOJTX_o.mjs +2016 -0
- package/dist/utils-vIpCrZmn.js +2015 -0
- package/dist/v18.cjs.js +15 -0
- package/dist/v18.d.ts +114 -0
- package/dist/v18.es.js +15 -0
- package/dist/v19.cjs.js +15 -0
- package/dist/v19.d.ts +115 -0
- package/dist/v19.es.js +15 -0
- package/jest.config.ts +21 -0
- package/package.json +129 -0
- package/project.json +23 -0
- package/src/index.ts +45 -0
- package/src/lazy/AwaitDataFetch.tsx +215 -0
- package/src/lazy/constant.ts +30 -0
- package/src/lazy/createLazyComponent.tsx +411 -0
- package/src/lazy/data-fetch/cache.ts +291 -0
- package/src/lazy/data-fetch/call-data-fetch.ts +13 -0
- package/src/lazy/data-fetch/data-fetch-server-middleware.ts +196 -0
- package/src/lazy/data-fetch/index.ts +16 -0
- package/src/lazy/data-fetch/inject-data-fetch.ts +109 -0
- package/src/lazy/data-fetch/prefetch.ts +112 -0
- package/src/lazy/data-fetch/runtime-plugin.ts +115 -0
- package/src/lazy/index.ts +35 -0
- package/src/lazy/logger.ts +6 -0
- package/src/lazy/types.ts +75 -0
- package/src/lazy/utils.ts +372 -0
- package/src/lazy/wrapNoSSR.tsx +10 -0
- package/src/modern-app-env.d.ts +2 -0
- package/src/plugins/lazy-load-component-plugin.spec.ts +21 -0
- package/src/plugins/lazy-load-component-plugin.ts +57 -0
- package/src/provider/context.tsx +4 -0
- package/src/provider/plugin.ts +22 -0
- package/src/provider/versions/bridge-base.tsx +122 -0
- package/src/provider/versions/legacy.ts +86 -0
- package/src/provider/versions/v18.ts +47 -0
- package/src/provider/versions/v19.ts +48 -0
- package/src/remote/component.tsx +211 -0
- package/src/remote/create.tsx +103 -0
- package/src/router/default.tsx +73 -0
- package/src/router/v5.tsx +43 -0
- package/src/router/v6.tsx +74 -0
- package/src/types.ts +147 -0
- package/src/utils/index.ts +44 -0
- package/src/v18.ts +9 -0
- package/src/v19.ts +9 -0
- package/tsconfig.json +42 -0
- package/tsconfig.node.json +11 -0
- package/tsconfig.spec.json +26 -0
- package/vite.config.ts +87 -0
- package/vitest.config.ts +27 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
|
|
3
|
+
import { LoggerInstance } from '../utils';
|
|
4
|
+
import RemoteApp from './component';
|
|
5
|
+
import {
|
|
6
|
+
RemoteComponentParams,
|
|
7
|
+
RemoteComponentProps,
|
|
8
|
+
RemoteModule,
|
|
9
|
+
} from '../types';
|
|
10
|
+
|
|
11
|
+
type LazyRemoteComponentInfo<T, _E extends keyof T> = RemoteComponentParams<T>;
|
|
12
|
+
|
|
13
|
+
function createLazyRemoteComponent<
|
|
14
|
+
T = Record<string, unknown>,
|
|
15
|
+
E extends keyof T = keyof T,
|
|
16
|
+
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
17
|
+
const exportName = info?.export || 'default';
|
|
18
|
+
return React.lazy(async () => {
|
|
19
|
+
LoggerInstance.debug(`createRemoteAppComponent LazyComponent create >>>`, {
|
|
20
|
+
lazyComponent: info.loader,
|
|
21
|
+
exportName,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const m = (await info.loader()) as RemoteModule;
|
|
26
|
+
// @ts-ignore
|
|
27
|
+
const moduleName = m && m[Symbol.for('mf_module_id')];
|
|
28
|
+
LoggerInstance.debug(
|
|
29
|
+
`createRemoteAppComponent LazyComponent loadRemote info >>>`,
|
|
30
|
+
{ name: moduleName, module: m, exportName },
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
// @ts-ignore
|
|
34
|
+
const exportFn = m[exportName];
|
|
35
|
+
if (exportName in m && typeof exportFn === 'function') {
|
|
36
|
+
const RemoteAppComponent = forwardRef<
|
|
37
|
+
HTMLDivElement,
|
|
38
|
+
RemoteComponentProps
|
|
39
|
+
>((props, ref) => {
|
|
40
|
+
return (
|
|
41
|
+
<RemoteApp
|
|
42
|
+
// change `name` key to `moduleName` to avoid same property `name` passed by user's props which may cause unexpected issues.
|
|
43
|
+
moduleName={moduleName}
|
|
44
|
+
providerInfo={exportFn}
|
|
45
|
+
exportName={info.export || 'default'}
|
|
46
|
+
fallback={info.fallback}
|
|
47
|
+
loading={info.loading}
|
|
48
|
+
ref={ref}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
default: RemoteAppComponent,
|
|
56
|
+
};
|
|
57
|
+
} else {
|
|
58
|
+
LoggerInstance.debug(
|
|
59
|
+
`createRemoteAppComponent LazyComponent module not found >>>`,
|
|
60
|
+
{ name: moduleName, module: m, exportName },
|
|
61
|
+
);
|
|
62
|
+
throw Error(
|
|
63
|
+
`Make sure that ${moduleName} has the correct export when export is ${String(
|
|
64
|
+
exportName,
|
|
65
|
+
)}`,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function createRemoteAppComponent<
|
|
75
|
+
T = Record<string, unknown>,
|
|
76
|
+
E extends keyof T = keyof T,
|
|
77
|
+
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
78
|
+
const LazyComponent = createLazyRemoteComponent(info);
|
|
79
|
+
return forwardRef<HTMLDivElement, RemoteComponentProps>((props, ref) => {
|
|
80
|
+
return (
|
|
81
|
+
<ErrorBoundary
|
|
82
|
+
FallbackComponent={info.fallback as React.ComponentType<FallbackProps>}
|
|
83
|
+
>
|
|
84
|
+
<React.Suspense fallback={info.loading}>
|
|
85
|
+
<LazyComponent {...props} ref={ref} />
|
|
86
|
+
</React.Suspense>
|
|
87
|
+
</ErrorBoundary>
|
|
88
|
+
);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* @deprecated createRemoteAppComponent is deprecated, please use createRemoteAppComponent instead!
|
|
94
|
+
*/
|
|
95
|
+
export function createRemoteComponent<
|
|
96
|
+
T = Record<string, unknown>,
|
|
97
|
+
E extends keyof T = keyof T,
|
|
98
|
+
>(info: LazyRemoteComponentInfo<T, E>) {
|
|
99
|
+
LoggerInstance.warn(
|
|
100
|
+
`createRemoteComponent is deprecated, please use createRemoteAppComponent instead!`,
|
|
101
|
+
);
|
|
102
|
+
return createRemoteAppComponent(info);
|
|
103
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
// The upper alias react-router-dom$ into this file avoids the loop
|
|
3
|
+
import * as ReactRouterDom from 'react-router-dom/';
|
|
4
|
+
import { RouterContext } from '../provider/context';
|
|
5
|
+
import { LoggerInstance } from '../utils';
|
|
6
|
+
|
|
7
|
+
function WrapperRouter(
|
|
8
|
+
props:
|
|
9
|
+
| Parameters<typeof ReactRouterDom.BrowserRouter>[0]
|
|
10
|
+
| Parameters<typeof ReactRouterDom.MemoryRouter>[0],
|
|
11
|
+
) {
|
|
12
|
+
const { basename, ...propsRes } = props;
|
|
13
|
+
const routerContextProps = useContext(RouterContext) || {};
|
|
14
|
+
|
|
15
|
+
LoggerInstance.debug(`WrapperRouter info >>>`, {
|
|
16
|
+
...routerContextProps,
|
|
17
|
+
routerContextProps,
|
|
18
|
+
WrapperRouterProps: props,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (routerContextProps?.memoryRoute) {
|
|
22
|
+
return (
|
|
23
|
+
<ReactRouterDom.MemoryRouter
|
|
24
|
+
{...props}
|
|
25
|
+
initialEntries={[routerContextProps?.memoryRoute.entryPath]}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return (
|
|
30
|
+
<ReactRouterDom.BrowserRouter
|
|
31
|
+
{...propsRes}
|
|
32
|
+
basename={routerContextProps?.basename || basename}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function WrapperRouterProvider(
|
|
38
|
+
props: Parameters<typeof ReactRouterDom.RouterProvider>[0],
|
|
39
|
+
) {
|
|
40
|
+
const { router, ...propsRes } = props;
|
|
41
|
+
const routerContextProps = useContext(RouterContext) || {};
|
|
42
|
+
const routers = router.routes;
|
|
43
|
+
LoggerInstance.debug(`WrapperRouterProvider info >>>`, {
|
|
44
|
+
...routerContextProps,
|
|
45
|
+
routerContextProps,
|
|
46
|
+
WrapperRouterProviderProps: props,
|
|
47
|
+
router,
|
|
48
|
+
});
|
|
49
|
+
const RouterProvider = (ReactRouterDom as any)['Router' + 'Provider'];
|
|
50
|
+
const createMemoryRouter = (ReactRouterDom as any)['create' + 'MemoryRouter'];
|
|
51
|
+
const createBrowserRouter = (ReactRouterDom as any)[
|
|
52
|
+
'create' + 'BrowserRouter'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (routerContextProps.memoryRoute) {
|
|
56
|
+
const MemeoryRouterInstance = createMemoryRouter(routers, {
|
|
57
|
+
initialEntries: [routerContextProps?.memoryRoute.entryPath],
|
|
58
|
+
});
|
|
59
|
+
return <RouterProvider router={MemeoryRouterInstance} />;
|
|
60
|
+
} else {
|
|
61
|
+
const BrowserRouterInstance = createBrowserRouter(routers, {
|
|
62
|
+
basename: routerContextProps.basename || router?.basename,
|
|
63
|
+
future: router.future,
|
|
64
|
+
window: router.window,
|
|
65
|
+
});
|
|
66
|
+
return <RouterProvider {...propsRes} router={BrowserRouterInstance} />;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export * from 'react-router-dom/';
|
|
71
|
+
|
|
72
|
+
export { WrapperRouter as BrowserRouter };
|
|
73
|
+
export { WrapperRouterProvider as RouterProvider };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
// The upper alias react-router-dom$ into this file avoids the loop
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import * as ReactRouterDom from 'react-router-dom/index.js';
|
|
5
|
+
import { RouterContext } from '../provider/context';
|
|
6
|
+
import { LoggerInstance } from '../utils';
|
|
7
|
+
|
|
8
|
+
function WraperRouter(
|
|
9
|
+
props:
|
|
10
|
+
| Parameters<typeof ReactRouterDom.BrowserRouter>[0]
|
|
11
|
+
| Parameters<typeof ReactRouterDom.MemoryRouter>[0],
|
|
12
|
+
) {
|
|
13
|
+
const { basename, ...propsRes } = props;
|
|
14
|
+
const routerContextProps = useContext(RouterContext) || {};
|
|
15
|
+
|
|
16
|
+
LoggerInstance.debug(`WraperRouter info >>>`, {
|
|
17
|
+
...routerContextProps,
|
|
18
|
+
routerContextProps,
|
|
19
|
+
WraperRouterProps: props,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (routerContextProps?.memoryRoute) {
|
|
23
|
+
return (
|
|
24
|
+
<ReactRouterDom.MemoryRouter
|
|
25
|
+
{...props}
|
|
26
|
+
initialEntries={[routerContextProps?.memoryRoute.entryPath]}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
return (
|
|
31
|
+
<ReactRouterDom.BrowserRouter
|
|
32
|
+
{...propsRes}
|
|
33
|
+
basename={routerContextProps?.basename || basename}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
// because export directly from react-router-dom/index.js will cause build falied.
|
|
40
|
+
// it will be replace by react-router-dom/index.js in building phase
|
|
41
|
+
export * from 'react-router-dom/';
|
|
42
|
+
|
|
43
|
+
export { WraperRouter as BrowserRouter };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import React, { useContext } from 'react';
|
|
2
|
+
// The upper alias react-router-dom$ into this file avoids the loop
|
|
3
|
+
import * as ReactRouterDom from 'react-router-dom/dist/index.js';
|
|
4
|
+
import { RouterContext } from '../provider/context';
|
|
5
|
+
import { LoggerInstance } from '../utils';
|
|
6
|
+
|
|
7
|
+
function WraperRouter(
|
|
8
|
+
props:
|
|
9
|
+
| Parameters<typeof ReactRouterDom.BrowserRouter>[0]
|
|
10
|
+
| Parameters<typeof ReactRouterDom.MemoryRouter>[0],
|
|
11
|
+
) {
|
|
12
|
+
const { basename, ...propsRes } = props;
|
|
13
|
+
const routerContextProps = useContext(RouterContext) || {};
|
|
14
|
+
|
|
15
|
+
LoggerInstance.debug(`WraperRouter info >>>`, {
|
|
16
|
+
...routerContextProps,
|
|
17
|
+
routerContextProps,
|
|
18
|
+
WraperRouterProps: props,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
if (routerContextProps?.memoryRoute) {
|
|
22
|
+
return (
|
|
23
|
+
<ReactRouterDom.MemoryRouter
|
|
24
|
+
{...props}
|
|
25
|
+
initialEntries={[routerContextProps?.memoryRoute.entryPath]}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
return (
|
|
30
|
+
<ReactRouterDom.BrowserRouter
|
|
31
|
+
{...propsRes}
|
|
32
|
+
basename={routerContextProps?.basename || basename}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function WraperRouterProvider(
|
|
38
|
+
props: Parameters<typeof ReactRouterDom.RouterProvider>[0],
|
|
39
|
+
) {
|
|
40
|
+
const { router, ...propsRes } = props;
|
|
41
|
+
const routerContextProps = useContext(RouterContext) || {};
|
|
42
|
+
const routers = router.routes;
|
|
43
|
+
LoggerInstance.debug(`WraperRouterProvider info >>>`, {
|
|
44
|
+
...routerContextProps,
|
|
45
|
+
routerContextProps,
|
|
46
|
+
WraperRouterProviderProps: props,
|
|
47
|
+
router,
|
|
48
|
+
});
|
|
49
|
+
const RouterProvider = (ReactRouterDom as any)['Router' + 'Provider'];
|
|
50
|
+
const createMemoryRouter = (ReactRouterDom as any)['create' + 'MemoryRouter'];
|
|
51
|
+
const createBrowserRouter = (ReactRouterDom as any)[
|
|
52
|
+
'create' + 'BrowserRouter'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
if (routerContextProps.memoryRoute) {
|
|
56
|
+
const MemeoryRouterInstance = createMemoryRouter(routers, {
|
|
57
|
+
initialEntries: [routerContextProps?.memoryRoute.entryPath],
|
|
58
|
+
});
|
|
59
|
+
return <RouterProvider router={MemeoryRouterInstance} />;
|
|
60
|
+
} else {
|
|
61
|
+
const BrowserRouterInstance = createBrowserRouter(routers, {
|
|
62
|
+
// In host app, the routerContextProps is {}, so we should use router.basename as fallback
|
|
63
|
+
basename: routerContextProps.basename || router.basename,
|
|
64
|
+
future: router.future,
|
|
65
|
+
window: router.window,
|
|
66
|
+
});
|
|
67
|
+
return <RouterProvider {...propsRes} router={BrowserRouterInstance} />;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// export * from 'react-router-dom/dist/index.js';
|
|
72
|
+
export * from 'react-router-dom/';
|
|
73
|
+
export { WraperRouter as BrowserRouter };
|
|
74
|
+
export { WraperRouterProvider as RouterProvider };
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ErrorBoundaryPropsWithComponent } from 'react-error-boundary';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Options for creating a React root
|
|
6
|
+
*/
|
|
7
|
+
export interface CreateRootOptions {
|
|
8
|
+
identifierPrefix?: string;
|
|
9
|
+
onRecoverableError?: (error: unknown) => void;
|
|
10
|
+
transitionCallbacks?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Interface for a React root object
|
|
15
|
+
*/
|
|
16
|
+
export interface Root {
|
|
17
|
+
render(children: React.ReactNode): void;
|
|
18
|
+
unmount(): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Type for a root element, which can be either an HTMLElement or a React root
|
|
23
|
+
*/
|
|
24
|
+
export type RootType = HTMLElement | Root;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Parameters for the render function
|
|
28
|
+
*/
|
|
29
|
+
export interface RenderParams {
|
|
30
|
+
moduleName?: string;
|
|
31
|
+
basename?: string;
|
|
32
|
+
memoryRoute?: {
|
|
33
|
+
entryPath: string;
|
|
34
|
+
initialState?: Record<string, unknown>;
|
|
35
|
+
};
|
|
36
|
+
dom: HTMLElement;
|
|
37
|
+
/**
|
|
38
|
+
* Options to pass to createRoot for React 18 and 19
|
|
39
|
+
* @example
|
|
40
|
+
* {
|
|
41
|
+
* identifierPrefix: 'app-',
|
|
42
|
+
* onRecoverableError: (err) => console.error(err)
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
rootOptions?: CreateRootOptions;
|
|
46
|
+
[key: string]: unknown;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Parameters for the destroy function
|
|
51
|
+
*/
|
|
52
|
+
export interface DestroyParams {
|
|
53
|
+
moduleName: string;
|
|
54
|
+
dom: HTMLElement;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parameters for the provider function
|
|
59
|
+
*/
|
|
60
|
+
export interface ProviderParams {
|
|
61
|
+
moduleName?: string;
|
|
62
|
+
basename?: string;
|
|
63
|
+
memoryRoute?: {
|
|
64
|
+
entryPath: string;
|
|
65
|
+
initialState?: Record<string, unknown>;
|
|
66
|
+
};
|
|
67
|
+
style?: React.CSSProperties;
|
|
68
|
+
className?: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Parameters for the render function, extending ProviderParams
|
|
73
|
+
*/
|
|
74
|
+
export interface RenderFnParams extends ProviderParams {
|
|
75
|
+
dom: HTMLElement;
|
|
76
|
+
fallback?: React.ComponentType<{ error: Error }>;
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Parameters for the provider function
|
|
82
|
+
*/
|
|
83
|
+
export interface ProviderFnParams<T> {
|
|
84
|
+
rootComponent: React.ComponentType<T>;
|
|
85
|
+
render?: (
|
|
86
|
+
App: React.ReactElement,
|
|
87
|
+
id?: HTMLElement | string,
|
|
88
|
+
) => RootType | Promise<RootType>;
|
|
89
|
+
createRoot?: (
|
|
90
|
+
container: Element | DocumentFragment,
|
|
91
|
+
options?: CreateRootOptions,
|
|
92
|
+
) => Root;
|
|
93
|
+
/**
|
|
94
|
+
* Default options to pass to createRoot for React 18 and 19
|
|
95
|
+
* These options will be used when creating a root unless overridden by rootOptions in render params
|
|
96
|
+
* @example
|
|
97
|
+
* {
|
|
98
|
+
* identifierPrefix: 'app-',
|
|
99
|
+
* onRecoverableError: (err) => console.error(err)
|
|
100
|
+
* }
|
|
101
|
+
*/
|
|
102
|
+
defaultRootOptions?: CreateRootOptions;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Parameters for the remote component
|
|
107
|
+
*/
|
|
108
|
+
export interface RemoteComponentProps<T = Record<string, unknown>> {
|
|
109
|
+
props?: T;
|
|
110
|
+
fallback?: React.ComponentType<{ error: Error }>;
|
|
111
|
+
loading?: React.ReactNode;
|
|
112
|
+
[key: string]: unknown;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Parameters for the remote component loader
|
|
117
|
+
*/
|
|
118
|
+
export interface RemoteComponentParams<
|
|
119
|
+
T = Record<string, unknown>,
|
|
120
|
+
E extends keyof T = keyof T,
|
|
121
|
+
> {
|
|
122
|
+
loader: () => Promise<T>;
|
|
123
|
+
loading: React.ReactNode;
|
|
124
|
+
fallback: React.ComponentType<{ error: Error }>;
|
|
125
|
+
export?: E;
|
|
126
|
+
props?: T;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Interface for a remote module provider
|
|
131
|
+
*/
|
|
132
|
+
export interface RemoteModule {
|
|
133
|
+
provider: () => {
|
|
134
|
+
render: (info: RenderFnParams) => void;
|
|
135
|
+
destroy: (info: { dom: any }) => void;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Parameters for a remote app component
|
|
141
|
+
*/
|
|
142
|
+
export interface RemoteAppParams extends ProviderParams {
|
|
143
|
+
moduleName: string;
|
|
144
|
+
providerInfo: NonNullable<RemoteModule['provider']>;
|
|
145
|
+
exportName: string | number | symbol;
|
|
146
|
+
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
|
|
147
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { createLogger } from '@module-federation/sdk';
|
|
2
|
+
|
|
3
|
+
export const LoggerInstance = createLogger(
|
|
4
|
+
'[ Module Federation Bridge React ]',
|
|
5
|
+
);
|
|
6
|
+
|
|
7
|
+
export function pathJoin(...args: string[]) {
|
|
8
|
+
const res = args.reduce((res, path: string) => {
|
|
9
|
+
let nPath = path;
|
|
10
|
+
if (!nPath || typeof nPath !== 'string') {
|
|
11
|
+
return res;
|
|
12
|
+
}
|
|
13
|
+
if (nPath[0] !== '/') {
|
|
14
|
+
nPath = `/${nPath}`;
|
|
15
|
+
}
|
|
16
|
+
const lastIndex = nPath.length - 1;
|
|
17
|
+
if (nPath[lastIndex] === '/') {
|
|
18
|
+
nPath = nPath.substring(0, lastIndex);
|
|
19
|
+
}
|
|
20
|
+
return res + nPath;
|
|
21
|
+
}, '');
|
|
22
|
+
return res || '/';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const getModuleName = (id: string) => {
|
|
26
|
+
if (!id) {
|
|
27
|
+
return id;
|
|
28
|
+
}
|
|
29
|
+
// separate module name without detailed module path
|
|
30
|
+
// @vmok-e2e/edenx-demo-app2/button -> @vmok-e2e/edenx-demo-app2
|
|
31
|
+
const idArray = id.split('/');
|
|
32
|
+
if (idArray.length < 2) {
|
|
33
|
+
return id;
|
|
34
|
+
}
|
|
35
|
+
return idArray[0] + '/' + idArray[1];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const getRootDomDefaultClassName = (moduleName: string) => {
|
|
39
|
+
if (!moduleName) {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
const name = getModuleName(moduleName).replace(/\@/, '').replace(/\//, '-');
|
|
43
|
+
return `bridge-root-component-${name}`;
|
|
44
|
+
};
|
package/src/v18.ts
ADDED
package/src/v19.ts
ADDED
package/tsconfig.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"useDefineForClassFields": true,
|
|
4
|
+
|
|
5
|
+
/* Bundler mode */
|
|
6
|
+
"allowImportingTsExtensions": true,
|
|
7
|
+
"resolveJsonModule": true,
|
|
8
|
+
|
|
9
|
+
"declarationDir": "./dist/types",
|
|
10
|
+
"rootDir": "./src",
|
|
11
|
+
"module": "commonjs",
|
|
12
|
+
"target": "es2015",
|
|
13
|
+
|
|
14
|
+
/* Linting */
|
|
15
|
+
"noUnusedLocals": true,
|
|
16
|
+
"noUnusedParameters": true,
|
|
17
|
+
"noFallthroughCasesInSwitch": true,
|
|
18
|
+
"declaration": true,
|
|
19
|
+
"emitDeclarationOnly": true,
|
|
20
|
+
"outDir": "dist",
|
|
21
|
+
"skipLibCheck": true,
|
|
22
|
+
"strict": true,
|
|
23
|
+
"moduleResolution": "node",
|
|
24
|
+
"lib": ["esnext", "dom"],
|
|
25
|
+
"jsx": "preserve",
|
|
26
|
+
"esModuleInterop": true,
|
|
27
|
+
"allowSyntheticDefaultImports": true,
|
|
28
|
+
"sourceMap": true,
|
|
29
|
+
"baseUrl": ".",
|
|
30
|
+
"paths": {
|
|
31
|
+
"@/*": ["src/*"]
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"include": [
|
|
35
|
+
"src/**/*.ts",
|
|
36
|
+
"src/**/*.tsx",
|
|
37
|
+
"src/**/*.vue",
|
|
38
|
+
"src/remoteApp.tsx",
|
|
39
|
+
"src/create.ts"
|
|
40
|
+
],
|
|
41
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
42
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../dist/out-tsc",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"types": ["jest", "node", "@testing-library/jest-dom"],
|
|
7
|
+
"jsx": "react-jsx",
|
|
8
|
+
"noUnusedLocals": false,
|
|
9
|
+
"noUnusedParameters": false,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"allowSyntheticDefaultImports": true
|
|
13
|
+
},
|
|
14
|
+
"include": [
|
|
15
|
+
"**/*.test.ts",
|
|
16
|
+
"**/*.test.tsx",
|
|
17
|
+
"**/*.test.js",
|
|
18
|
+
"**/*.test.jsx",
|
|
19
|
+
"**/*.spec.ts",
|
|
20
|
+
"**/*.spec.tsx",
|
|
21
|
+
"**/*.spec.js",
|
|
22
|
+
"**/*.spec.jsx",
|
|
23
|
+
"**/*.d.ts",
|
|
24
|
+
"__tests__/**/*"
|
|
25
|
+
]
|
|
26
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { defineConfig } from 'vite';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import dts from 'vite-plugin-dts';
|
|
4
|
+
import packageJson from './package.json';
|
|
5
|
+
|
|
6
|
+
const perDepsKeys = Object.keys(packageJson.peerDependencies);
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
plugins: [
|
|
10
|
+
// 添加我们的自定义插件
|
|
11
|
+
dts({
|
|
12
|
+
rollupTypes: true,
|
|
13
|
+
bundledPackages: [
|
|
14
|
+
'@module-federation/bridge-shared',
|
|
15
|
+
'react-error-boundary',
|
|
16
|
+
],
|
|
17
|
+
}),
|
|
18
|
+
],
|
|
19
|
+
build: {
|
|
20
|
+
lib: {
|
|
21
|
+
entry: {
|
|
22
|
+
index: path.resolve(__dirname, 'src/index.ts'),
|
|
23
|
+
plugin: path.resolve(__dirname, 'src/provider/plugin.ts'),
|
|
24
|
+
router: path.resolve(__dirname, 'src/router/default.tsx'),
|
|
25
|
+
'router-v5': path.resolve(__dirname, 'src/router/v5.tsx'),
|
|
26
|
+
'router-v6': path.resolve(__dirname, 'src/router/v6.tsx'),
|
|
27
|
+
v18: path.resolve(__dirname, 'src/v18.ts'),
|
|
28
|
+
v19: path.resolve(__dirname, 'src/v19.ts'),
|
|
29
|
+
'lazy-load-component-plugin': path.resolve(
|
|
30
|
+
__dirname,
|
|
31
|
+
'src/plugins/lazy-load-component-plugin.ts',
|
|
32
|
+
),
|
|
33
|
+
'data-fetch-server-middleware': path.resolve(
|
|
34
|
+
__dirname,
|
|
35
|
+
'src/lazy/data-fetch/data-fetch-server-middleware.ts',
|
|
36
|
+
),
|
|
37
|
+
'lazy-utils': path.resolve(__dirname, 'src/lazy/utils.ts'),
|
|
38
|
+
'data-fetch-utils': path.resolve(
|
|
39
|
+
__dirname,
|
|
40
|
+
'src/lazy/data-fetch/index.ts',
|
|
41
|
+
),
|
|
42
|
+
},
|
|
43
|
+
formats: ['cjs', 'es'],
|
|
44
|
+
fileName: (format, entryName) => `${entryName}.${format}.js`,
|
|
45
|
+
},
|
|
46
|
+
rollupOptions: {
|
|
47
|
+
external: [
|
|
48
|
+
...perDepsKeys,
|
|
49
|
+
'@remix-run/router',
|
|
50
|
+
/react-dom\/.*/,
|
|
51
|
+
'react-router',
|
|
52
|
+
'react-router-dom/',
|
|
53
|
+
'react-router-dom/index.js',
|
|
54
|
+
'react-router-dom/dist/index.js',
|
|
55
|
+
],
|
|
56
|
+
plugins: [
|
|
57
|
+
{
|
|
58
|
+
name: 'modify-output-plugin',
|
|
59
|
+
generateBundle(options, bundle) {
|
|
60
|
+
for (const fileName in bundle) {
|
|
61
|
+
const chunk = bundle[fileName];
|
|
62
|
+
if (fileName.includes('router-v6') && chunk.type === 'chunk') {
|
|
63
|
+
chunk.code = chunk.code.replace(
|
|
64
|
+
// Match 'react-router-dom/' followed by single quotes, double quotes, or backticks, replacing only 'react-router-dom/' to react-router-v6 dist file structure
|
|
65
|
+
/react-router-dom\/(?=[\'\"\`])/g,
|
|
66
|
+
'react-router-dom/dist/index.js',
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (fileName.includes('router-v5') && chunk.type === 'chunk') {
|
|
71
|
+
chunk.code = chunk.code.replace(
|
|
72
|
+
// Match 'react-router-dom/' followed by single quotes, double quotes, or backticks, replacing only 'react-router-dom/' to react-router-v5 dist file structure
|
|
73
|
+
/react-router-dom\/(?=[\'\"\`])/g,
|
|
74
|
+
'react-router-dom/index.js',
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
minify: false,
|
|
83
|
+
},
|
|
84
|
+
define: {
|
|
85
|
+
__APP_VERSION__: JSON.stringify(packageJson.version),
|
|
86
|
+
},
|
|
87
|
+
});
|