Skip to content

Commit a1f3470

Browse files
committed
chore: wip
1 parent 23a29a6 commit a1f3470

File tree

18 files changed

+364
-200
lines changed

18 files changed

+364
-200
lines changed

apps/modern-component-data-fetch/host/src/routes/page.tsx

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,34 +11,38 @@ const RemoteSSRComponent = createRemoteSSRComponent({
1111
fallback: ({ error }) => {
1212
console.log(33333333333);
1313
console.error(error);
14+
// throw new Error('error no caught');
1415
if (error instanceof Error && error.message.includes('not exist')) {
1516
return <div>fallback - not existed id</div>;
1617
}
1718
return <div>fallback</div>;
1819
},
1920
});
2021

21-
const RemoteSSRComponent2 = createRemoteSSRComponent({
22-
loader: () => import('remote/Content2'),
23-
loading: 'loading...',
24-
export: 'default',
25-
fallback: ({ error }) => {
26-
console.log(33333333333);
27-
console.error(error);
28-
if (error instanceof Error && error.message.includes('not exist')) {
29-
return <div>fallback - not existed id</div>;
30-
}
31-
return <div>fallback</div>;
32-
},
33-
});
22+
// const RemoteSSRComponent2 = createRemoteSSRComponent({
23+
// loader: () => import('remote/Content2'),
24+
// loading: 'loading...',
25+
// export: 'default',
26+
// fallback: ({ error }) => {
27+
// console.log(33333333333);
28+
// console.error(error);
29+
// if (error instanceof Error && error.message.includes('not exist')) {
30+
// return <div>fallback - not existed id</div>;
31+
// }
32+
// return <div>fallback</div>;
33+
// },
34+
// });
3435

35-
const Index = () => (
36-
<>
37-
<div className="container-box">
38-
<RemoteSSRComponent />
39-
<RemoteSSRComponent2 />
40-
</div>
41-
</>
42-
);
36+
const Index = () => {
37+
return (
38+
<>
39+
<div className="container-box">
40+
<h1>asdadasdasd</h1>
41+
<RemoteSSRComponent />
42+
{/* <RemoteSSRComponent2 /> */}
43+
</div>
44+
</>
45+
);
46+
};
4347

4448
export default Index;

