Skip to content

Commit 006b061

Browse files
authored
fix: fix router alias issue for react-bridge (#2887)
1 parent 24ba96e commit 006b061

File tree

8 files changed

+302
-55
lines changed

8 files changed

+302
-55
lines changed

apps/router-demo/router-host-2000/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"@ant-design/icons": "^5.3.6",
1212
"@module-federation/bridge-react": "workspace:*",
1313
"@module-federation/enhanced": "workspace:*",
14-
"react-router-dom": "6.24.1"
14+
"react-router-dom": "^6.24.1"
1515
},
1616
"devDependencies": {
1717
"@rsbuild/core": "^0.6.15",
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"name": "react-router-dom",
3+
"version": "5.3.4",
4+
"description": "DOM bindings for React Router",
5+
"homepage": "https://reactrouter.com/",
6+
"repository": {
7+
"url": "https://github.com/remix-run/react-router.git",
8+
"type": "git",
9+
"directory": "packages/react-router-dom"
10+
},
11+
"license": "MIT",
12+
"author": "Remix Software <[email protected]>",
13+
"files": [
14+
"LICENSE",
15+
"README.md",
16+
"BrowserRouter.js",
17+
"HashRouter.js",
18+
"Link.js",
19+
"MemoryRouter.js",
20+
"NavLink.js",
21+
"Prompt.js",
22+
"Redirect.js",
23+
"Route.js",
24+
"Router.js",
25+
"StaticRouter.js",
26+
"Switch.js",
27+
"cjs",
28+
"es",
29+
"esm",
30+
"index.js",
31+
"generatePath.js",
32+
"matchPath.js",
33+
"modules/*.js",
34+
"modules/utils/*.js",
35+
"withRouter.js",
36+
"warnAboutDeprecatedCJSRequire.js",
37+
"umd"
38+
],
39+
"main": "index.js",
40+
"module": "esm/react-router-dom.js",
41+
"sideEffects": false,
42+
"scripts": {
43+
"build": "rollup -c",
44+
"lint": "eslint modules"
45+
},
46+
"peerDependencies": {
47+
"react": ">=15"
48+
},
49+
"dependencies": {
50+
"@babel/runtime": "^7.12.13",
51+
"history": "^4.9.0",
52+
"loose-envify": "^1.3.1",
53+
"prop-types": "^15.6.2",
54+
"react-router": "5.3.4",
55+
"tiny-invariant": "^1.0.2",
56+
"tiny-warning": "^1.0.0"
57+
},
58+
"browserify": {
59+
"transform": [
60+
"loose-envify"
61+
]
62+
},
63+
"keywords": [
64+
"react",
65+
"router",
66+
"route",
67+
"routing",
68+
"history",
69+
"link"
70+
]
71+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "react-router-dom",
3+
"version": "6.22.3",
4+
"description": "Declarative routing for React web applications",
5+
"keywords": [
6+
"react",
7+
"router",
8+
"route",
9+
"routing",
10+
"history",
11+
"link"
12+
],
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/remix-run/react-router",
16+
"directory": "packages/react-router-dom"
17+
},
18+
"license": "MIT",
19+
"author": "Remix Software <[email protected]>",
20+
"sideEffects": false,
21+
"main": "./dist/main.js",
22+
"unpkg": "./dist/umd/react-router-dom.production.min.js",
23+
"module": "./dist/index.js",
24+
"types": "./dist/index.d.ts",
25+
"dependencies": {
26+
"@remix-run/router": "1.15.3",
27+
"react-router": "6.22.3"
28+
},
29+
"devDependencies": {
30+
"react": "^18.2.0",
31+
"react-dom": "^18.2.0"
32+
},
33+
"peerDependencies": {
34+
"react": ">=16.8",
35+
"react-dom": ">=16.8"
36+
},
37+
"files": [
38+
"dist/",
39+
"CHANGELOG.md",
40+
"LICENSE.md",
41+
"README.md",
42+
"server.d.ts",
43+
"server.js",
44+
"server.mjs"
45+
],
46+
"engines": {
47+
"node": ">=14.0.0"
48+
}
49+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import path from 'node:path';
2+
import {
3+
checkVersion,
4+
findPackageJson,
5+
getBridgeRouterAlias,
6+
} from '../src/utis';
7+
8+
const resolveRouterV5 = path.resolve(
9+
__dirname,
10+
'../__tests__/mockRouterDir/router-v5/react-router-dom',
11+
);
12+
const resolveRouterV5_PkgPath = path.resolve(
13+
__dirname,
14+
'../__tests__/mockRouterDir/router-v5/react-router-dom/package.json',
15+
);
16+
const resolveRouterV6 = path.resolve(
17+
__dirname,
18+
'../__tests__/mockRouterDir/router-v6/react-router-dom/dist/main.js',
19+
);
20+
const resolveRouterV6_PkgPath = path.resolve(
21+
__dirname,
22+
'../__tests__/mockRouterDir/router-v6/react-router-dom/package.json',
23+
);
24+
25+
describe('test checkVersion: should return the correct major version for react-router-dom', () => {
26+
it('should return 5', () => {
27+
expect(checkVersion('5.0.0')).toBe(5);
28+
});
29+
30+
it('should return 5', () => {
31+
expect(checkVersion('^5.0.0')).toBe(5);
32+
});
33+
34+
it('should return 6', () => {
35+
expect(checkVersion('6.0.0')).toBe(6);
36+
});
37+
38+
it('should return 6', () => {
39+
expect(checkVersion('~6.0.0')).toBe(6);
40+
});
41+
42+
it('should return 6', () => {
43+
expect(checkVersion('^6.0.0')).toBe(6);
44+
});
45+
});
46+
47+
describe('test findPackageJson: should return the correct package.json path for react-router-dom v5 and v6', () => {
48+
it('should return the package.json path', () => {
49+
expect(findPackageJson(resolveRouterV5)).toBe(resolveRouterV5_PkgPath);
50+
expect(findPackageJson(resolveRouterV6)).toBe(resolveRouterV6_PkgPath);
51+
});
52+
});
53+
54+
describe('test getBridgeRouterAlias: should return the correct alias for react-router-dom v5 and v6', () => {
55+
it('should return the correct alias for router v5', () => {
56+
const res = getBridgeRouterAlias(resolveRouterV5);
57+
expect(res).toEqual({
58+
'react-router-dom$':
59+
'@module-federation/bridge-react/dist/router-v5.es.js',
60+
'react-router-dom/index.js': resolveRouterV5,
61+
});
62+
});
63+
64+
it('should return the correct alias for router v6', () => {
65+
const res = getBridgeRouterAlias(resolveRouterV6);
66+
expect(res).toEqual({
67+
'react-router-dom$':
68+
'@module-federation/bridge-react/dist/router-v6.es.js',
69+
});
70+
});
71+
});

