Skip to content
Open
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
2 changes: 1 addition & 1 deletion apps/website-new/docs/en/guide/framework/modernjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ The Modern.js plugin re-exports `@module-federation/bridge-react` from `@module-
### createRemoteComponent <Badge type="danger">Deprecated</Badge>

::: danger
This API has been deprecated. Please use [createLazyComponent](/practice/bridge/react-bridge/load-component.html#createlazycomponent-vs-createremoteappcomponent) instead.
This API has been deprecated. Please use [createLazyComponent](/practice/bridge/react-bridge/load-component.html#what-is-createlazycomponent) instead.
:::

#### Migration Guide
Expand Down
110 changes: 109 additions & 1 deletion apps/website-new/docs/en/practice/bridge/react-bridge/load-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,112 @@ interface RemoteComponentProps<T = Record<string, unknown>> {
loader: () => loadRemote('remote1/export-app'),
export: 'dashboard'
})
```
```

## Bundle Size Optimization

### React Router Dependency Explanation

By default, `@module-federation/bridge-react` includes `react-router-dom` in your bundle to provide the following out-of-the-box capabilities:

- ✅ Automatic basename injection - No manual route base path configuration needed
- ✅ Router context passing - Automatic React Router context handling
- ✅ Nested routing support - Complete router integration capabilities

**However**, if your project meets any of these conditions:
- Doesn't need routing functionality (pure component loading)
- Uses a non-react-router routing framework (e.g., TanStack Router)
- Wants to minimize bundle size

**We recommend** disabling the `enableBridgeRouter` configuration to turn off this capability, which will:
- ✅ Reduce bundle size by ~3KB (gzipped)
- ✅ Avoid unnecessary dependency injection
- ✅ Eliminate potential version conflict risks

### How to Disable Router Dependency

You can control whether to include router support through the `bridge.enableBridgeRouter` configuration:

```ts title="rsbuild.config.ts"
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default {
plugins: [
pluginModuleFederation({
name: 'host-app',
remotes: {
remote1: 'remote1@http://localhost:3001/mf-manifest.json',
},
bridge: {
// Disable router support to reduce bundle size
enableBridgeRouter: false,
},
}),
],
};
```

:::tip Configuration Behavior
- **`enableBridgeRouter: false`**: Automatically aliases to `/base` entry point (no react-router-dom code)
- **`enableBridgeRouter: true`** or **`undefined`**: Includes router support (default behavior)
:::

### When to Disable Router?

**Disable router** (`enableBridgeRouter: false`) when:
- ✅ Your application doesn't use react-router
- ✅ You want to minimize bundle size
- ✅ You can manually manage basename if needed

**Keep router enabled** (default) when:
- ✅ Your application uses react-router
- ✅ You need automatic basename injection
- ✅ You need routing context integration

### Migration Example

#### Before: With Router (Default)
```tsx
import { createRemoteAppComponent } from '@module-federation/bridge-react';

const RemoteApp = createRemoteAppComponent({
loader: () => loadRemote('remote1/app'),
loading: <div>Loading...</div>,
fallback: ErrorBoundary,
});

// basename automatically retrieved from router context
<RemoteApp />
```

#### After: Without Router (Optimized)
```ts title="rsbuild.config.ts"
// Configuration
pluginModuleFederation({
bridge: {
enableBridgeRouter: false, // Disable router
},
})
```

```tsx
import { createRemoteAppComponent } from '@module-federation/bridge-react';

const RemoteApp = createRemoteAppComponent({
loader: () => loadRemote('remote1/app'),
loading: <div>Loading...</div>,
fallback: ErrorBoundary,
});

// No changes needed! The plugin automatically aliases to /base entry
<RemoteApp basename="/" /> // Manually pass basename if needed
```

:::info How It Works
When `enableBridgeRouter: false`, the Module Federation plugin automatically sets up a webpack alias:
```
'@module-federation/bridge-react' → '@module-federation/bridge-react/base'
```

This means your imports automatically resolve to the router-free version without changing any code!
:::
2 changes: 1 addition & 1 deletion apps/website-new/docs/zh/guide/framework/modernjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export default App;
### createRemoteSSRComponent <Badge type="danger">废弃</Badge>

::: danger
此 API 已被废弃,请使用[createLazyComponent](../../practice/bridge/react-bridge#createlazycomponent) 。
此 API 已被废弃,请使用[createLazyComponent](/practice/bridge/react-bridge/load-component.html#什么是-createlazycomponent) 。
:::

#### 如何迁移
Expand Down
Empty file.
124 changes: 117 additions & 7 deletions apps/website-new/docs/zh/practice/bridge/react-bridge/load-app.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ function createRemoteAppComponent<T = Record<string, unknown>, E extends keyof T
>
```

