Modern.js
This plugin provides Module Federation supporting functions for Modern.js
Supports
- modern.js ^2.56.1
- Server-Side Rendering
We highly recommend referencing this application which takes advantage of the best capabilities:
module-federation example
Quick Start
Installation
You can install the plugin with the following commands:
npm add @module-federation/modern-js --save
Apply Plugin
Apply this plugin in plugins
of modern.config.ts
:
modern.config.ts
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js';
export default defineConfig({
dev: {
port: 3005,
},
runtime: {
router: true,
},
// moduleFederationPlugin is a plug-in for modern.js, which can make certain modifications to the build/runtime
plugins: [appTools(), moduleFederationPlugin()],
});
Then create the module-federation.config.ts
file and write the required configuration:
module-federation.config.ts
import { createModuleFederationConfig } from '@module-federation/modern-js';
export default createModuleFederationConfig({
name: 'host',
remotes: {
remote: 'remote@http://localhost:3006/mf-manifest.json',
},
shared: {
react: { singleton: true },
'react-dom': { singleton: true },
},
});
Type support
add /// <reference types='@module-federation/modern-js/types' />
in modern-app-env.d.ts
to get type support.
modern-app-env.d.ts
+ /// <reference types='@module-federation/modern-js/types' />
Server-Side Rendering
INFO
For a better performance experience, Module Federation X Modern.js SSR only supports stream SSR.
There is no difference between using Module Federation in SSR scenarios and CSR scenarios. Developers can just keep following the original development behavior.
But for a better user experience, we provide supporting functions/components to help developers better use Module Federation.
createRemoteSSRComponent
Type declaration
declare function createRemoteSSRComponent(
props: CreateRemoteSSRComponentOptions
): (props: ComponentType) => React.JSX.Element;
type CreateRemoteSSRComponentOptions = {
loader: () => Promise<T>;
loading: React.ReactNode;
fallback: ErrorBoundaryPropsWithComponent['FallbackComponent'];
export?: E;
};
type ComponentType = T[E] extends (...args: any) => any
? Parameters<T[E]>[0] extends undefined
? Record<string, never>
: Parameters<T[E]>[0]
: Record<string, never>;
This function will also help inject the corresponding style tag/script while loading the component. This behavior can help avoid the CSS flickering problem caused by streaming rendering and accelerate the PID (first screen interactive time).
Example
import React, { FC, memo, useEffect } from 'react';
import { registerRemotes, createRemoteSSRComponent } from '@modern-js/runtime/mf';
// The remote declared in the build plug-in can be imported directly at the top level
import RemoteComp from 'remote/Image';
const RemoteSSRComponent = createRemoteSSRComponent({
// The remote declared in the build plug-in can also be loaded using this function: loader: () => import('remote/Image'),
loader: () => loadRemote('dynamic_remote/Image'),
loading: <div>loading...</div>,
fallback: ({ error }) => {
if (error instanceof Error && error.message.includes('not exist')) {
return <div>fallback - not existed id</div>;
}
return <div>fallback</div>;
},
});
const Product: FC = () => {
registerRemotes([
{
name: 'dynamic_remote',
entry: 'http://localhost:3008/mf-manifest.json',
},
]);
const fallback = (err: Error) => {
if (err.message.includes('does not exist in container')) {
return <div>404</div>;
}
throw err;
};
return <>
<RemoteSSRComponent />
<RemoteComp />
</>;
};
export default Product;
loading
- Type:
React.ReactNode
- Required: Yes
- Default value:
undefined
Set module loading status.
fallback
- Type:
((err: Error) => React.ReactElement)
- Required: Yes
- Default value:
undefined
A fault-tolerant component that is rendered when the component fails to load or render.
Note: This component only renders this fault-tolerant component on the client side when rendering fails.
Configuration
ssr
- Type:
false
- Is it required: No
- Default value:
undefined
@module-federation/modern-js
will automatically add SSR related build presets based on server.ssr
in modern.js config.
If the current project only needs to load MF in the CSR, you can set ssr: false
to help progressive migration.
import { appTools, defineConfig } from '@modern-js/app-tools';
import { moduleFederationPlugin } from '@module-federation/modern-js';
// https://modernjs.dev/en/configure/app/usage
export default defineConfig({
dev: {
port: 3050,
},
runtime: {
router: true,
},
server: {
ssr: {
mode: 'stream',
},
},
plugins: [
appTools(),
moduleFederationPlugin({ ssr: false })
],
});