apps/modern-component-data-fetch/provider/module-federation.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ export default createModuleFederationConfig({
1111
react: { singleton: true },
1212
'react-dom': { singleton: true },
1313
},
14+
runtimePlugins: ['./runtimePlugin.ts'],
1415
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { FederationRuntimePlugin } from '@module-federation/modern-js';
2+
3+
export default function (): FederationRuntimePlugin {
4+
return {
5+
name: 'next-internal-plugin',
6+
beforeInit: function (args) {
7+
if (typeof window === 'undefined') {
8+
throw new Error('Force downgrade');
9+
}
10+
return args;
11+
},
12+
};
13+
}

packages/modernjs/src/cli/configPlugin.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,11 @@ const patchDTSConfig = (
146146
export const patchMFConfig = (
147147
mfConfig: moduleFederationPlugin.ModuleFederationPluginOptions,
148148
isServer: boolean,
149+
enableSSR = false,
149150
remoteIpStrategy?: 'ipv4' | 'inherit',
150151
) => {
151152
replaceRemoteUrl(mfConfig, remoteIpStrategy);
152-
addDataFetchExposes(mfConfig.exposes, isServer);
153+
addDataFetchExposes(mfConfig.exposes, isServer, enableSSR);
153154

154155
if (mfConfig.remoteType === undefined) {
155156
mfConfig.remoteType = 'script';
@@ -404,6 +405,7 @@ export const moduleFederationConfigPlugin = (
404405
patchMFConfig(
405406
targetMFConfig,
406407
!isWeb,
408+
enableSSR,
407409
userConfig.remoteIpStrategy || 'ipv4',
408410
);
409411

packages/modernjs/src/cli/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,5 @@ export const moduleFederationPlugin = (
7979
export default moduleFederationPlugin;
8080

8181
export { createModuleFederationConfig } from '@module-federation/enhanced';
82+
83+
export type { FederationRuntimePlugin } from '@module-federation/enhanced/runtime';

packages/modernjs/src/cli/mfRuntimePlugins/auto-fetch-data.ts

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,28 @@
11
import type { FederationRuntimePlugin } from '@module-federation/enhanced/runtime';
2-
import helpers from '@module-federation/runtime/helpers';
3-
import { getDataFetchInfo } from '../../runtime/utils';
2+
import {
3+
getDataFetchInfo,
4+
initDataFetchMap,
5+
getDataFetchItem,
6+
getDataFetchMap,
7+
isCSROnly,
8+
isSSRDowngrade,
9+
} from '../../runtime/utils';
410
import logger from '../../runtime/logger';
511
import { getDataFetchMapKey } from '../../runtime/dataFetch';
12+
import type { MF_DATA_FETCH_MAP_VALUE } from '../../interfaces/global';
613

714
const autoFetchData: () => FederationRuntimePlugin = () => ({
815
name: 'auto-fetch-data-plugin',
16+
beforeInit(args) {
17+
initDataFetchMap();
18+
return args;
19+
},
920
afterLoadSnapshot(args) {
10-
if (typeof window !== 'undefined') {
11-
return args;
12-
}
21+
// if (typeof window !== 'undefined' && !(isCSROnly() || isSSRDowngrade() )) {
22+
// if(!globalThis._MF__DATA_FETCH_ID_MAP__['_mfSSRDowngrade']){
23+
// return args;
24+
// }
25+
// }
1326

1427
const { id, moduleInfo, remoteSnapshot, host } = args;
1528
if (typeof id === 'string' && id.includes('data')) {
@@ -30,12 +43,20 @@ const autoFetchData: () => FederationRuntimePlugin = () => ({
3043
}
3144
const { dataFetchId, dataFetchName } = dataFetchInfo;
3245

46+
if (
47+
!remoteSnapshot.modules.find(
48+
(module) => module.moduleName === dataFetchName,
49+
)
50+
) {
51+
return args;
52+
}
53+
3354
const { modules, version } = remoteSnapshot;
3455

35-
const dataFetchMapKey = getDataFetchMapKey(
36-
{ name, version },
37-
dataFetchInfo,
38-
);
56+
const dataFetchMapKey = getDataFetchMapKey(dataFetchInfo, {
57+
name: host.name,
58+
version: host.options.version,
59+
});
3960
logger.debug(
4061
'======= auto fetch plugin dataFetchMapKey: ',
4162
dataFetchMapKey,
@@ -45,11 +66,8 @@ const autoFetchData: () => FederationRuntimePlugin = () => ({
4566
return args;
4667
}
4768

48-
if (
49-
helpers.global.nativeGlobal.__FEDERATION__.__DATA_FETCH_MAP__[
50-
dataFetchMapKey
51-
]
52-
) {
69+
const dataFetchItem = getDataFetchItem(dataFetchMapKey);
70+
if (dataFetchItem) {
5371
return args;
5472
}
5573

@@ -62,9 +80,10 @@ const autoFetchData: () => FederationRuntimePlugin = () => ({
6280
return args;
6381
}
6482

65-
const fetchData = host
66-
.loadRemote(dataFetchId)
67-
.then((m) => {
83+
const dataFetchMap = getDataFetchMap();
84+
85+
const getDataFetchGetter = () =>
86+
host.loadRemote(dataFetchId).then((m) => {
6887
if (
6988
m &&
7089
typeof m === 'object' &&
@@ -73,16 +92,23 @@ const autoFetchData: () => FederationRuntimePlugin = () => ({
7392
) {
7493
return m.fetchData as () => Promise<unknown>;
7594
}
76-
})
77-
.catch((e) => {
78-
console.log('======= auto fetch plugin fetchData error', e);
79-
return undefined;
95+
throw new Error(
96+
`fetchData not found in remote ${dataFetchId}, ${JSON.stringify(m)}`,
97+
);
8098
});
99+
// .catch((e) => {
100+
// console.log('======= auto fetch plugin fetchData error', e);
101+
// return ()=>`${e}`;
102+
// });
81103

82-
helpers.global.nativeGlobal.__FEDERATION__.__DATA_FETCH_MAP__.set(
83-
dataFetchMapKey,
84-
fetchData,
85-
);
104+
const dataFetchFnItem: MF_DATA_FETCH_MAP_VALUE[0] = [getDataFetchGetter];
105+
106+
// server client must execute
107+
if (typeof window === 'undefined' || isCSROnly()) {
108+
dataFetchFnItem.push(getDataFetchGetter());
109+
}
110+
111+
dataFetchMap.set(dataFetchMapKey, [dataFetchFnItem]);
86112

87113
return args;
88114
},

packages/modernjs/src/cli/server/data-fetch-server-plugin.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { DATA_FETCH_QUERY } from '../../constant';
2+
import logger from '../../runtime/logger';
13
import type { ServerPluginLegacy } from '@modern-js/server-core';
24

35
export default (): ServerPluginLegacy => ({
@@ -16,8 +18,32 @@ export default (): ServerPluginLegacy => ({
1618
config.render!.middleware!.push(
1719
async (ctx: { request: any }, next: () => any) => {
1820
const { request } = ctx;
19-
console.log('request.url: ', request.url);
20-
return next();
21+
try {
22+
const url = new URL(request.url);
23+
const dataFetchId = url.searchParams.get(DATA_FETCH_QUERY);
24+
if (!dataFetchId) {
25+
return next();
26+
}
27+
logger.debug('dataFetchId: ', dataFetchId);
28+
29+
const fetchDataPromise =
30+
globalThis.nativeGlobal.__FEDERATION__.__DATA_FETCH_MAP__.get(
31+
dataFetchId,
32+
);
33+
if (!fetchDataPromise) {
34+
return next();
35+
}
36+
37+
const fetchDataFn = await fetchDataPromise;
38+
if (!fetchDataFn) {
39+
return next();
40+
}
41+
return fetchDataFn();
42+
} catch (e) {
43+
console.log('data fetch error:');
44+
console.error(e);
45+
return next();
46+
}
2147
},
2248
);
2349
return config;

packages/modernjs/src/constant.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
11
export const LOCALHOST = 'localhost';
22
export const PLUGIN_IDENTIFIER = '[ Modern.js Module Federation ]';
3+
export const DATA_FETCH_QUERY = 'x-mf-data-fetch';
4+
export const DATA_FETCH_ERROR_PREFIX =
5+
'caught the following error during dataFetch: ';
6+
export const LOAD_REMOTE_ERROR_PREFIX =
7+
'caught the following error during loadRemote: ';
8+
export const DOWNGRADE_KEY = '_mfSSRDowngrade';
9+
10+
export const ERROR_TYPE = {
11+
DATA_FETCH: 1,
12+
LOAD_REMOTE: 2,
13+
UNKNOWN: 3,
14+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export type MF_DATA_FETCH_MAP_VALUE = [
2+
// getDataFetchGetter , getDataFetchPromise
3+
[() => Promise<() => Promise<unknown>>, Promise<() => Promise<unknown>>?],
4+
[Promise<unknown>, ((data: unknown) => void)?, ((err: unknown) => void)?]?,
5+
1?,
6+
];
7+
export type MF_DATA_FETCH_MAP = Map<string, MF_DATA_FETCH_MAP_VALUE>;
8+
export type MF_SSR_DOWNGRADE = string[] | true | undefined;

packages/modernjs/src/runtime/Await.tsx

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
import React, { MutableRefObject, ReactNode, Suspense, useRef } from 'react';
2+
import logger from './logger';
3+
import {
4+
DATA_FETCH_ERROR_PREFIX,
5+
LOAD_REMOTE_ERROR_PREFIX,
6+
ERROR_TYPE,
7+
} from '../constant';
28

39
function isPromise<T>(obj: any): obj is PromiseLike<T> {
410
return (
@@ -7,16 +13,39 @@ function isPromise<T>(obj: any): obj is PromiseLike<T> {
713
typeof obj.then === 'function'
814
);
915
}
10-
export const AWAIT_ERROR_PREFIX =
16+
const AWAIT_ERROR_PREFIX =
1117
'<Await /> caught the following error during render: ';
1218

13-
export const IsAwaitErrorText = (text: string) =>
14-
typeof text === 'string' && text.indexOf(AWAIT_ERROR_PREFIX) === 0;
19+
export type ErrorInfo = {
20+
err: Error;
21+
errorType: number;
22+
};
23+
24+
const transformError = (errMsg: string): ErrorInfo => {
25+
const originalMsg = errMsg.replace(AWAIT_ERROR_PREFIX, '');
26+
if (originalMsg.indexOf(DATA_FETCH_ERROR_PREFIX) === 0) {
27+
return {
28+
err: new Error(originalMsg.replace(DATA_FETCH_ERROR_PREFIX, '')),
29+
errorType: ERROR_TYPE.DATA_FETCH,
30+
};
31+
}
32+
if (originalMsg.indexOf(LOAD_REMOTE_ERROR_PREFIX) === 0) {
33+
return {
34+
err: new Error(originalMsg.replace(LOAD_REMOTE_ERROR_PREFIX, '')),
35+
errorType: ERROR_TYPE.LOAD_REMOTE,
36+
};
37+
}
38+
39+
return {
40+
err: new Error(originalMsg),
41+
errorType: ERROR_TYPE.UNKNOWN,
42+
};
43+
};
1544

1645
export interface AwaitProps<T> {
1746
resolve: T | Promise<T>;
1847
loading?: ReactNode;
19-
errorElement?: ReactNode | ((data?: string) => ReactNode);
48+
errorElement?: ReactNode | ((errorInfo: ErrorInfo) => ReactNode);
2049
children: (data: T) => ReactNode;
2150
}
2251

@@ -57,7 +86,7 @@ function AwaitSuspense<T>({
5786
errorElement = DefaultErrorElement,
5887
}: AwaitErrorHandlerProps<T>) {
5988
return (
60-
<Suspense fallback={loading}>
89+
<Suspense>
6190
<ResolveAwait
6291
resolve={resolve}
6392
loading={loading}
@@ -76,10 +105,27 @@ function ResolveAwait<T>({
76105
errorElement,
77106
}: AwaitErrorHandlerProps<T>) {
78107
const data = resolve();
108+
logger.debug('resolve data: ', data);
79109
if (typeof data === 'string' && data.indexOf(AWAIT_ERROR_PREFIX) === 0) {
80110
return (
81111
<>
82-
{typeof errorElement === 'function' ? errorElement(data) : errorElement}
112+
{typeof errorElement === 'function' ? (
113+
<>
114+
{/* TODO: set _mfSSRDowngrade */}
115+
<script
116+
suppressHydrationWarning
117+
dangerouslySetInnerHTML={{
118+
__html: String.raw`
119+
globalThis._MF__DATA_FETCH_ID_MAP__ = globalThis._MF__DATA_FETCH_ID_MAP__ || {};
120+
globalThis._MF__DATA_FETCH_ID_MAP__['_mfSSRDowngrade'] = true;
121+
`,
122+
}}
123+
></script>
124+
{errorElement(transformError(data))}
125+
</>
126+
) : (
127+
errorElement
128+
)}
83129
</>
84130
);
85131
}

0 commit comments

Comments
 (0)