### RemoteComponentParams\<T, E\>
#### RemoteComponentParams\<T, E\>

配置参数接口:

Expand All @@ -206,7 +206,7 @@ interface RemoteComponentParams<T = Record<string, unknown>, E extends keyof T =
}
```

### RemoteComponentProps\<T\>
#### RemoteComponentProps\<T\>

返回组件的属性接口:

Expand Down Expand Up @@ -241,7 +241,7 @@ interface RemoteComponentProps<T = Record<string, unknown>> {

### 参数详解

### loader
#### loader

- **类型**: `() => Promise<T>`
- **必需**: 是
Expand All @@ -252,7 +252,7 @@ interface RemoteComponentProps<T = Record<string, unknown>> {
loader: () => import('remote1/export-app')
```

### loading
#### loading

- **类型**: `React.ReactNode`
- **必需**: 是
Expand All @@ -264,7 +264,7 @@ interface RemoteComponentProps<T = Record<string, unknown>> {
loading: <Spinner />
```

### fallback
#### fallback

- **类型**: `React.ComponentType<{ error: Error }>`
- **必需**: 是
Expand All @@ -275,7 +275,7 @@ interface RemoteComponentProps<T = Record<string, unknown>> {
fallback: ErrorBoundaryComponent
```

### export
#### export

- **类型**: `E extends keyof T` (泛型约束,通常是 `string`)
- **必需**: 否
Expand Down Expand Up @@ -310,4 +310,114 @@ interface RemoteComponentProps<T = Record<string, unknown>> {
loader: () => loadRemote('remote1/export-app'),
export: 'dashboard'
})
```
```


## Bundle 体积优化

### React Router 依赖说明

默认情况下,`@module-federation/bridge-react` 会将 `react-router-dom` 打包到你的 bundle 中,这是为了提供以下开箱即用的能力:

- ✅ 自动 basename 注入 - 无需手动配置路由基础路径
- ✅ 路由上下文传递 - 自动处理 React Router 上下文
- ✅ 嵌套路由支持 - 完整的路由集成能力

**但是**,如果你的项目满足以下任一条件:
- 不需要路由功能(纯组件加载)
- 使用非 react-router 的路由框架(如 TanStack Router)
- 希望最小化 bundle 体积

**建议关闭** `enableBridgeRouter` 配置来禁用此能力,这将:
- ✅ 减小 bundle 体积约 3KB (gzipped)
- ✅ 避免不必要的依赖注入
- ✅ 消除潜在的版本冲突风险

### 如何禁用 Router 依赖

你可以通过 `bridge.enableBridgeRouter` 配置来控制是否包含路由支持:

```ts title="rsbuild.config.ts"
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';

export default {
plugins: [
pluginModuleFederation({
name: 'host-app',
remotes: {
remote1: 'remote1@http://localhost:3001/mf-manifest.json',
},
bridge: {
// 禁用路由支持以减小 bundle 体积
enableBridgeRouter: false,
},
}),
],
};
```

:::tip 配置行为
- **`enableBridgeRouter: false`**: 自动 alias 到 `/base` 入口(不包含 react-router-dom 代码)
- **`enableBridgeRouter: true`** 或 **`undefined`**: 包含路由支持(默认行为)

:::

### 何时禁用 Router?

**禁用 router** (`enableBridgeRouter: false`) 适用于:
- ✅ 应用不使用 react-router
- ✅ 想要最小化 bundle 体积
- ✅ 可以手动管理 basename(如果需要)

**保持 router 启用**(默认)适用于:
- ✅ 应用使用 react-router
- ✅ 需要自动 basename 注入
- ✅ 需要路由上下文集成

### 迁移示例

