Skip to content

Commit 5269a21

Browse files
committed
fix(rsc-mf): proxy remote async assets via host server
1 parent 2af359d commit 5269a21

2 files changed

Lines changed: 89 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { ModuleFederationRuntimePlugin } from '@module-federation/modern-js-v3';
2+
3+
const forceRemotePublicPath = (): ModuleFederationRuntimePlugin => ({
4+
name: 'rsc-mf-force-remote-public-path',
5+
loadRemoteSnapshot(args: any) {
6+
const { remoteInfo, remoteSnapshot } = args;
7+
if (remoteInfo?.alias !== 'rscRemote' || !remoteSnapshot) {
8+
return args;
9+
}
10+
11+
const entry = remoteInfo?.entry;
12+
if (!entry || typeof entry !== 'string') {
13+
return args;
14+
}
15+
const remotePublicPath = `${new URL(entry).origin}/`;
16+
17+
if ('publicPath' in remoteSnapshot) {
18+
remoteSnapshot.publicPath = remotePublicPath;
19+
}
20+
if (remoteSnapshot.metaData && 'publicPath' in remoteSnapshot.metaData) {
21+
remoteSnapshot.metaData.publicPath = remotePublicPath;
22+
}
23+
if (remoteSnapshot.metaData && 'ssrPublicPath' in remoteSnapshot.metaData) {
24+
remoteSnapshot.metaData.ssrPublicPath = `${remotePublicPath}bundles/`;
25+
}
26+
27+
return args;
28+
},
29+
});
30+
31+
export default forceRemotePublicPath;
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {
2+
type MiddlewareHandler,
3+
defineServerConfig,
4+
} from '@modern-js/server-runtime';
5+
6+
const shouldProxyRemoteAsset = (pathname: string) => {
7+
if (pathname.startsWith('/static/js/async/')) {
8+
return (
9+
pathname.includes('__federation_expose_') ||
10+
pathname.includes('_react-server-components_') ||
11+
pathname.includes('node_modules_pnpm_react')
12+
);
13+
}
14+
15+
if (pathname.startsWith('/static/css/async/')) {
16+
return pathname.includes('__federation_expose_');
17+
}
18+
19+
return false;
20+
};
21+
22+
const proxyRemoteFederationAsset: MiddlewareHandler = async (c, next) => {
23+
const reqUrl = new URL(c.req.url);
24+
const pathname = reqUrl.pathname;
25+
26+
if (!shouldProxyRemoteAsset(pathname)) {
27+
await next();
28+
return;
29+
}
30+
31+
const remotePort = process.env.RSC_MF_REMOTE_PORT;
32+
if (!remotePort) {
33+
await next();
34+
return;
35+
}
36+
37+
const remoteUrl = `http://127.0.0.1:${remotePort}${pathname}${reqUrl.search}`;
38+
const upstream = await fetch(remoteUrl).catch(() => undefined);
39+
40+
if (!upstream || !upstream.ok) {
41+
await next();
42+
return;
43+
}
44+
45+
c.res = new Response(await upstream.arrayBuffer(), {
46+
status: upstream.status,
47+
headers: upstream.headers,
48+
});
49+
};
50+
51+
export default defineServerConfig({
52+
middlewares: [
53+
{
54+
name: 'proxy-remote-federation-asset',
55+
handler: proxyRemoteFederationAsset,
56+
},
57+
],
58+
});

0 commit comments

Comments
 (0)