Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/serious-pears-guess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@module-federation/bridge-react-webpack-plugin': minor
'remote6': minor
'@module-federation/bridge-react': minor
'website-new': minor
---

feat: Add React Router v7 Support to Module Federation Bridge
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('router-remote5-2005 in host', () => {

describe('Remote5 render and destroy', () => {
it('jump to remote5 home page', () => {
cy.clickMenuItem('remote5');
cy.clickMenuItem('Remote5-React19');
cy.verifyContent('This is the remote app5 with React 19');
});
});
Expand Down
116 changes: 116 additions & 0 deletions apps/router-demo/router-host-2000/cypress/e2e/remote6.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
describe('router-remote6-2006/', () => {
beforeEach(() => cy.visit('http://localhost:2006/'));

describe('visit', () => {
it('should display React Router v7 content', () => {
cy.verifyContent('Remote6 - React Router v7 Demo');
cy.verifyContent('hello remote6 home page');
cy.verifyContent('React Router v7 + React 18 + Module Federation');
});

it('should navigate between routes', () => {
// Test navigation functionality with React Router v7
cy.get('.self-remote6-home-link').should('exist').click();
cy.url().should('include', '/');
cy.verifyContent('Remote6 home page');

cy.get('.self-remote6-about-link').should('exist').click();
cy.url().should('include', '/about');
cy.verifyContent('Remote6 about page');
cy.verifyContent('This is a React Router v7 demo in Module Federation');

cy.get('.self-remote6-detail-link').should('exist').click();
cy.url().should('include', '/detail');
cy.verifyContent('Remote6 detail page');
cy.verifyContent('hello remote6 detail page with React Router v7');
});

it('should have working React Router v7 features', () => {
// Verify React Router v7 specific content
cy.verifyContent('Features: Data APIs, Type Safety, Future Flags');

// Navigate to about page to see v7 features
cy.get('.self-remote6-about-link').click();
cy.verifyContent('New features in v7:');
cy.verifyContent('Improved data loading patterns');
cy.verifyContent('Better TypeScript support');
});
});
});

describe('router-remote6-2006 in host', () => {
beforeEach(() => cy.visit('/'));

describe('Remote6 render and destroy', () => {
it('jump to remote6 home page', () => {
cy.clickMenuItem('Remote6-ReactRouteV7');
cy.verifyContent('Remote6 - React Router v7 Demo');
cy.verifyContent('hello remote6 home page');
cy.url().should('include', '/remote6');
});

it('should handle routing within remote6', () => {
cy.clickMenuItem('Remote6-ReactRouteV7');

// Test navigation within the remote app
cy.get('.self-remote6-about-link').should('exist').click();
cy.verifyContent('Remote6 about page');
cy.verifyContent('This is a React Router v7 demo in Module Federation');
cy.url().should('include', '/remote6/about');

// Navigate to detail page
cy.get('.self-remote6-detail-link').should('exist').click();
cy.verifyContent('Remote6 detail page');
cy.url().should('include', '/remote6/detail');

// Navigate back to home
cy.get('.self-remote6-home-link').should('exist').click();
cy.verifyContent('hello remote6 home page');
cy.url().should('include', '/remote6');
});

it('should maintain React Router v7 context and features', () => {
cy.clickMenuItem('Remote6-ReactRouteV7');

// Verify React Router v7 specific content is loaded
cy.verifyContent('React Router v7 + React 18 + Module Federation');
cy.verifyContent('Features: Data APIs, Type Safety, Future Flags');

// Test that routing works properly within the federated context
cy.get('.self-remote6-about-link').click();
cy.verifyContent('New features in v7:');
cy.verifyContent('Enhanced error boundaries');
});

it('should handle deep linking', () => {
// Test direct navigation to remote6 sub-route
cy.visit('/remote6/about');
cy.verifyContent('Remote6 about page');
cy.verifyContent('This is a React Router v7 demo in Module Federation');
});

it('should support browser navigation', () => {
cy.clickMenuItem('Remote6-ReactRouteV7');

// Navigate to about page
cy.get('.self-remote6-about-link').click();
cy.verifyContent('Remote6 about page');

// Navigate to detail page
cy.get('.self-remote6-detail-link').click();
cy.verifyContent('Remote6 detail page');

// Use browser back button
cy.go('back');
cy.verifyContent('Remote6 about page');

// Use browser back button again
cy.go('back');
cy.verifyContent('hello remote6 home page');

// Use browser forward button
cy.go('forward');
cy.verifyContent('Remote6 about page');
});
});
});
2 changes: 1 addition & 1 deletion apps/router-demo/router-host-2000/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"forwardAllArgs": false
},
{
"command": "sleep 4 && nx run router-host-2000:e2e",
"command": "sleep 4 && nx run router-host-2000:e2e --watch",
"forwardAllArgs": true
}
]
Expand Down
1 change: 1 addition & 0 deletions apps/router-demo/router-host-2000/rsbuild.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default defineConfig({
'remote-resource-error':
'remote-resource-error@http://localhost:2008/not-exist-mf-manifest.json',
remote5: 'remote5@http://localhost:2005/mf-manifest.json',
remote6: 'remote6@http://localhost:2006/mf-manifest.json',
},
shared: {
react: {
Expand Down
18 changes: 18 additions & 0 deletions apps/router-demo/router-host-2000/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ const Remote5App = createRemoteAppComponent({
fallback: FallbackErrorComp,
loading: FallbackComp,
});
const Remote6App = createRemoteAppComponent({
loader: () => loadRemote('remote6/export-app'),
fallback: FallbackErrorComp,
loading: FallbackComp,
});

const Remote1AppWithLoadRemote = React.lazy(
() =>
Expand Down Expand Up @@ -277,6 +282,19 @@ const App = () => {
/>
)}
/>
<Route
path="/remote6/*"
Component={() => (
<Remote6App
rootOptions={{
identifierPrefix: 'remote6-instance-',
onRecoverableError: (error: Error) => {
console.error('[Host] Remote6 recoverable error:', error);
},
}}
/>
)}
/>
</Routes>
</div>
);
Expand Down
13 changes: 9 additions & 4 deletions apps/router-demo/router-host-2000/src/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function Navgation() {
icon: <GroupOutlined />,
},
{
label: 'Remote1',
label: 'Remote1-React17',
key: '/remote1',
icon: <SettingOutlined />,
children: [
Expand Down Expand Up @@ -53,7 +53,7 @@ function Navgation() {
],
},
{
label: <Link to="/remote2">Remote2</Link>,
label: <Link to="/remote2">Remote2-React18</Link>,
key: '/remote2',
icon: <GroupOutlined />,
children: [
Expand Down Expand Up @@ -90,7 +90,7 @@ function Navgation() {
],
},
{
label: <Link to="/remote3">Remote3</Link>,
label: <Link to="/remote3">Remote3-Vue3</Link>,
key: '/remote3',
icon: <GroupOutlined />,
children: [
Expand Down Expand Up @@ -134,7 +134,7 @@ function Navgation() {
icon: <GroupOutlined />,
},
{
label: <Link to="/remote5">remote5</Link>,
label: <Link to="/remote5">Remote5-React19</Link>,
key: '/remote5',
icon: <GroupOutlined />,
},
Expand All @@ -148,6 +148,11 @@ function Navgation() {
key: '/error-load-with-error-boundary',
icon: <GroupOutlined />,
},
{
label: <Link to="/remote6">Remote6-ReactRouteV7</Link>,
key: '/remote6',
icon: <GroupOutlined />,
},
];

const onClick: MenuProps['onClick'] = (e) => {
Expand Down
18 changes: 18 additions & 0 deletions apps/router-demo/router-remote6-2006/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changelog

## [1.0.34] - 2025-10-15

### Added
- Initial React Router v7 + Module Federation demo
- Bridge router integration with `enableBridgeRouter: true`
- Enhanced error boundaries with React Router v7
- Multiple demo routes (Home, Detail, About)
- Styled components with Emotion
- TypeScript support

### Features
- React Router v7 data APIs
- Module Federation bridge components
- Modern build setup with Rsbuild
- Enhanced routing capabilities
- Better developer experience
60 changes: 60 additions & 0 deletions apps/router-demo/router-remote6-2006/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Router Remote6 (React Router v7 Demo)

A Module Federation remote application demonstrating React Router v7 integration.

## Features

- 🎯 **React Router v7**: Latest routing capabilities with improved DX
- ⚡ **Module Federation**: Micro-frontend architecture
- 🔧 **Rsbuild**: Fast build tool with Rspack
- 🎨 **Emotion**: Styled components with great performance
- 🧩 **Bridge Components**: Seamless integration with host applications

## React Router v7 Highlights

This demo showcases React Router v7 new features:
- Enhanced data loading patterns
- Better TypeScript support
- Improved error boundaries
- Future-ready APIs
- Better performance

## Development

```bash
# Start development server
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview
```

## Usage

The application exposes two federated modules:

- `./button`: A styled button component
- `./export-app`: The main app component with routing

## Configuration

The Module Federation configuration explicitly enables bridge router:

```typescript
bridge: {
enableBridgeRouter: true, // ✅ Explicitly enable bridge router for React Router v7
}
```

## Routes

- `/` - Home page
- `/detail` - Detail page with sample content
- `/about` - About page explaining React Router v7 features

## Port

Development server runs on `http://localhost:2006`
27 changes: 27 additions & 0 deletions apps/router-demo/router-remote6-2006/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "remote6",
"private": true,
"version": "1.0.34",
"scripts": {
"dev": "rsbuild dev",
"build": "rsbuild build",
"preview": "rsbuild preview"
},
"dependencies": {
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@module-federation/bridge-react": "workspace:*",
"@module-federation/rsbuild-plugin": "workspace:*",
"antd": "^5.17.0",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-router": "7.9.4"
},
"devDependencies": {
"@rsbuild/core": "^1.3.21",
"@rsbuild/plugin-react": "^1.0.6",
"@types/react": "^18.2.79",
"@types/react-dom": "^18.3.0",
"typescript": "^5.4.5"
}
}
39 changes: 39 additions & 0 deletions apps/router-demo/router-remote6-2006/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"name": "router-remote6-2006",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "packages/router-demo/router-remote6-2006/src",
"projectType": "library",
"tags": ["type:app"],
"targets": {
"build": {
"executor": "nx:run-commands",
"options": {
"commands": [
"npm run build --prefix apps/router-demo/router-remote6-2006"
]
}
},
"test": {
"executor": "nx:run-commands",
"options": {
"commands": [
"npm run test --prefix apps/router-demo/router-remote6-2006"
]
}
},
"serve": {
"executor": "nx:run-commands",
"options": {
"commands": [
"npm run dev --prefix apps/router-demo/router-remote6-2006"
]
},
"dependsOn": [
{
"target": "build",
"dependencies": true
}
]
}
}
}
Loading
Loading