#### 迁移前:启用 Router(默认)
```tsx
import { createRemoteAppComponent } from '@module-federation/bridge-react';

const RemoteApp = createRemoteAppComponent({
loader: () => loadRemote('remote1/app'),
loading: <div>Loading...</div>,
fallback: ErrorBoundary,
});

// basename 自动从路由上下文获取
<RemoteApp />
```

#### 迁移后:禁用 Router(优化)
```ts title="rsbuild.config.ts"
// 配置
pluginModuleFederation({
bridge: {
enableBridgeRouter: false, // 禁用 router
},
})
```

```tsx
import { createRemoteAppComponent } from '@module-federation/bridge-react';

const RemoteApp = createRemoteAppComponent({
loader: () => loadRemote('remote1/app'),
loading: <div>Loading...</div>,
fallback: ErrorBoundary,
});

// 无需修改代码!插件会自动 alias 到 /base 入口
<RemoteApp basename="/" /> // 如果需要,手动传递 basename
```

:::info 工作原理
当设置 `enableBridgeRouter: false` 时,Module Federation 插件会自动设置 webpack alias:
```
'@module-federation/bridge-react' → '@module-federation/bridge-react/base'
```

这意味着你的导入会自动解析到无路由版本,无需修改任何代码!
:::
4 changes: 2 additions & 2 deletions packages/bridge/bridge-react-webpack-plugin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ class ReactBridgeAliasChangerPlugin {
const originalResolve = compiler.options.resolve || {};
const originalAlias = originalResolve.alias || {};

// Update alias
const updatedAlias = {
// Update alias - set up router version alias
const updatedAlias: Record<string, string> = {
// allow `alias` can be override
// [this.alias]: targetFilePath,
...getBridgeRouterAlias(originalAlias['react-router-dom']),
Expand Down
8 changes: 8 additions & 0 deletions packages/bridge/bridge-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
"import": "./dist/index.es.js",
"require": "./dist/index.cjs.js"
},
"./base": {
"types": "./dist/base.d.ts",
"import": "./dist/base.es.js",
"require": "./dist/base.cjs.js"
},
"./v18": {
"types": "./dist/v18.d.ts",
"import": "./dist/v18.es.js",
Expand Down Expand Up @@ -83,6 +88,9 @@
".": [
"./dist/index.d.ts"
],
"base": [
"./dist/base.d.ts"
],
"v18": [
"./dist/v18.d.ts"
],
Expand Down
50 changes: 50 additions & 0 deletions packages/bridge/bridge-react/src/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
export { createBridgeComponent } from './provider/versions/legacy';

// Export router-free versions of remote component creators
export {
createRemoteComponent,
createRemoteAppComponent,
} from './remote/base-component';
export type { LazyRemoteComponentInfo } from './remote/base-component';

// Export all lazy loading and data fetching utilities (no router dependencies)
export {
ERROR_TYPE,
createLazyComponent,
collectSSRAssets,
callDataFetch,
setSSREnv,
autoFetchDataPlugin,
CacheSize,
CacheTime,
configureCache,
generateKey,
cache,
revalidateTag,
clearStore,
prefetch,
} from './lazy';

export { lazyLoadComponentPlugin } from './plugins/lazy-load-component-plugin';

// Export all types
export type { CreateRootOptions, Root } from './provider/versions/legacy';
export type {
ProviderParams,
ProviderFnParams,
RootType,
DestroyParams,
RenderParams,
RemoteComponentParams,
RenderFnParams,
RemoteComponentProps,
RemoteModule,
} from './types';
export type {
DataFetchParams,
NoSSRRemoteInfo,
CollectSSRAssetsOptions,
CreateLazyComponentOptions,
CacheStatus,
CacheStatsInfo,
} from './lazy';
4 changes: 2 additions & 2 deletions packages/bridge/bridge-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export { createBridgeComponent } from './provider/versions/legacy';
export {
createRemoteComponent,
createRemoteAppComponent,
} from './remote/create';
export type { LazyRemoteComponentInfo } from './remote/create';
} from './remote/router-component';
export type { LazyRemoteComponentInfo } from './remote/router-component';
export {
ERROR_TYPE,
createLazyComponent,
Expand Down
Loading