Skip to content

Commit

Permalink
feat: support node esmodule and mf-manifest esmodule (#2934)
Browse files Browse the repository at this point in the history
Co-authored-by: 张洪恩 <zhanghongen@bwcj.com>
Co-authored-by: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 28, 2024
1 parent 0216364 commit c529a72
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"nx": "nx",
"commit": "cz",
"docs": "typedoc",
"f": "nx format:write",
"lint": "nx run-many --target=lint",
"test": "nx run-many --target=test",
"build": "nx run-many --target=build --parallel=5 --projects=tag:type:pkg",
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/plugins/generate-preload-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ export const generatePreloadAssetsPlugin: () => FederationRuntimePlugin =
moduleInfo: {
name: remoteInfo.name,
entry: remote.entry,
type: 'global',
type: remoteInfo.type || 'global',
entryGlobalName: '',
shareScope: '',
},
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/src/utils/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ async function loadEntryNode({
remoteInfo: RemoteInfo;
createScriptHook: FederationHost['loaderHook']['lifecycle']['createScript'];
}) {
const { entry, entryGlobalName: globalName, name } = remoteInfo;
const { entry, entryGlobalName: globalName, name, type } = remoteInfo;
const { entryExports: remoteEntryExports } = getRemoteEntryExports(
name,
globalName,
Expand All @@ -158,7 +158,7 @@ async function loadEntryNode({
}

return loadScriptNode(entry, {
attrs: { name, globalName },
attrs: { name, globalName, type },
createScriptHook: (url, attrs) => {
const res = createScriptHook.emit({ url, attrs });

Expand Down
4 changes: 2 additions & 2 deletions packages/sdk/src/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ export function createScript(info: {
}

if (!script) {
const attrs = info.attrs;
script = document.createElement('script');
script.type = 'text/javascript';
script.type = attrs?.['type'] === 'module' ? 'module' : 'text/javascript';
script.src = info.url;
let createScriptRes: CreateScriptHookReturnDom = undefined;
if (info.createScriptHook) {
Expand All @@ -65,7 +66,6 @@ export function createScript(info: {
}
}
}
const attrs = info.attrs;
if (attrs && !createScriptRes) {
Object.keys(attrs).forEach((name) => {
if (script) {
Expand Down
3 changes: 2 additions & 1 deletion packages/sdk/src/generateSnapshotFromManifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ export function generateSnapshotFromManifest(
ssrRemoteEntry.name,
);
remoteSnapshot.ssrRemoteEntry = fullSSRRemoteEntry;
remoteSnapshot.ssrRemoteEntryType = 'commonjs-module';
remoteSnapshot.ssrRemoteEntryType =
ssrRemoteEntry.type || 'commonjs-module';
}

return remoteSnapshot;
Expand Down
49 changes: 48 additions & 1 deletion packages/sdk/src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,26 @@ export function createScriptNode(
};

getFetch()
.then((f) => handleScriptFetch(f, urlObj))
.then(async (f) => {
if (attrs?.['type'] === 'esm' || attrs?.['type'] === 'module') {
return loadModule(urlObj.href, {
fetch: f,
vm: await importNodeModule<typeof import('vm')>('vm'),
})
.then(async (module) => {
await module.evaluate();
cb(undefined, module.namespace);
})
.catch((e) => {
cb(
e instanceof Error
? e
: new Error(`Script execution error: ${e}`),
);
});
}
handleScriptFetch(f, urlObj);
})
.catch((err) => {
cb(err);
});
Expand Down Expand Up @@ -165,3 +184,31 @@ export function loadScriptNode(
);
});
}

async function loadModule(
url: string,
options: {
vm: any;
fetch: any;
}
) {
const { fetch, vm } = options;
const response = await fetch(url);
const code = await response.text();

const module: any = new vm.SourceTextModule(code, {
// @ts-ignore
importModuleDynamically: async (specifier, script) => {
const resolvedUrl = new URL(specifier, url).href;
return loadModule(resolvedUrl, options);
},
});

await module.link(async (specifier: string) => {
const resolvedUrl = new URL(specifier, url).href;
const module = await loadModule(resolvedUrl, options);
return module;
});

return module;
}

0 comments on commit c529a72

Please sign in to comment.