packages/bridge/bridge-react-webpack-plugin/project.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,18 @@
1111
"npm run build --prefix packages/bridge/bridge-react-webpack-plugin"
1212
]
1313
}
14+
},
15+
"test": {
16+
"executor": "nx:run-commands",
17+
"options": {
18+
"parallel": false,
19+
"commands": [
20+
{
21+
"command": "vitest run -c packages/bridge/bridge-react-webpack-plugin/vitest.config.ts",
22+
"forwardAllArgs": false
23+
}
24+
]
25+
}
1426
}
1527
},
1628
"tags": ["type:pkg"]

packages/bridge/bridge-react-webpack-plugin/src/utis.ts

Lines changed: 75 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,34 @@ import fs from 'node:fs';
22
import path from 'node:path';
33
import semver from 'semver';
44

5+
export const checkVersion = (version: string) => {
6+
// Extract the version number starting from the first digit
7+
const versionMatch = version.match(/\d.*/);
8+
if (!versionMatch) return 0;
9+
10+
const cleanVersion = versionMatch[0];
11+
12+
if (semver.gte(cleanVersion, '5.0.0') && semver.lt(cleanVersion, '6.0.0')) {
13+
return 5;
14+
} else if (semver.gte(cleanVersion, '6.0.0')) {
15+
return 6;
16+
}
17+
18+
return 0;
19+
};
20+
21+
export const findPackageJson = (startPath: string): string | null => {
22+
let currentPath = startPath;
23+
while (currentPath !== path.parse(currentPath).root) {
24+
const packageJsonPath = path.join(currentPath, 'package.json');
25+
if (fs.existsSync(packageJsonPath)) {
26+
return packageJsonPath;
27+
}
28+
currentPath = path.dirname(currentPath);
29+
}
30+
return null;
31+
};
32+
533
export const getBridgeRouterAlias = (
634
originalAlias: string,
735
): Record<string, string> => {
@@ -18,69 +46,63 @@ export const getBridgeRouterAlias = (
1846
};
1947
}
2048

