Skip to content

Commit d225658

Browse files
authored
feat: Add React Router v7 Support to Module Federation Bridge (#4132)
1 parent aa7daae commit d225658

File tree

32 files changed

+1408
-386
lines changed

32 files changed

+1408
-386
lines changed

.changeset/serious-pears-guess.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
'@module-federation/bridge-react-webpack-plugin': minor
3+
'remote6': minor
4+
'@module-federation/bridge-react': minor
5+
'website-new': minor
6+
---
7+
8+
feat: Add React Router v7 Support to Module Federation Bridge

apps/router-demo/router-host-2000/cypress/e2e/remote5.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe('router-remote5-2005 in host', () => {
1313

1414
describe('Remote5 render and destroy', () => {
1515
it('jump to remote5 home page', () => {
16-
cy.clickMenuItem('remote5');
16+
cy.clickMenuItem('Remote5-React19');
1717
cy.verifyContent('This is the remote app5 with React 19');
1818
});
1919
});
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
describe('router-remote6-2006/', () => {
2+
beforeEach(() => cy.visit('http://localhost:2006/'));
3+
4+
describe('visit', () => {
5+
it('should display React Router v7 content', () => {
6+
cy.verifyContent('Remote6 - React Router v7 Demo');
7+
cy.verifyContent('hello remote6 home page');
8+
cy.verifyContent('React Router v7 + React 18 + Module Federation');
9+
});
10+
11+
it('should navigate between routes', () => {
12+
// Test navigation functionality with React Router v7
13+
cy.get('.self-remote6-home-link').should('exist').click();
14+
cy.url().should('include', '/');
15+
cy.verifyContent('Remote6 home page');
16+
17+
cy.get('.self-remote6-about-link').should('exist').click();
18+
cy.url().should('include', '/about');
19+
cy.verifyContent('Remote6 about page');
20+
cy.verifyContent('This is a React Router v7 demo in Module Federation');
21+
22+
cy.get('.self-remote6-detail-link').should('exist').click();
23+
cy.url().should('include', '/detail');
24+
cy.verifyContent('Remote6 detail page');
25+
cy.verifyContent('hello remote6 detail page with React Router v7');
26+
});
27+
28+
it('should have working React Router v7 features', () => {
29+
// Verify React Router v7 specific content
30+
cy.verifyContent('Features: Data APIs, Type Safety, Future Flags');
31+
32+
// Navigate to about page to see v7 features
33+
cy.get('.self-remote6-about-link').click();
34+
cy.verifyContent('New features in v7:');
35+
cy.verifyContent('Improved data loading patterns');
36+
cy.verifyContent('Better TypeScript support');
37+
});
38+
});
39+
});
40+
41+
describe('router-remote6-2006 in host', () => {
42+
beforeEach(() => cy.visit('/'));
43+
44+
describe('Remote6 render and destroy', () => {
45+
it('jump to remote6 home page', () => {
46+
cy.clickMenuItem('Remote6-ReactRouteV7');
47+
cy.verifyContent('Remote6 - React Router v7 Demo');
48+
cy.verifyContent('hello remote6 home page');
49+
cy.url().should('include', '/remote6');
50+
});
51+
52+
it('should handle routing within remote6', () => {
53+
cy.clickMenuItem('Remote6-ReactRouteV7');
54+
55+
// Test navigation within the remote app
56+
cy.get('.self-remote6-about-link').should('exist').click();
57+
cy.verifyContent('Remote6 about page');
58+
cy.verifyContent('This is a React Router v7 demo in Module Federation');
59+
cy.url().should('include', '/remote6/about');
60+
61+
// Navigate to detail page
62+
cy.get('.self-remote6-detail-link').should('exist').click();
63+
cy.verifyContent('Remote6 detail page');
64+
cy.url().should('include', '/remote6/detail');
65+
66+
// Navigate back to home
67+
cy.get('.self-remote6-home-link').should('exist').click();
68+
cy.verifyContent('hello remote6 home page');
69+
cy.url().should('include', '/remote6');
70+
});
71+
72+
it('should maintain React Router v7 context and features', () => {
73+
cy.clickMenuItem('Remote6-ReactRouteV7');
74+
75+
// Verify React Router v7 specific content is loaded
76+
cy.verifyContent('React Router v7 + React 18 + Module Federation');
77+
cy.verifyContent('Features: Data APIs, Type Safety, Future Flags');
78+
79+
// Test that routing works properly within the federated context
80+
cy.get('.self-remote6-about-link').click();
81+
cy.verifyContent('New features in v7:');
82+
cy.verifyContent('Enhanced error boundaries');
83+
});
84+
85+
it('should handle deep linking', () => {
86+
// Test direct navigation to remote6 sub-route
87+
cy.visit('/remote6/about');
88+
cy.verifyContent('Remote6 about page');
89+
cy.verifyContent('This is a React Router v7 demo in Module Federation');
90+
});
91+
92+
it('should support browser navigation', () => {
93+
cy.clickMenuItem('Remote6-ReactRouteV7');
94+
95+
// Navigate to about page
96+
cy.get('.self-remote6-about-link').click();
97+
cy.verifyContent('Remote6 about page');
98+
99+
// Navigate to detail page
100+
cy.get('.self-remote6-detail-link').click();
101+
cy.verifyContent('Remote6 detail page');
102+
103+
// Use browser back button
104+
cy.go('back');
105+
cy.verifyContent('Remote6 about page');
106+
107+
// Use browser back button again
108+
cy.go('back');
109+
cy.verifyContent('hello remote6 home page');
110+
111+
// Use browser forward button
112+
cy.go('forward');
113+
cy.verifyContent('Remote6 about page');
114+
});
115+
});
116+
});

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"forwardAllArgs": false
5757
},
5858
{
59-
"command": "sleep 4 && nx run router-host-2000:e2e",
59+
"command": "sleep 4 && nx run router-host-2000:e2e --watch",
6060
"forwardAllArgs": true
6161
}
6262
]

apps/router-demo/router-host-2000/rsbuild.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default defineConfig({
2828
'remote-resource-error':
2929
'remote-resource-error@http://localhost:2008/not-exist-mf-manifest.json',
3030
remote5: 'remote5@http://localhost:2005/mf-manifest.json',
31+
remote6: 'remote6@http://localhost:2006/mf-manifest.json',
3132
},
3233
shared: {
3334
react: {

apps/router-demo/router-host-2000/src/App.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,11 @@ const Remote5App = createRemoteAppComponent({
8181
fallback: FallbackErrorComp,
8282
loading: FallbackComp,
8383
});
84+
const Remote6App = createRemoteAppComponent({
85+
loader: () => loadRemote('remote6/export-app'),
86+
fallback: FallbackErrorComp,
87+
loading: FallbackComp,
88+
});
8489

8590
const Remote1AppWithLoadRemote = React.lazy(
8691
() =>
@@ -277,6 +282,19 @@ const App = () => {
277282
/>
278283
)}
279284
/>
285+
<Route
286+
path="/remote6/*"
287+
Component={() => (
288+
<Remote6App
289+
rootOptions={{
290+
identifierPrefix: 'remote6-instance-',
291+
onRecoverableError: (error: Error) => {
292+
console.error('[Host] Remote6 recoverable error:', error);
293+
},
294+
}}
295+
/>
296+
)}
297+
/>
280298
</Routes>
281299
</div>
282300
);

apps/router-demo/router-host-2000/src/navigation.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function Navgation() {
2424
icon: <GroupOutlined />,
2525
},
2626
{
27-
label: 'Remote1',
27+
label: 'Remote1-React17',
2828
key: '/remote1',
2929
icon: <SettingOutlined />,
3030
children: [
@@ -53,7 +53,7 @@ function Navgation() {
5353
],
5454
},
5555
{
56-
label: <Link to="/remote2">Remote2</Link>,
56+
label: <Link to="/remote2">Remote2-React18</Link>,
5757
key: '/remote2',
5858
icon: <GroupOutlined />,
5959
children: [
@@ -90,7 +90,7 @@ function Navgation() {
9090
],
9191
},
9292
{
93-
label: <Link to="/remote3">Remote3</Link>,
93+
label: <Link to="/remote3">Remote3-Vue3</Link>,
9494
key: '/remote3',
9595
icon: <GroupOutlined />,
9696
children: [
@@ -134,7 +134,7 @@ function Navgation() {
134134
icon: <GroupOutlined />,
135135
},
136136
{
137-
label: <Link to="/remote5">remote5</Link>,
137+
label: <Link to="/remote5">Remote5-React19</Link>,
138138
key: '/remote5',
139139
icon: <GroupOutlined />,
140140
},
@@ -148,6 +148,11 @@ function Navgation() {
148148
key: '/error-load-with-error-boundary',
149149
icon: <GroupOutlined />,
150150
},
151+
{
152+
label: <Link to="/remote6">Remote6-ReactRouteV7</Link>,
153+
key: '/remote6',
154+
icon: <GroupOutlined />,
155+
},
151156
];
152157

153158
const onClick: MenuProps['onClick'] = (e) => {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Changelog
2+
3+
## [1.0.34] - 2025-10-15
4+
5+
### Added
6+
- Initial React Router v7 + Module Federation demo
7+
- Bridge router integration with `enableBridgeRouter: true`
8+
- Enhanced error boundaries with React Router v7
9+
- Multiple demo routes (Home, Detail, About)
10+
- Styled components with Emotion
11+
- TypeScript support
12+
13+
### Features
14+
- React Router v7 data APIs
15+
- Module Federation bridge components
16+
- Modern build setup with Rsbuild
17+
- Enhanced routing capabilities
18+
- Better developer experience
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Router Remote6 (React Router v7 Demo)
2+
3+
A Module Federation remote application demonstrating React Router v7 integration.
4+
5+
## Features
6+
7+
- 🎯 **React Router v7**: Latest routing capabilities with improved DX
8+
-**Module Federation**: Micro-frontend architecture
9+
- 🔧 **Rsbuild**: Fast build tool with Rspack
10+
- 🎨 **Emotion**: Styled components with great performance
11+
- 🧩 **Bridge Components**: Seamless integration with host applications
12+
13+
## React Router v7 Highlights
14+
15+
This demo showcases React Router v7 new features:
16+
- Enhanced data loading patterns
17+
- Better TypeScript support
18+
- Improved error boundaries
19+
- Future-ready APIs
20+
- Better performance
21+
22+
## Development
23+
24+
```bash
25+
# Start development server
26+
npm run dev
27+
28+
# Build for production
29+
npm run build
30+
31+
# Preview production build
32+
npm run preview
33+
```
34+
35+
## Usage
36+
37+
The application exposes two federated modules:
38+
39+
- `./button`: A styled button component
40+
- `./export-app`: The main app component with routing
41+
42+
## Configuration
43+
44+
The Module Federation configuration explicitly enables bridge router:
45+
46+
```typescript
47+
bridge: {
48+
enableBridgeRouter: true, // ✅ Explicitly enable bridge router for React Router v7
49+
}
50+
```
51+
52+
## Routes
53+
54+
- `/` - Home page
55+
- `/detail` - Detail page with sample content
56+
- `/about` - About page explaining React Router v7 features
57+
58+
## Port
59+
60+
Development server runs on `http://localhost:2006`
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "remote6",
3+
"private": true,
4+
"version": "1.0.34",
5+
"scripts": {
6+
"dev": "rsbuild dev",
7+
"build": "rsbuild build",
8+
"preview": "rsbuild preview"
9+
},
10+
"dependencies": {
11+
"@emotion/react": "^11.11.4",
12+
"@emotion/styled": "^11.11.5",
13+
"@module-federation/bridge-react": "workspace:*",
14+
"@module-federation/rsbuild-plugin": "workspace:*",
15+
"antd": "^5.17.0",
16+
"react": "18.3.1",
17+
"react-dom": "18.3.1",
18+
"react-router": "7.9.4"
19+
},
20+
"devDependencies": {
21+
"@rsbuild/core": "^1.3.21",
22+
"@rsbuild/plugin-react": "^1.0.6",
23+
"@types/react": "^18.2.79",
24+
"@types/react-dom": "^18.3.0",
25+
"typescript": "^5.4.5"
26+
}
27+
}

0 commit comments

Comments
 (0)