-
-
Notifications
You must be signed in to change notification settings - Fork 393
Description
| Changelog | 2024-05-22:draft |
|---|---|
| Implementation PR | WIP... |
Summary
Module Federation supports Modern.js SSR , includes stream ssr and string ssr two modes.
Basic example
- Static remote (register remotes in build config)
// config
new ModuleFederation({
remotes: {
remote: 'remote@http://localhost:3001/mf-manifest.json'
}
})
// usage
import Comp from 'remote/Content'- Dynamic remote(register remotes in runtime)
import React, { Suspense } from 'react';
import Button from 'antd/lib/button';
import {
loadRemote,
registerRemotes,
} from '@module-federation/enhanced/runtime';
registerRemotes([
{
name: 'dynamic_remote',
entry: 'http://localhost:3008/mf-stats.json',
},
]);
const Comp = React.lazy(() =>
loadRemote('dynamic_remote/Image').then((m) => {
return m;
}),
);
export default (): JSX.Element => (
<Suspense fallback={'loading'}>
<Comp />
</Suspense>
);Motivation
- Optimize first screen performance
- Support ssr can help to investigate more performance optimization ways
Detailed design
Update stats/manifest/snapshot
Stats/Manifest
Add ssr related fields
// metaData
interface BasicStatsMetaData {
+ ssrRemoteEntry?: ResourceInfo;
}Snapshot
Add ssr related fields
interface BasicProviderModuleInfo extends BasicModuleInfo {
// ssrRemoteEntry/ssrRemoteEntryType only appear while manifest has serveSideRemoteEntry field
+ ssrRemoteEntry?: string;
+ ssrRemoteEntryType?: RemoteEntryType
}render mode
only support stream ssr mode
CSS flickering issue
Leverage mf-stats.json , we can easily get the module css assets, and insert them to html
// encapsulation component for users
const Comp = React.lazy(() =>
loadRemote('dynamic_remote/Image').then((m) => {
return {
default:()=><div>
<link href='http://localhost:3008/static/css/async/__federation_expose_Image.css' rel="stylesheet" type="text/css" />
<span>11</span>
<m.default />
</div>
};
}),
);Cache Strategy
For static remote , there won't be any serious problems. But for dynamic remotes , it may add endless dynamic remotes , and cause memory crashes.
To avoid the issue , it needs to add LRU cache:
- Delete the reference of least usage mf instance, include the shared and expose modules
Data Fetch
Use Modernjs Data loader
Downgrade strategy
Provide two ways to help CSR cab work normally while SSR failed
- Use the runtime version plugin to downgrade the latest available modules
- runtime version plugin: allows users downgrade specific fallback modules while the entry can not get normally
- Provide encapsulation component for users which provide fallback
Dev
LiveReload
fetch all loaded remotes before render host , and judge whether remoteEntry content hash has changed . If yes , flush chunks .
import type { Plugin } from '@modern-js/runtime';
export const mfPluginSSR = (): Plugin => ({
name: '@module-federation/modern-js',
setup: () => ({
async init({ context }, next) {
if (typeof window !== 'undefined') {
return next({ context });
}
const nodeUtils = await import('@module-federation/node/utils');
const shouldUpdate = await nodeUtils.revalidate();
if (shouldUpdate) {
console.log('should HMR', shouldUpdate);
}
return next({ context });
},
}),
});Dynamic remote type hints
notify local broker server while calling loadRemotes , and then the broker server will have the full relationship .
import type { FederationRuntimePlugin } from '@module-federation/enhanced/runtime';
const notifyDynamicRemotePlugin: () => FederationRuntimePlugin = () => ({
name: 'notify-dynamic-remote-plugin',
loadRemote(args) {
if(isDynamicRemote(args)){
notifyBrokerServer(args.remote);
}
return args;
},
});
export default notifyDynamicRemotePlugin;debug
Because node server can not access local env , so not support yet.
It will auto forceCSR when accepting the debug info:
- Chrome devtools
- Skip collect downgrade rate
Drawbacks
- Only support stream ssr , it means that react under version 18 is not supported