@module-federation/bridge-react 0.19.1 → 0.21.0

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/__tests__/bridge.spec.tsx +37 -14
  3. package/dist/{bridge-base-Ds850AOx.js → bridge-base-B2malZDo.js} +6 -4
  4. package/dist/{bridge-base-BwHtOqw_.mjs → bridge-base-DRFFglgm.mjs} +6 -4
  5. package/dist/data-fetch-server-middleware.cjs.js +2 -2
  6. package/dist/data-fetch-server-middleware.es.js +2 -2
  7. package/dist/data-fetch-utils.cjs.js +2 -2
  8. package/dist/data-fetch-utils.es.js +4 -4
  9. package/dist/{index-eN2xRRXs.js → index-DRSBaSu3.js} +1 -1
  10. package/dist/{index-rAO0Wr0M.mjs → index-DyQNwY2M.mjs} +1 -1
  11. package/dist/index.cjs.js +6 -6
  12. package/dist/index.es.js +6 -6
  13. package/dist/{index.esm-Ju4RY-yW.js → index.esm-BWaKho-8.js} +108 -46
  14. package/dist/{index.esm-CtI0uQUR.mjs → index.esm-CPwSeCvw.mjs} +113 -51
  15. package/dist/{lazy-load-component-plugin-vtpWwn-P.js → lazy-load-component-plugin-B-nqmULm.js} +2 -2
  16. package/dist/{lazy-load-component-plugin-Dmzr-hGo.mjs → lazy-load-component-plugin-D_--Azke.mjs} +2 -2
  17. package/dist/lazy-load-component-plugin.cjs.js +2 -2
  18. package/dist/lazy-load-component-plugin.es.js +2 -2
  19. package/dist/lazy-utils.cjs.js +2 -2
  20. package/dist/lazy-utils.es.js +2 -2
  21. package/dist/{prefetch-HjsWsmMr.js → prefetch-C8kORtvg.js} +63 -139
  22. package/dist/{prefetch-DtZwviM-.mjs → prefetch-Cxo6GKct.mjs} +63 -139
  23. package/dist/router-v5.cjs.js +1 -1
  24. package/dist/router-v5.es.js +1 -1
  25. package/dist/router-v6.cjs.js +1 -1
  26. package/dist/router-v6.es.js +1 -1
  27. package/dist/router-v7.cjs.js +83 -0
  28. package/dist/router-v7.d.ts +20 -0
  29. package/dist/router-v7.es.js +61 -0
  30. package/dist/router.cjs.js +1 -1
  31. package/dist/router.es.js +1 -1
  32. package/dist/{utils-VSOJTX_o.mjs → utils-Bx_8GGd-.mjs} +1 -1
  33. package/dist/{utils-vIpCrZmn.js → utils-tM9yE73c.js} +1 -1
  34. package/dist/v18.cjs.js +1 -1
  35. package/dist/v18.es.js +1 -1
  36. package/dist/v19.cjs.js +1 -1
  37. package/dist/v19.es.js +1 -1
  38. package/package.json +22 -7
  39. package/src/provider/versions/bridge-base.tsx +7 -2
  40. package/src/provider/versions/legacy.ts +2 -1
  41. package/src/router/v7.tsx +75 -0
  42. package/vite.config.ts +24 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/bridge-react",
3
- "version": "0.19.1",
3
+ "version": "0.21.0",
4
4
  "sideEffects": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -51,6 +51,11 @@
51
51
  "import": "./dist/router-v6.es.js",
52
52
  "require": "./dist/router-v6.cjs.js"
53
53
  },
