Skip to content

Commit 8ed7256

Browse files
authored
fix: Support empty entry JS in build mode. (#122)
* fix: Support empty entry JS in build mode. * demo: Support empty entry JS in build mode. * format: Support empty entry JS in build mode.
1 parent 0b62a3f commit 8ed7256

File tree

9 files changed

+59
-33
lines changed

9 files changed

+59
-33
lines changed

examples/rust-vite/rust-host/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"scripts": {
55
"dev": "rsbuild dev",
66
"build": "rsbuild build",
7-
"preview": "npm run build && rsbuild"
7+
"preview": "npm run build && rsbuild preview"
88
},
99
"dependencies": {
1010
"@module-federation/enhanced": "0.2.5",
Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +0,0 @@
1-
import React from 'react';
2-
import ReactDOM from 'react-dom/client';
3-
import App from './App';
4-
5-
//@ts-ignore
6-
const root = ReactDOM.createRoot(document.getElementById('app'));
7-
root.render(
8-
<React.StrictMode>
9-
<App />
10-
</React.StrictMode>
11-
);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"dev": "microbundle watch --no-sourcemap --compress=false",
1818
"build": "rimraf lib && microbundle --no-sourcemap --compress=false",
1919
"dev-rv": "pnpm -filter 'examples-rust-vite*' run dev",
20+
"preview-rv": "pnpm -filter 'examples-rust-vite*' run preview",
2021
"dev-vv": "pnpm -filter 'examples-vite-vite*' run dev",
2122
"dev-nv": "pnpm -filter 'examples-nuxt-vite-host' -filter 'examples-vite-vite-remote' run dev",
2223
"preview-vv": "pnpm -filter 'examples-vite-vite*' run preview",

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
initVirtualModules,
2020
REMOTE_ENTRY_ID,
2121
} from './virtualModules';
22+
import { VIRTUAL_EXPOSES } from './virtualModules/virtualExposes';
2223

2324
function federation(mfUserOptions: ModuleFederationOptions): Plugin[] {
2425
const options = normalizeModuleFederationOptions(mfUserOptions);
@@ -38,6 +39,10 @@ function federation(mfUserOptions: ModuleFederationOptions): Plugin[] {
3839
entryName: 'hostInit',
3940
entryPath: getHostAutoInitPath(),
4041
}),
42+
...addEntry({
43+
entryName: 'virtualExposes',
44+
entryPath: VIRTUAL_EXPOSES,
45+
}),
4146
pluginProxyRemoteEntry(),
4247
pluginProxyRemotes(options),
4348
...pluginModuleParseEnd((id: string) => {

src/plugins/pluginModuleParseEnd.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* This plugin allows me to wait until all modules are built, and then expose them together.
44
*/
55
import { Plugin } from 'vite';
6+
import { VIRTUAL_EXPOSES } from '../virtualModules';
67

78
let _resolve: any,
89
_reject: any,
@@ -11,6 +12,7 @@ let _resolve: any,
1112
_reject = reject;
1213
});
1314
let parsePromise = promise;
15+
let exposesParseEnd = false;
1416

1517
const parseStartSet = new Set();
1618
const parseEndSet = new Set();
@@ -44,8 +46,12 @@ export default function (excludeFn: Function): Plugin[] {
4446
if (excludeFn(id)) {
4547
return;
4648
}
49+
if (id === VIRTUAL_EXPOSES) {
50+
// When the entry JS file is empty and only contains exposes export code, it’s necessary to wait for the exposes modules to be resolved in order to collect the dependencies being used.
51+
exposesParseEnd = true;
52+
}
4753
parseEndSet.add(id);
48-
if (parseStartSet.size === parseEndSet.size) {
54+
if (exposesParseEnd && parseStartSet.size === parseEndSet.size) {
4955
_resolve(1);
5056
}
5157
},

src/plugins/pluginProxyRemoteEntry.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { createFilter } from '@rollup/pluginutils';
22
import { Plugin } from 'vite';
33
import { getNormalizeModuleFederationOptions } from '../utils/normalizeModuleFederationOptions';
4-
import { generateRemoteEntry, REMOTE_ENTRY_ID } from '../virtualModules';
4+
import {
5+
generateExposes,
6+
generateRemoteEntry,
7+
REMOTE_ENTRY_ID,
8+
VIRTUAL_EXPOSES,
9+
} from '../virtualModules';
510
import { parsePromise } from './pluginModuleParseEnd';
611

712
const filter: (id: string) => boolean = createFilter();
@@ -14,17 +19,26 @@ export default function (): Plugin {
1419
if (id === REMOTE_ENTRY_ID) {
1520
return REMOTE_ENTRY_ID;
1621
}
22+
if (id === VIRTUAL_EXPOSES) {
23+
return VIRTUAL_EXPOSES;
24+
}
1725
},
1826
load(id: string) {
1927
if (id === REMOTE_ENTRY_ID) {
2028
return parsePromise.then((_) => generateRemoteEntry(getNormalizeModuleFederationOptions()));
2129
}
30+
if (id === VIRTUAL_EXPOSES) {
31+
return generateExposes();
32+
}
2233
},
2334
async transform(code: string, id: string) {
2435
if (!filter(id)) return;
2536
if (id.includes(REMOTE_ENTRY_ID)) {
2637
return parsePromise.then((_) => generateRemoteEntry(getNormalizeModuleFederationOptions()));
2738
}
39+
if (id === VIRTUAL_EXPOSES) {
40+
return generateExposes();
41+
}
2842
},
2943
};
3044
}

