Skip to content

Commit d1dd548

Browse files
committed
chore(react): export createRemoteComponent and related react utils
1 parent a40d744 commit d1dd548

36 files changed

+1298
-693
lines changed

.changeset/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
"@module-federation/inject-external-runtime-core-plugin",
2828
"@module-federation/runtime-core",
2929
"create-module-federation",
30-
"@module-federation/cli"
30+
"@module-federation/cli",
31+
"@module-federation/react"
3132
]
3233
],
3334
"ignorePatterns": ["^alpha|^beta"],

.changeset/spicy-parents-greet.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@module-federation/react': patch
3+
'@module-federation/modern-js': patch
4+
---
5+
6+
chore(react): export createRemoteComponent and related react utils

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createModuleFederationConfig } from '@module-federation/modern-js';
1+
import { createModuleFederationConfig } from '@module-federation/rsbuild-plugin';
22

33
export default createModuleFederationConfig({
44
name: 'provider_csr',

packages/modernjs/package.json

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@
5555
"import": "./dist/esm/cli/mfRuntimePlugins/resolve-entry-ipv4.js",
5656
"require": "./dist/esm/cli/mfRuntimePlugins/resolve-entry-ipv4.js"
5757
},
58-
"./auto-fetch-data": {
59-
"types": "./dist/types/cli/mfRuntimePlugins/auto-fetch-data.d.ts",
60-
"import": "./dist/esm/cli/mfRuntimePlugins/auto-fetch-data.js",
61-
"require": "./dist/esm/cli/mfRuntimePlugins/auto-fetch-data.js"
62-
},
6358
"./inject-node-fetch": {
6459
"types": "./dist/types/cli/mfRuntimePlugins/inject-node-fetch.d.ts",
6560
"import": "./dist/esm/cli/mfRuntimePlugins/inject-node-fetch.js",
@@ -94,9 +89,6 @@
9489
"resolve-entry-ipv4": [
9590
"./dist/types/cli/mfRuntimePlugins/resolve-entry-ipv4.d.ts"
9691
],
97-
"auto-fetch-data": [
98-
"./dist/types/cli/mfRuntimePlugins/auto-fetch-data.d.ts"
99-
],
10092
"inject-node-fetch": [
10193
"./dist/types/cli/mfRuntimePlugins/inject-node-fetch.d.ts"
10294
],
@@ -119,6 +111,7 @@
119111
"@modern-js/utils": "2.67.5",
120112
"@modern-js/node-bundle-require": "2.67.6",
121113
"@module-federation/rsbuild-plugin": "workspace:*",
114+
"@module-federation/react": "workspace:*",
122115
"fs-extra": "11.3.0",
123116
"lru-cache": "10.4.3",
124117
"@module-federation/enhanced": "workspace:*",

packages/modernjs/src/cli/configPlugin.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ describe('patchMFConfig', async () => {
3434
remoteType: 'script',
3535
runtimePlugins: [
3636
require.resolve('@module-federation/modern-js/shared-strategy'),
37-
require.resolve('@module-federation/modern-js/auto-fetch-data'),
37+
require.resolve('@module-federation/react/data-fetch-runtime-plugin'),
3838
require.resolve('@module-federation/node/runtimePlugin'),
3939
require.resolve('@module-federation/modern-js/inject-node-fetch'),
4040
],
@@ -65,7 +65,7 @@ describe('patchMFConfig', async () => {
6565
remoteType: 'script',
6666
runtimePlugins: [
6767
require.resolve('@module-federation/modern-js/shared-strategy'),
68-
require.resolve('@module-federation/modern-js/auto-fetch-data'),
68+
require.resolve('@module-federation/react/data-fetch-runtime-plugin'),
6969
],
7070
shared: {
7171
react: {

packages/modernjs/src/cli/configPlugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export const patchMFConfig = (
170170
);
171171

172172
injectRuntimePlugins(
173-
require.resolve('@module-federation/modern-js/auto-fetch-data'),
173+
require.resolve('@module-federation/react/data-fetch-runtime-plugin'),
174174
runtimePlugins,
175175
);
176176

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

Lines changed: 3 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -1,194 +1,6 @@
1-
import { DATA_FETCH_QUERY, MF_DATA_FETCH_STATUS } from '../../constant';
2-
import logger from '../../logger';
3-
import { getDataFetchMap } from '../../utils';
4-
import {
5-
fetchData,
6-
initDataFetchMap,
7-
loadDataFetchModule,
8-
} from '../../utils/dataFetch';
9-
import { SEPARATOR, MANIFEST_EXT } from '@module-federation/sdk';
10-
import type {
11-
MiddlewareHandler,
12-
ServerPlugin,
13-
} from '@modern-js/server-runtime';
14-
import type { NoSSRRemoteInfo } from '../../interfaces/global';
1+
import dataFetchMiddleWare from '@module-federation/react/data-fetch-server-middleware';
152

16-
function wrapSetTimeout(
17-
targetPromise: Promise<unknown>,
18-
delay = 20000,
19-
id: string,
20-
) {
21-
if (targetPromise && typeof targetPromise.then === 'function') {
22-
return new Promise((resolve, reject) => {
23-
const timeoutId = setTimeout(() => {
24-
logger.warn(`Data fetch for ID ${id} timed out after 20 seconds.`);
25-
reject(new Error(`Data fetch for ID ${id} timed out after 20 seconds`));
26-
}, delay);
27-
28-
targetPromise
29-
.then((value: any) => {
30-
clearTimeout(timeoutId);
31-
resolve(value);
32-
})
33-
.catch((err: any) => {
34-
clearTimeout(timeoutId);
35-
reject(err);
36-
});
37-
});
38-
}
39-
}
40-
41-
function addProtocol(url: string) {
42-
if (url.startsWith('//')) {
43-
return 'https:' + url;
44-
}
45-
return url;
46-
}
47-
48-
const getDecodeQuery = (url: URL, name: string) => {
49-
const res = url.searchParams.get(name);
50-
if (!res) {
51-
return null;
52-
}
53-
return decodeURIComponent(res);
54-
};
55-
56-
const middleware: MiddlewareHandler = async (ctx, next) => {
57-
let url: URL;
58-
let dataFetchId: string | null;
59-
let params: Record<string, unknown>;
60-
let remoteInfo: NoSSRRemoteInfo;
61-
try {
62-
url = new URL(ctx.req.url);
63-
dataFetchId = getDecodeQuery(url, DATA_FETCH_QUERY);
64-
params = JSON.parse(getDecodeQuery(url, 'params') || '{}');
65-
const remoteInfoQuery = getDecodeQuery(url, 'remoteInfo');
66-
remoteInfo = remoteInfoQuery ? JSON.parse(remoteInfoQuery) : null;
67-
} catch (e) {
68-
logger.error('fetch data from server, error: ', e);
69-
return next();
70-
}
71-
72-
if (!dataFetchId) {
73-
return next();
74-
}
75-
logger.log('fetch data from server, dataFetchId: ', dataFetchId);
76-
logger.debug(
77-
'fetch data from server, moduleInfo: ',
78-
globalThis.__FEDERATION__?.moduleInfo,
79-
);
80-
try {
81-
const dataFetchMap = getDataFetchMap();
82-
if (!dataFetchMap) {
83-
initDataFetchMap();
84-
}
85-
const fetchDataPromise = dataFetchMap[dataFetchId]?.[1];
86-
logger.debug(
87-
'fetch data from server, fetchDataPromise: ',
88-
fetchDataPromise,
89-
);
90-
if (
91-
fetchDataPromise &&
92-
dataFetchMap[dataFetchId]?.[2] !== MF_DATA_FETCH_STATUS.ERROR
93-
) {
94-
const targetPromise = fetchDataPromise[0];
95-
// Ensure targetPromise is thenable
96-
const wrappedPromise = wrapSetTimeout(targetPromise, 20000, dataFetchId);
97-
if (wrappedPromise) {
98-
const res = await wrappedPromise;
99-
logger.log('fetch data from server, fetchDataPromise res: ', res);
100-
return ctx.json(res);
101-
}
102-
logger.error(
103-
`Expected a Promise from fetchDataPromise[0] for dataFetchId ${dataFetchId}, but received:`,
104-
targetPromise,
105-
'Will try call new dataFetch again...',
106-
);
107-
}
108-
109-
if (remoteInfo) {
110-
try {
111-
const hostInstance = globalThis.__FEDERATION__.__INSTANCES__[0];
112-
const remoteEntry = `${addProtocol(remoteInfo.ssrPublicPath) + remoteInfo.ssrRemoteEntry}`;
113-
if (!hostInstance) {
114-
throw new Error('host instance not found!');
115-
}
116-
const remote = hostInstance.options.remotes.find(
117-
(remote) => remote.name === remoteInfo.name,
118-
);
119-
logger.debug('find remote: ', JSON.stringify(remote));
120-
if (!remote) {
121-
hostInstance.registerRemotes([
122-
{
123-
name: remoteInfo.name,
124-
entry: remoteEntry,
125-
entryGlobalName: remoteInfo.globalName,
126-
},
127-
]);
128-
} else if (
129-
!('entry' in remote) ||
130-
!remote.entry.includes(MANIFEST_EXT)
131-
) {
132-
const { hostGlobalSnapshot, remoteSnapshot } =
133-
hostInstance.snapshotHandler.getGlobalRemoteInfo(remoteInfo);
134-
logger.debug(
135-
'find hostGlobalSnapshot: ',
136-
JSON.stringify(hostGlobalSnapshot),
137-
);
138-
logger.debug('find remoteSnapshot: ', JSON.stringify(remoteSnapshot));
139-
140-
if (!hostGlobalSnapshot || !remoteSnapshot) {
141-
if ('version' in remote) {
142-
// @ts-ignore
143-
delete remote.version;
144-
}
145-
// @ts-ignore
146-
remote.entry = remoteEntry;
147-
remote.entryGlobalName = remoteInfo.globalName;
148-
}
149-
}
150-
} catch (e) {
151-
ctx.status(500);
152-
return ctx.text(
153-
`failed to fetch ${remoteInfo.name} data, error:\n ${e}`,
154-
);
155-
}
156-
}
157-
158-
const dataFetchItem = dataFetchMap[dataFetchId];
159-
logger.debug('fetch data from server, dataFetchItem: ', dataFetchItem);
160-
if (dataFetchItem) {
161-
const callFetchDataPromise = fetchData(dataFetchId, {
162-
...params,
163-
isDowngrade: !remoteInfo,
164-
});
165-
const wrappedPromise = wrapSetTimeout(
166-
callFetchDataPromise,
167-
20000,
168-
dataFetchId,
169-
);
170-
if (wrappedPromise) {
171-
const res = await wrappedPromise;
172-
logger.log('fetch data from server, dataFetchItem res: ', res);
173-
return ctx.json(res);
174-
}
175-
}
176-
177-
const remoteId = dataFetchId.split(SEPARATOR)[0];
178-
const hostInstance = globalThis.__FEDERATION__.__INSTANCES__[0];
179-
if (!hostInstance) {
180-
throw new Error('host instance not found!');
181-
}
182-
const dataFetchFn = await loadDataFetchModule(hostInstance, remoteId);
183-
const data = await dataFetchFn({ ...params, isDowngrade: !remoteInfo });
184-
logger.log('fetch data from server, loadDataFetchModule res: ', data);
185-
return ctx.json(data);
186-
} catch (e) {
187-
logger.error('server plugin data fetch error: ', e);
188-
ctx.status(500);
189-
return ctx.text(`failed to fetch ${remoteInfo.name} data, error:\n ${e}`);
190-
}
191-
};
3+
import type { ServerPlugin } from '@modern-js/server-runtime';
1924

1935
const dataFetchServePlugin = (): ServerPlugin => ({
1946
name: 'mf-data-fetch-server-plugin',
@@ -198,7 +10,7 @@ const dataFetchServePlugin = (): ServerPlugin => ({
19810
middlewares.push({
19911
name: 'module-federation-serve-manifest',
20012
// @ts-ignore type error
201-
handler: middleware,
13+
handler: dataFetchMiddleWare,
20214
});
20315
});
20416
},

packages/modernjs/src/constant.ts

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,2 @@
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-
export const DATA_FETCH_MAP_KEY = '__MF_DATA_FETCH_MAP__';
10-
export const DATA_FETCH_FUNCTION = '_mfDataFetch';
11-
export const FS_HREF = '_mfFSHref';
12-
export const ERROR_TYPE = {
13-
DATA_FETCH: 1,
14-
LOAD_REMOTE: 2,
15-
UNKNOWN: 3,
16-
};
17-
export const WRAP_DATA_FETCH_ID_IDENTIFIER = 'wrap_dfip_identifier';
18-
export const enum MF_DATA_FETCH_TYPE {
19-
FETCH_SERVER = 1,
20-
FETCH_CLIENT = 2,
21-
}
22-
23-
export const enum MF_DATA_FETCH_STATUS {
24-
LOADED = 1,
25-
LOADING = 2,
26-
AWAIT = 0,
27-
ERROR = 3,
28-
}

packages/modernjs/src/interfaces/global.ts

Lines changed: 0 additions & 28 deletions
This file was deleted.

0 commit comments

Comments
 (0)