Loading Components
This chapter will introduce how to use createLazyComponent
to load and integrate remote React component modules in host applications.
What is createLazyComponent?
createLazyComponent
is an API provided by React Bridge for loading individual remote components. Unlike createRemoteAppComponent
, it is specifically designed for loading specific React components rather than complete applications.
createLazyComponent vs createRemoteAppComponent
Feature | createLazyComponent | createRemoteAppComponent |
---|
Use Case | Load individual remote components | Load complete remote applications |
Router Support | ❌ No routing functionality | ✅ Complete router integration |
Lifecycle | ✅ Basic component lifecycle | ✅ Complete application lifecycle |
Data Fetching | ✅ Supports data fetching | ❌ Depends on application internal handling |
SSR Control | ✅ Controllable SSR | ❌ Determined by application |
Installation
npm install @module-federation/bridge-react@latest
Basic Usage
Step 1: Register lazyLoadComponentPlugin
Register the lazyLoadComponentPlugin plugin at runtime to enable createLazyComponent and prefetch APIs.
import { getInstance } from '@module-federation/runtime';
import { lazyLoadComponentPlugin } from '@module-federation/bridge-react';
const instance = getInstance();
// Register lazyLoadComponentPlugin plugin
instance.registerPlugins([lazyLoadComponentPlugin()]);
Step 2: Call createLazyComponent
After registering the lazyLoadComponentPlugin
plugin, you can create lazy-loaded components using the instance.createLazyComponent
method.
import { getInstance } from '@module-federation/runtime';
import { lazyLoadComponentPlugin } from '@module-federation/bridge-react';
const instance = getInstance();
// After registering lazyLoadComponentPlugin plugin, you can use `createLazyComponent` or `prefetch` APIs
instance.registerPlugins([lazyLoadComponentPlugin()]);
// Use instance.prefetch for remote module data prefetching
instance.prefetch({
id: 'dynamic_remote'
});
// Use instance.createLazyComponent for lazy loading remote modules
const LazyComponent = instance.createLazyComponent({
loader: () => loadRemote('dynamic_remote'),
loading: 'loading...',
fallback: ({ error }) => {
if (error instanceof Error && error.message.includes('not exist')) {
return <div>fallback - not existed id</div>;
}
return <div>fallback</div>;
},
});
createLazyComponent API Reference
Function Signature
function createLazyComponent<T, E extends keyof T>(
options: CreateLazyComponentOptions<T, E>
): React.ComponentType<ComponentProps>
createLazyComponent
This API requires registering the lazyLoadComponentPlugin plugin first before it can be called.
Type declaration
declare function createLazyComponent(
props: CreateLazyComponentOptions
): (props: ComponentType) => React.JSX.Element;
type CreateLazyComponentOptions<T, E extends keyof T> = {
loader: () => Promise<T>;
loading: React.ReactNode;
delayLoading?: number;
fallback: ReactNode | ((errorInfo: ErrorInfo) => ReactNode);
export?: E;
dataFetchParams?: DataFetchParams;
noSSR?: boolean;
injectScript?: boolean;
injectLink?: boolean;
};
type ComponentType = T[E] extends (...args: any) => any
? Parameters<T[E]>[0] extends undefined
? Record<string, never>
: Parameters<T[E]>[0]
: Record<string, never>;
type DataFetchParams = {
isDowngrade: boolean;
} & Record<string, unknown>;
type ErrorInfo = {
error: Error;
errorType: number;
dataFetchMapKey?: string;
};
In addition to loading components, this function also supports the following capabilities:
- In SSR mode, it will inject the corresponding producer's style tags/script resources, which can help avoid CSS flickering issues caused by streaming rendering and accelerate PID (First Paint Interactive Time).
- If the producer has a data fetching function, it will automatically call this function and inject the data.
import React, { FC, memo, useEffect } from 'react';
import { getInstance } from '@module-federation/enhanced/runtime';
import { ERROR_TYPE } from '@module-federation/bridge-react';
const instance = getInstance();
const LazyComponent = instance.createLazyComponent({
loader: () => import('remote/Image'),
loading: <div>loading...</div>,
fallback: ({error,errorType,dataFetchMapKey}) => {
console.error(error)
if(errorType === ERROR_TYPE.LOAD_REMOTE){
return <div>load remote failed</div>
}
if(errorType === ERROR_TYPE.DATA_FETCH){
return <div>data fetch failed, the dataFetchMapKey key is: {dataFetchMapKey}</div>
}
return <div>error type is unknown</div>;
},
});
const App: FC = () => {
return <>
<LazyComponent />
</>;
};
export default App;
loader
- Type:
() => Promise<T>
- Required: Yes
- Default:
undefined
Function to load remote components, typically ()=>loadRemote(id)
or ()=>import(id)
.
loading
- Type:
React.ReactNode
- Required: Yes
- Default:
undefined
Sets the module loading state.
delayLoading
- Type:
number
- Required: No
- Default:
undefined
Sets the delay time for displaying loading state in milliseconds. If the loading time is less than this time, the loading state will not be displayed.
fallback
- Type:
(({ error }: { error: ErrorInfo}) => React.ReactElement)
- Required: Yes
- Default:
undefined
The error component rendered when component loading or rendering fails.
export
- Type:
string
- Required: No
- Default:
'default'
If the remote component is a named export, you can specify the component name to export through this parameter. By default, it loads the default export.
dataFetchParams
- Type:
DataFetchParams
- Required: No
- Default:
undefined
If the remote component has a data fetching function, this will be passed to the data fetching function when set.
noSSR
- Type:
boolean
- Required: No
- Default:
false
When set to true
, this component will not render in SSR scenarios.
injectScript
- Type:
boolean
- Required: No
- Default:
false
In SSR environment, if set to true
, the created component will inject the corresponding script resources.
For example, if remote/button
has __federation_button.js
, then in the HTML returned by SSR, the corresponding script will be injected before the component to accelerate interaction speed.
<script async src="__federation_button.js" crossOrigin="anonymous"/>
<button>remote button</button>
injectLink
- Type:
boolean
- Required: No
- Default:
true
In SSR environment, if set to true
, the created component will inject the corresponding style resource links.
For example, if remote/button
has __federation_button.css
, then in the HTML returned by SSR, the corresponding link will be injected before the component to avoid page flickering issues.
<link href="__federation_button.css" rel="stylesheet" type="text/css">
<button>remote button</button>
prefetch
This API requires registering the lazyLoadComponentPlugin plugin first before it can be called.
Type declaration
type PrefetchOptions = {
id: string;
dataFetchParams?: DataFetchParams;
preloadComponentResource?: boolean;
};
type DataFetchParams = {
isDowngrade: boolean;
_id?: string;
} & Record<string, unknown>;
Preload component resource files and the component's data loader.
import React, { FC, memo, useEffect } from 'react';
import { getInstance } from '@module-federation/enhanced/runtime';
const instance = getInstance();
instance.prefetch({
id: 'remote/Image',
preloadComponentResource: true,
});
id
- Type:
string
- Required: Yes
- Default:
undefined
The id of the component to preload.
preloadComponentResource
- Type:
boolean
- Required: No
- Default:
false
Whether to preload the component's resource files.
dataFetchParams
- Type:
DataFetchParams
- Required: No
- Default:
undefined
If the remote component has a data fetching function, this will be passed to the data fetching function when set.