src/virtualModules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export {
2929
writePreBuildLibPath,
3030
} from './virtualShared_preBuild';
3131

32+
export { generateExposes, VIRTUAL_EXPOSES } from './virtualExposes';
33+
3234
export { virtualRuntimeInitStatus } from './virtualRuntimeInitStatus';
3335

3436
export function initVirtualModules() {

src/virtualModules/virtualExposes.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { getNormalizeModuleFederationOptions } from '../utils/normalizeModuleFederationOptions';
2+
3+
export const VIRTUAL_EXPOSES = 'virtual:mf-exposes';
4+
export function generateExposes() {
5+
const options = getNormalizeModuleFederationOptions();
6+
return `
7+
export default {
8+
${Object.keys(options.exposes)
9+
.map((key) => {
10+
return `
11+
${JSON.stringify(key)}: async () => {
12+
const importModule = await import(${JSON.stringify(options.exposes[key].import)})
13+
const exportModule = {}
14+
Object.assign(exportModule, importModule)
15+
Object.defineProperty(exportModule, "__esModule", {
16+
value: true,
17+
enumerable: false
18+
})
19+
return exportModule
20+
}
21+
`;
22+
})
23+
.join(',')}
24+
}
25+
`;
26+
}

src/virtualModules/virtualRemoteEntry.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
NormalizedModuleFederationOptions,
99
} from '../utils/normalizeModuleFederationOptions';
1010
import VirtualModule from '../utils/VirtualModule';
11+
import { VIRTUAL_EXPOSES } from './virtualExposes';
1112
import { getUsedRemotesMap } from './virtualRemotes';
1213
import { virtualRuntimeInitStatus } from './virtualRuntimeInitStatus';
1314
import { getPreBuildLibImportId } from './virtualShared_preBuild';
@@ -114,25 +115,7 @@ export function generateRemoteEntry(options: NormalizedModuleFederationOptions):
114115
return `
115116
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
116117
${pluginImportNames.map((item) => item[1]).join('\n')}
117-
118-
const exposesMap = {
119-
${Object.keys(options.exposes)
120-
.map((key) => {
121-
return `
122-
${JSON.stringify(key)}: async () => {
123-
const importModule = await import(${JSON.stringify(options.exposes[key].import)})
124-
const exportModule = {}
125-
Object.assign(exportModule, importModule)
126-
Object.defineProperty(exportModule, "__esModule", {
127-
value: true,
128-
enumerable: false
129-
})
130-
return exportModule
131-
}
132-
`;
133-
})
134-
.join(',')}
135-
}
118+
import exposesMap from "${VIRTUAL_EXPOSES}"
136119
import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
137120
import {
138121
initResolve

0 commit comments

Comments
 (0)