54
+ "./router-v7": {
55
+ "types": "./dist/router-v7.d.ts",
56
+ "import": "./dist/router-v7.es.js",
57
+ "require": "./dist/router-v7.cjs.js"
58
+ },
54
59
  "./lazy-utils": {
55
60
  "types": "./dist/lazy-utils.d.ts",
56
61
  "import": "./dist/lazy-utils.es.js",
@@ -95,13 +100,22 @@
95
100
  "dependencies": {
96
101
  "react-error-boundary": "^4.1.2",
97
102
  "lru-cache": "^10.4.3",
98
- "@module-federation/bridge-shared": "0.19.1",
99
- "@module-federation/sdk": "0.19.1"
103
+ "@module-federation/bridge-shared": "0.21.0",
104
+ "@module-federation/sdk": "0.21.0"
100
105
  },
101
106
  "peerDependencies": {
102
107
  "react": ">=16.9.0",
103
108
  "react-dom": ">=16.9.0",
104
- "react-router-dom": "^4 || ^5 || ^6 || ^7"
109
+ "react-router-dom": "^4 || ^5 || ^6 || ^7",
110
+ "react-router": "^7"
111
+ },
112
+ "peerDependenciesMeta": {
113
+ "react-router-dom": {
114
+ "optional": true
115
+ },
116
+ "react-router": {
117
+ "optional": true
118
+ }
105
119
  },
106
120
  "devDependencies": {
107
121
  "@testing-library/react": "15.0.7",
@@ -114,12 +128,13 @@
114
128
  "react": "18.3.1",
115
129
  "react-dom": "18.3.1",
116
130
  "react-router-dom": "6.22.3",
131
+ "react-router": "7.9.4",
117
132
  "typescript": "^5.2.2",
118
- "vite": "^5.4.18",
133
+ "vite": "^5.4.20",
119
134
  "vite-plugin-dts": "^4.3.0",
120
135
  "hono": "3.12.12",
121
- "@module-federation/runtime": "0.19.1",
122
- "@module-federation/runtime-core": "0.19.1"
136
+ "@module-federation/runtime": "0.21.0",
137
+ "@module-federation/runtime-core": "0.21.0"
123
138
  },
124
139
  "scripts": {
125
140
  "dev": "vite",
@@ -64,7 +64,7 @@ export function createBaseBridgeComponent<T>({
64
64
  const beforeBridgeRenderRes =
65
65
  instance?.bridgeHook?.lifecycle?.beforeBridgeRender?.emit(info) || {};
66
66
 
67
- const rootComponentWithErrorBoundary = (
67
+ const BridgeWrapper = ({ basename }: { basename?: string }) => (
68
68
  <ErrorBoundary
69
69
  FallbackComponent={fallback as React.ComponentType<FallbackProps>}
70
70
  >
@@ -77,6 +77,7 @@ export function createBaseBridgeComponent<T>({
77
77
  propsInfo={
78
78
  {
79
79
  ...propsInfo,
80
+ basename,
80
81
  ...(beforeBridgeRenderRes as any)?.extraProps,
81
82
  } as T
82
83
  }
@@ -84,6 +85,10 @@ export function createBaseBridgeComponent<T>({
84
85
  </ErrorBoundary>
85
86
  );
86
87
 
88
+ const rootComponentWithErrorBoundary = (
89
+ <BridgeWrapper basename={basename} />
90
+ );
91
+
87
92
  if (bridgeInfo.render) {
88
93
  await Promise.resolve(
89
94
  bridgeInfo.render(rootComponentWithErrorBoundary, dom),
@@ -111,7 +116,7 @@ export function createBaseBridgeComponent<T>({
111
116
  if ('unmount' in root) {
112
117
  root.unmount();
113
118
  } else {
114
- console.warn('Root does not have unmount method');
119
+ LoggerInstance.warn('Root does not have unmount method');
115
120
  }
116
121
  rootMap.delete(dom);
117
122
  }
@@ -5,6 +5,7 @@
5
5
  import type { ProviderFnParams } from '../../types';
6
6
  import { createBaseBridgeComponent } from './bridge-base';
7
7
  import ReactDOM from 'react-dom';
8
+ import { LoggerInstance } from '../../utils';
8
9
 
9
10
  export interface CreateRootOptions {
10
11
  identifierPrefix?: string;
@@ -58,7 +59,7 @@ export function createReact16Or17Root(
58
59
  * Provide warning for React 18
59
60
  */
60
61
  if (isReact18) {
61
- console.warn(
62
+ LoggerInstance.warn(
62
63
  `[Bridge-React] React 18 detected in legacy mode. ` +
63
64
  `For better compatibility, please use the version-specific import: ` +
64
65
  `import { createBridgeComponent } from '@module-federation/bridge-react/v18'`,
@@ -0,0 +1,75 @@
1
+ import React, { useContext } from 'react';
2
+ // The upper alias react-router$ into this file avoids the loop
3
+ // React Router v7 uses different dist structure, we'll import from the main entry
4
+ import * as ReactRouterDom from 'react-router';
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
+ function WraperRouterProvider(
39
+ props: Parameters<typeof ReactRouterDom.RouterProvider>[0],
40
+ ) {
41
+ const { router, ...propsRes } = props;
42
+ const routerContextProps = useContext(RouterContext) || {};
43
+ const routers = router.routes;
44
+ LoggerInstance.debug(`WraperRouterProvider info >>>`, {
45
+ ...routerContextProps,
46
+ routerContextProps,
47
+ WraperRouterProviderProps: props,
48
+ router,
49
+ });
50
+ const RouterProvider = (ReactRouterDom as any)['Router' + 'Provider'];
51
+ const createMemoryRouter = (ReactRouterDom as any)['create' + 'MemoryRouter'];
52
+ const createBrowserRouter = (ReactRouterDom as any)[
53
+ 'create' + 'BrowserRouter'
54
+ ];
55
+
56
+ if (routerContextProps.memoryRoute) {
57
+ const MemeoryRouterInstance = createMemoryRouter(routers, {
58
+ initialEntries: [routerContextProps?.memoryRoute.entryPath],
59
+ });
60
+ return <RouterProvider router={MemeoryRouterInstance} />;
61
+ } else {
62
+ const BrowserRouterInstance = createBrowserRouter(routers, {
63
+ // In host app, the routerContextProps is {}, so we should use router.basename as fallback
64
+ basename: routerContextProps.basename || router.basename,
65
+ future: router.future,
66
+ window: router.window,
67
+ });
68
+ return <RouterProvider {...propsRes} router={BrowserRouterInstance} />;
69
+ }
70
+ }
71
+
72
+ // Export all from react-router for v7 compatibility
73
+ export * from 'react-router';
74
+ export { WraperRouter as BrowserRouter };
75
+ export { WraperRouterProvider as RouterProvider };
package/vite.config.ts CHANGED
@@ -24,6 +24,7 @@ export default defineConfig({
24
24
  router: path.resolve(__dirname, 'src/router/default.tsx'),
25
25
  'router-v5': path.resolve(__dirname, 'src/router/v5.tsx'),
26
26
  'router-v6': path.resolve(__dirname, 'src/router/v6.tsx'),
27
+ 'router-v7': path.resolve(__dirname, 'src/router/v7.tsx'),
27
28
  v18: path.resolve(__dirname, 'src/v18.ts'),
28
29
  v19: path.resolve(__dirname, 'src/v19.ts'),
29
30
  'lazy-load-component-plugin': path.resolve(
@@ -49,6 +50,12 @@ export default defineConfig({
49
50
  '@remix-run/router',
50
51
  /react-dom\/.*/,
51
52
  'react-router',
53
+ 'react-router/',
54
+ 'react-router/index.js',
55
+ 'react-router/dist/index.js',
56
+ 'react-router/dist/development/index.js',
57
+ 'react-router/dist/production/index.js',
58
+ /^react-router\/.*/,
52
59
  'react-router-dom/',
53
60
  'react-router-dom/index.js',
54
61
  'react-router-dom/dist/index.js',
@@ -67,6 +74,23 @@ export default defineConfig({
67
74
  );
68
75
  }
69
76
 
77
+ if (fileName.includes('router-v7') && chunk.type === 'chunk') {
78
+ // Replace 'react-router' with the correct v7 dist path based on environment
79
+ const isProduction = process.env.NODE_ENV === 'production';
80
+ const distPath = isProduction
81
+ ? 'react-router/dist/production/index.js'
82
+ : 'react-router/dist/development/index.js';
83
+
84
+ chunk.code = chunk.code.replace(
85
+ /from\s+['"`]react-router['"`]/g,
86
+ `from '${distPath}'`,
87
+ );
88
+ chunk.code = chunk.code.replace(
89
+ /export\s+\*\s+from\s+['"`]react-router['"`]/g,
90
+ `export * from '${distPath}'`,
91
+ );
92
+ }
93
+
70
94
  if (fileName.includes('router-v5') && chunk.type === 'chunk') {
71
95
  chunk.code = chunk.code.replace(
72
96
  // Match 'react-router-dom/' followed by single quotes, double quotes, or backticks, replacing only 'react-router-dom/' to react-router-v5 dist file structure