Skip to content

Commit ebe14e1

Browse files
authored
chore: add example (#3825)
1 parent 0b4b748 commit ebe14e1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4000
-0
lines changed

pnpm-workspace.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ packages:
1111
- '!nextjs-dynamic-ssr/*'
1212
- '!cra-react-app-rewired/*'
1313
- '!runtime-plugins/remote-router'
14+
- '!react-manifest-example'

react-manifest-example/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Module Federation 2.0 with Rspack in React
2+
3+
This repo uses Module Federation 2.0 Rspack plugin to build a React microfrontend
4+
5+
## Get started
6+
7+
```shell
8+
cd react-manifest-example
9+
# In the reacts-manifest-example directory
10+
# You do not need to run the installation command in this directory
11+
pnpm install
12+
pnpm run start
13+
```
14+
15+
Host runs at http://localhost:9000 (live reload only)
16+
Remote1 runs at http://localhost:9001 (HMR supported)
17+
Remote2 runs at http://localhost:9002 (HMR supported)
18+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import type { PackageType as PackageType_0,RemoteKeys as RemoteKeys_0 } from './remote1/apis.d.ts';
2+
import type { PackageType as PackageType_1,RemoteKeys as RemoteKeys_1 } from './remote2/apis.d.ts';
3+
declare module "@module-federation/runtime" {
4+
type RemoteKeys = RemoteKeys_0 | RemoteKeys_1;
5+
type PackageType<T, Y=any> = T extends RemoteKeys_0 ? PackageType_0<T> :
6+
T extends RemoteKeys_1 ? PackageType_1<T> :
7+
Y ;
8+
export function loadRemote<T extends RemoteKeys,Y>(packageName: T): Promise<PackageType<T, Y>>;
9+
export function loadRemote<T extends string,Y>(packageName: T): Promise<PackageType<T, Y>>;
10+
}
11+
declare module "@module-federation/enhanced/runtime" {
12+
type RemoteKeys = RemoteKeys_0 | RemoteKeys_1;
13+
type PackageType<T, Y=any> = T extends RemoteKeys_0 ? PackageType_0<T> :
14+
T extends RemoteKeys_1 ? PackageType_1<T> :
15+
Y ;
16+
export function loadRemote<T extends RemoteKeys,Y>(packageName: T): Promise<PackageType<T, Y>>;
17+
export function loadRemote<T extends string,Y>(packageName: T): Promise<PackageType<T, Y>>;
18+
}
19+
declare module "@module-federation/runtime-tools" {
20+
type RemoteKeys = RemoteKeys_0 | RemoteKeys_1;
21+
type PackageType<T, Y=any> = T extends RemoteKeys_0 ? PackageType_0<T> :
22+
T extends RemoteKeys_1 ? PackageType_1<T> :
23+
Y ;
24+
export function loadRemote<T extends RemoteKeys,Y>(packageName: T): Promise<PackageType<T, Y>>;
25+
export function loadRemote<T extends string,Y>(packageName: T): Promise<PackageType<T, Y>>;
26+
}
27+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
export type RemoteKeys = 'remote1/button' | 'remote1/app';
3+
type PackageType<T> = T extends 'remote1/app' ? typeof import('remote1/app') :T extends 'remote1/button' ? typeof import('remote1/button') :any;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './compiled-types/app';
2+
export { default } from './compiled-types/app';
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './compiled-types/button';
2+
export { default } from './compiled-types/button';
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import './App.css';
2+
declare const App: (info?: {
3+
abc?: string;
4+
}) => import("react/jsx-runtime").JSX.Element;
5+
export default App;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default function Button(): import("react/jsx-runtime").JSX.Element;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
export type RemoteKeys = 'remote2/button';
3+
type PackageType<T> = T extends 'remote2/button' ? typeof import('remote2/button') :any;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './compiled-types/button';
2+
export { default } from './compiled-types/button';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export default function Button(): import("react/jsx-runtime").JSX.Element;

react-manifest-example/host/README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Rsbuild Project
2+
3+
## Setup
4+
5+
Install the dependencies:
6+
7+
```bash
8+
pnpm install
9+
```
10+
11+
## Get Started
12+
13+
Start the dev server:
14+
15+
```bash
16+
pnpm dev
17+
```
18+
19+
Build the app for production:
20+
21+
```bash
22+
pnpm build
23+
```
24+
25+
Preview the production build locally:
26+
27+
```bash
28+
pnpm preview
29+
```
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "react-manifest-example_host",
3+
"private": true,
4+
"version": "1.0.0",
5+
"scripts": {
6+
"dev": "rsbuild dev --open",
7+
"build": "rsbuild build",
8+
"preview": "rsbuild preview"
9+
},
10+
"dependencies": {
11+
"@ant-design/icons": "^5.3.6",
12+
"@module-federation/enhanced": "0.1.7",
13+
"antd": "^5.16.2",
14+
"react": "^18.2.0",
15+
"react-dom": "^18.2.0",
16+
"react-router-dom": "^6.22.3"
17+
},
18+
"devDependencies": {
19+
"@rsbuild/core": "^0.6.3",
20+
"@rsbuild/plugin-react": "^0.6.3",
21+
"@types/react": "^18.2.79",
22+
"@types/react-dom": "^18.2.25",
23+
"typescript": "^5.4.5"
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { defineConfig } from '@rsbuild/core';
2+
import { pluginReact } from '@rsbuild/plugin-react';
3+
import { ModuleFederationPlugin } from '@module-federation/enhanced/rspack';
4+
5+
export default defineConfig({
6+
server: {
7+
port: 9000,
8+
},
9+
tools: {
10+
rspack: (config, { appendPlugins }) => {
11+
appendPlugins([
12+
new ModuleFederationPlugin({
13+
name: 'host',
14+
remotes: {
15+
remote1: 'remote1@http://localhost:9001/mf-manifest.json',
16+
remote2: 'remote2@http://localhost:9002/mf-manifest.json',
17+
},
18+
shared: ['react', 'react-dom'],
19+
}),
20+
]);
21+
},
22+
},
23+
plugins: [pluginReact()],
24+
});
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* body {
2+
margin: 0;
3+
color: #fff;
4+
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
5+
background-image: linear-gradient(to bottom, #020917, #101725);
6+
}
7+
8+
.content {
9+
display: flex;
10+
min-height: 100vh;
11+
line-height: 1.1;
12+
text-align: center;
13+
flex-direction: column;
14+
justify-content: center;
15+
}
16+
17+
.content h1 {
18+
font-size: 3.6rem;
19+
font-weight: 700;
20+
}
21+
22+
.content p {
23+
font-size: 1.2rem;
24+
font-weight: 400;
25+
opacity: 0.5;
26+
} */
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
2+
import Navigation from './navigation';
3+
import './App.css';
4+
import { useMemo, useState } from 'react';
5+
import Home from './pages/Home';
6+
import Remote1 from './pages/remote1';
7+
import Remote2 from './pages/remote2';
8+
9+
10+
11+
12+
const App = () => {
13+
return (
14+
<BrowserRouter basename="/">
15+
<Navigation />
16+
<Routes>
17+
<Route path="/" Component={Home}/>
18+
<Route path="/remote1" Component={()=> <Remote1 />}/>
19+
<Route path="/remote2" Component={()=> <Remote2 />}/>
20+
</Routes>
21+
</BrowserRouter>
22+
);
23+
};
24+
25+
export default App;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom/client';
3+
import App from './App';
4+
5+
const root = ReactDOM.createRoot(document.getElementById('root')!);
6+
root.render(
7+
<React.StrictMode>
8+
<App />
9+
</React.StrictMode>,
10+
);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/// <reference types="@rsbuild/core/types" />
2+
3+
// import type { PackageType as PackageType_0,RemoteKeys as RemoteKeys_0, PackageExportType as PackageExportType_0 } from './remote2/apis.d.ts';
4+
// import type { PackageType as PackageType_1,RemoteKeys as RemoteKeys_1, PackageExportType as PackageExportType_1 } from './remote1/apis.d.ts';
5+
6+
7+
// declare module "@module-federation/enhanced/runtime" {
8+
// type RemoteKeys = RemoteKeys_0 | RemoteKeys_1;
9+
// type PackageType<T, R=any> = T extends RemoteKeys_0 ? PackageType_0<T> : T extends RemoteKeys_1 ? PackageType_1<T> : R ;
10+
// type GetType<T, Y extends keyof T> = T[Y];
11+
// export function createRemoteComponent<T extends RemoteKeys,Y>(info: {name: T, export: Y}): GetType<PackageType<T>, Y>;
12+
// }
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import('./bootstrap');
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, { useState } from 'react';
2+
import { BrowserRouter, createBrowserRouter, Routes, Router, Route, Link, RouterProvider, useLocation } from 'react-router-dom';
3+
import type { MenuProps } from 'antd';
4+
import { Menu, Timeline } from 'antd';
5+
import { GroupOutlined, HomeOutlined, SettingOutlined } from '@ant-design/icons';
6+
7+
8+
9+
function Navgation () {
10+
let location = useLocation();
11+
const [current, setCurrent] = useState(location.pathname);
12+
13+
const items: MenuProps['items'] = [
14+
{
15+
label: (
16+
<Link to="/">
17+
Home
18+
</Link>
19+
),
20+
key: '/',
21+
icon: <HomeOutlined />,
22+
},
23+
{
24+
label: (
25+
<Link to="/remote1">
26+
Remote1
27+
</Link>
28+
),
29+
key: '/remote1',
30+
icon: <GroupOutlined />,
31+
},
32+
{
33+
label: (
34+
<Link to="/remote2">
35+
Remote2
36+
</Link>
37+
),
38+
key: '/remote2',
39+
icon: <GroupOutlined />
40+
},
41+
];
42+
43+
const onClick: MenuProps['onClick'] = (e) => {
44+
setCurrent(e.key);
45+
};
46+
return <Menu onClick={onClick} selectedKeys={[current]} mode="horizontal" items={items} />;
47+
48+
}
49+
50+
export default Navgation;
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React from 'react';
2+
import { Space, Table, Tag } from 'antd';
3+
import type { TableProps } from 'antd';
4+
5+
interface DataType {
6+
key: string;
7+
name: string;
8+
age: number;
9+
address: string;
10+
tags: string[];
11+
}
12+
13+
const columns: TableProps<DataType>['columns'] = [
14+
{
15+
title: 'Name',
16+
dataIndex: 'name',
17+
key: 'name',
18+
render: (text) => <a>{text}</a>,
19+
},
20+
{
21+
title: 'Age',
22+
dataIndex: 'age',
23+
key: 'age',
24+
},
25+
{
26+
title: 'Address',
27+
dataIndex: 'address',
28+
key: 'address',
29+
},
30+
{
31+
title: 'Tags',
32+
key: 'tags',
33+
dataIndex: 'tags',
34+
render: (_, { tags }) => (
35+
<>
36+
{tags.map((tag) => {
37+
let color = tag.length > 5 ? 'geekblue' : 'green';
38+
if (tag === 'loser') {
39+
color = 'volcano';
40+
}
41+
return (
42+
<Tag color={color} key={tag}>
43+
{tag.toUpperCase()}
44+
</Tag>
45+
);
46+
})}
47+
</>
48+
),
49+
},
50+
{
51+
title: 'Action',
52+
key: 'action',
53+
render: (_, record) => (
54+
<Space size="middle">
55+
<a>Invite {record.name}</a>
56+
<a>Delete</a>
57+
</Space>
58+
),
59+
},
60+
];
61+
62+
const data: DataType[] = [
63+
{
64+
key: '1',
65+
name: 'John Brown',
66+
age: 32,
67+
address: 'New York No. 1 Lake Park',
68+
tags: ['nice', 'developer'],
69+
},
70+
{
71+
key: '2',
72+
name: 'Jim Green',
73+
age: 42,
74+
address: 'London No. 1 Lake Park',
75+
tags: ['loser'],
76+
},
77+
{
78+
key: '3',
79+
name: 'Joe Black',
80+
age: 32,
81+
address: 'Sydney No. 1 Lake Park',
82+
tags: ['cool', 'teacher'],
83+
},
84+
];
85+
86+
const Home: React.FC = () => <Table columns={columns} dataSource={data} />;
87+
88+
export default Home;

0 commit comments

Comments
 (0)