Skip to content

Commit d018704

Browse files
ScriptedAlchemyzhangHongEn张洪恩
authored
feat: support node esmodule and mf-manifest esmodule (#2934) (#3013)
Co-authored-by: zhn <[email protected]> Co-authored-by: 张洪恩 <[email protected]>
1 parent 0a1b880 commit d018704

File tree

8 files changed

+291
-498
lines changed

8 files changed

+291
-498
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
- name: Install deps
4848
run: pnpm install
4949

50-
- name: Build and test Packages
50+
- name: Build Packages
5151
run: pnpm run build:pkg
5252

5353
- name: Release

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"nx": "nx",
2323
"commit": "cz",
2424
"docs": "typedoc",
25+
"f": "nx format:write",
2526
"lint": "nx run-many --target=lint",
2627
"test": "nx run-many --target=test",
2728
"build": "nx run-many --target=build --parallel=5 --projects=tag:type:pkg",

packages/runtime/src/plugins/generate-preload-assets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ export const generatePreloadAssetsPlugin: () => FederationRuntimePlugin =
328328
moduleInfo: {
329329
name: remoteInfo.name,
330330
entry: remote.entry,
331-
type: 'global',
331+
type: remoteInfo.type || 'global',
332332
entryGlobalName: '',
333333
shareScope: '',
334334
},

packages/runtime/src/utils/load.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ async function loadEntryNode({
147147
remoteInfo: RemoteInfo;
148148
createScriptHook: FederationHost['loaderHook']['lifecycle']['createScript'];
149149
}) {
150-
const { entry, entryGlobalName: globalName, name } = remoteInfo;
150+
const { entry, entryGlobalName: globalName, name, type } = remoteInfo;
151151
const { entryExports: remoteEntryExports } = getRemoteEntryExports(
152152
name,
153153
globalName,
@@ -158,7 +158,7 @@ async function loadEntryNode({
158158
}
159159

160160
return loadScriptNode(entry, {
161-
attrs: { name, globalName },
161+
attrs: { name, globalName, type },
162162
createScriptHook: (url, attrs) => {
163163
const res = createScriptHook.emit({ url, attrs });
164164

packages/sdk/src/dom.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,9 @@ export function createScript(info: {
4747
}
4848

4949
if (!script) {
50+
const attrs = info.attrs;
5051
script = document.createElement('script');
51-
script.type = 'text/javascript';
52+
script.type = attrs?.['type'] === 'module' ? 'module' : 'text/javascript';
5253
script.src = info.url;
5354
let createScriptRes: CreateScriptHookReturnDom = undefined;
5455
if (info.createScriptHook) {
@@ -65,7 +66,6 @@ export function createScript(info: {
6566
}
6667
}
6768
}
68-
const attrs = info.attrs;
6969
if (attrs && !createScriptRes) {
7070
Object.keys(attrs).forEach((name) => {
7171
if (script) {

packages/sdk/src/generateSnapshotFromManifest.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,8 @@ export function generateSnapshotFromManifest(
190190
ssrRemoteEntry.name,
191191
);
192192
remoteSnapshot.ssrRemoteEntry = fullSSRRemoteEntry;
193-
remoteSnapshot.ssrRemoteEntryType = 'commonjs-module';
193+
remoteSnapshot.ssrRemoteEntryType =
194+
ssrRemoteEntry.type || 'commonjs-module';
194195
}
195196

196197
return remoteSnapshot;

packages/sdk/src/node.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,26 @@ export function createScriptNode(
133133
};
134134

135135
getFetch()
136-
.then((f) => handleScriptFetch(f, urlObj))
136+
.then(async (f) => {
137+
if (attrs?.['type'] === 'esm' || attrs?.['type'] === 'module') {
138+
return loadModule(urlObj.href, {
139+
fetch: f,
140+
vm: await importNodeModule<typeof import('vm')>('vm'),
141+
})
142+
.then(async (module) => {
143+
await module.evaluate();
144+
cb(undefined, module.namespace);
145+
})
146+
.catch((e) => {
147+
cb(
148+
e instanceof Error
149+
? e
150+
: new Error(`Script execution error: ${e}`),
151+
);
152+
});
153+
}
154+
handleScriptFetch(f, urlObj);
155+
})
137156
.catch((err) => {
138157
cb(err);
139158
});
@@ -166,3 +185,31 @@ export function loadScriptNode(
166185
);
167186
});
168187
}
188+
189+
async function loadModule(
190+
url: string,
191+
options: {
192+
vm: any;
193+
fetch: any;
194+
},
195+
) {
196+
const { fetch, vm } = options;
197+
const response = await fetch(url);
198+
const code = await response.text();
199+
200+
const module: any = new vm.SourceTextModule(code, {
201+
// @ts-ignore
202+
importModuleDynamically: async (specifier, script) => {
203+
const resolvedUrl = new URL(specifier, url).href;
204+
return loadModule(resolvedUrl, options);
205+
},
206+
});
207+
208+
await module.link(async (specifier: string) => {
209+
const resolvedUrl = new URL(specifier, url).href;
210+
const module = await loadModule(resolvedUrl, options);
211+
return module;
212+
});
213+
214+
return module;
215+
}

0 commit comments

Comments
 (0)