21-
const hasBridgeReact = '@module-federation/bridge-react' in userDependencies;
22-
2349
let bridgeRouterAlias = {};
24-
// user install @module-federation/bridge-react package or set bridgeReactRouterDomAlias
25-
if (hasBridgeReact) {
26-
// user install react-router-dom package
27-
const reactRouterDomVersion = userDependencies['react-router-dom'];
28-
let majorVersion = 0;
29-
let reactRouterDomPath = '';
50+
let majorVersion = 0;
51+
let reactRouterDomPath = '';
3052

31-
// if react-router-dom version is set, use the version in package.json
32-
if (reactRouterDomVersion) {
33-
majorVersion = semver.major(
34-
semver.coerce(reactRouterDomVersion || '0.0.0') ?? '0.0.0',
35-
);
36-
reactRouterDomPath = require.resolve('react-router-dom');
37-
} else {
38-
// if react-router-dom version is not set, reslove react-router-dom to get the version
39-
reactRouterDomPath = require.resolve('react-router-dom');
40-
const packageJsonPath = path.resolve(
41-
reactRouterDomPath,
42-
'../../package.json',
43-
);
44-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
45-
majorVersion = parseInt(packageJson.version.split('.')[0]);
46-
}
53+
const reactRouterDomVersion = userDependencies['react-router-dom'];
54+
55+
if (originalAlias) {
56+
reactRouterDomPath = originalAlias;
57+
} else if (reactRouterDomVersion) {
58+
majorVersion = checkVersion(reactRouterDomVersion);
59+
reactRouterDomPath = require.resolve('react-router-dom');
60+
} else {
61+
reactRouterDomPath = require.resolve('react-router-dom');
62+
}
4763

48-
// if react-router-dom path has set alias by user, use the originalAlias
49-
reactRouterDomPath = originalAlias || reactRouterDomPath;
64+
const packageJsonPath = findPackageJson(reactRouterDomPath);
5065

51-
if (majorVersion === 5) {
66+
if (packageJsonPath) {
67+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
68+
majorVersion = checkVersion(packageJson.version);
69+
} else {
70+
console.warn('Unable to find package.json for react-router-dom');
71+
}
72+
73+
if (majorVersion === 5) {
74+
bridgeRouterAlias = {
75+
'react-router-dom$':
76+
'@module-federation/bridge-react/dist/router-v5.es.js',
77+
};
78+
try {
79+
require.resolve('react-router-dom/index.js');
80+
} catch (error) {
81+
// if react-router-dom/index.js cannot be resolved, set the alias to origin reactRouterDomPath
5282
bridgeRouterAlias = {
53-
'react-router-dom$':
54-
'@module-federation/bridge-react/dist/router-v5.es.js',
83+
...bridgeRouterAlias,
84+
'react-router-dom/index.js': reactRouterDomPath,
5585
};
56-
try {
57-
require.resolve('react-router-dom/index.js');
58-
} catch (error) {
59-
// if react-router-dom/index.js cannot be resolved, set the alias to origin reactRouterDomPath
60-
bridgeRouterAlias = {
61-
...bridgeRouterAlias,
62-
'react-router-dom/index.js': reactRouterDomPath,
63-
};
64-
}
65-
} else if (majorVersion === 6) {
86+
}
87+
} else if (majorVersion === 6) {
88+
bridgeRouterAlias = {
89+
'react-router-dom$':
90+
'@module-federation/bridge-react/dist/router-v6.es.js',
91+
};
92+
93+
try {
94+
require.resolve('react-router-dom/dist/index.js');
95+
} catch (error) {
96+
// if react-router-dom/dist/index.js cannot be resolved, set the alias to origin reactRouterDomPath
6697
bridgeRouterAlias = {
67-
'react-router-dom$':
68-
'@module-federation/bridge-react/dist/router-v6.es.js',
98+
...bridgeRouterAlias,
99+
'react-router-dom/dist/index.js': reactRouterDomPath,
69100
};
70-
71-
try {
72-
require.resolve('react-router-dom/dist/index.js');
73-
} catch (error) {
74-
// if react-router-dom/dist/index.js cannot be resolved, set the alias to origin reactRouterDomPath
75-
bridgeRouterAlias = {
76-
...bridgeRouterAlias,
77-
'react-router-dom/dist/index.js': reactRouterDomPath,
78-
};
79-
}
80-
} else {
81-
console.warn('react-router-dom version is not supported');
82101
}
102+
} else {
103+
console.warn('react-router-dom version is not supported');
83104
}
105+
84106
console.log(
85107
'<<<<<<<<<<<<< bridgeRouterAlias >>>>>>>>>>>>>',
86108
bridgeRouterAlias,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { defineConfig } from 'vitest/config';
2+
import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin';
3+
import path from 'path';
4+
export default defineConfig({
5+
define: {
6+
__DEV__: true,
7+
__TEST__: true,
8+
__BROWSER__: false,
9+
__VERSION__: '"unknown"',
10+
__APP_VERSION__: '"0.0.0"',
11+
},
12+
plugins: [nxViteTsPaths()],
13+
test: {
14+
environment: 'jsdom',
15+
include: [
16+
path.resolve(__dirname, '__tests__/*.spec.ts'),
17+
path.resolve(__dirname, '__tests__/*.spec.tsx'),
18+
],
19+
globals: true,
20+
testTimeout: 10000,
21+
},
22+
});

0 commit comments

Comments
 (0)