diff --git a/src/index.ts b/src/index.ts index 8e20ab9..7812b72 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,7 +25,7 @@ import { VIRTUAL_EXPOSES } from './virtualModules/virtualExposes'; function federation(mfUserOptions: ModuleFederationOptions): Plugin[] { const options = normalizeModuleFederationOptions(mfUserOptions); - const { name, remotes, shared, filename } = options; + const { name, remotes, shared, filename, remotePlugin } = options; if (!name) throw new Error('name is required'); return [ @@ -47,11 +47,13 @@ function federation(mfUserOptions: ModuleFederationOptions): Plugin[] { entryPath: REMOTE_ENTRY_ID, fileName: filename, }), - ...addEntry({ - entryName: 'hostInit', - entryPath: getHostAutoInitPath(), - inject: 'html', - }), + ...(remotePlugin + ? [] + : addEntry({ + entryName: 'hostInit', + entryPath: getHostAutoInitPath(), + inject: 'html', + })), ...addEntry({ entryName: 'virtualExposes', entryPath: VIRTUAL_EXPOSES, diff --git a/src/plugins/pluginProxySharedModule_preBuild.ts b/src/plugins/pluginProxySharedModule_preBuild.ts index bfac5b3..9534b67 100644 --- a/src/plugins/pluginProxySharedModule_preBuild.ts +++ b/src/plugins/pluginProxySharedModule_preBuild.ts @@ -1,5 +1,8 @@ import { Plugin, UserConfig } from 'vite'; -import { NormalizedShared } from '../utils/normalizeModuleFederationOptions'; +import { + NormalizedShared, + getNormalizeModuleFederationOptions, +} from '../utils/normalizeModuleFederationOptions'; import { PromiseStore } from '../utils/PromiseStore'; import VirtualModule from '../utils/VirtualModule'; import { diff --git a/src/utils/normalizeModuleFederationOptions.ts b/src/utils/normalizeModuleFederationOptions.ts index 929da7a..223feef 100644 --- a/src/utils/normalizeModuleFederationOptions.ts +++ b/src/utils/normalizeModuleFederationOptions.ts @@ -273,6 +273,10 @@ export type ModuleFederationOptions = { filename?: string; library?: any; name: string; + /** + * When true, prevents shared modules from being bundled into remotes + * and makes them rely on host-provided shared modules at runtime + */ // remoteType?: string; remotes?: Record | undefined; runtime?: any; @@ -301,6 +305,11 @@ export type ModuleFederationOptions = { shareStrategy?: ShareStrategy; ignoreOrigin?: boolean; virtualModuleDir?: string; + /** + * When true, prevents shared modules from being bundled into remotes + * and makes them rely on host-provided shared modules at runtime + */ + remotePlugin?: boolean; }; export interface NormalizedModuleFederationOptions { @@ -308,6 +317,11 @@ export interface NormalizedModuleFederationOptions { filename: string; library: any; name: string; + /** + * When true, prevents shared modules from being bundled into remotes + * and makes them rely on host-provided shared modules at runtime + */ + remotePlugin: boolean; // remoteType: string; remotes: Record; runtime: any; @@ -393,6 +407,7 @@ export function normalizeModuleFederationOptions( return (config = { exposes: normalizeExposes(options.exposes), filename: options.filename || 'remoteEntry-[hash]', + remotePlugin: options.remotePlugin ?? false, library: normalizeLibrary(options.library), name: options.name, // remoteType: options.remoteType, diff --git a/src/virtualModules/virtualRemoteEntry.ts b/src/virtualModules/virtualRemoteEntry.ts index ececa6f..b295dbe 100644 --- a/src/virtualModules/virtualRemoteEntry.ts +++ b/src/virtualModules/virtualRemoteEntry.ts @@ -37,25 +37,33 @@ export function writeLocalSharedImportMap() { } export function generateLocalSharedImportMap() { const options = getNormalizeModuleFederationOptions(); + return ` const importMap = { - ${Array.from(getUsedShares()) - .map( - (pkg) => ` + ${ + options.remotePlugin + ? '' + : Array.from(getUsedShares()) + .map( + (pkg) => ` ${JSON.stringify(pkg)}: async () => { let pkg = await import("${getPreBuildLibImportId(pkg)}") return pkg } ` - ) - .join(',')} + ) + .join(',') + } } const usedShared = { - ${Array.from(getUsedShares()) - .map((key) => { - const shareItem = getNormalizeShareItem(key); - if (!shareItem) return null; - return ` + ${ + options.remotePlugin + ? '' + : Array.from(getUsedShares()) + .map((key) => { + const shareItem = getNormalizeShareItem(key); + if (!shareItem) return null; + return ` ${JSON.stringify(key)}: { name: ${JSON.stringify(key)}, version: ${JSON.stringify(shareItem.version)}, @@ -64,7 +72,7 @@ export function generateLocalSharedImportMap() { from: ${JSON.stringify(options.name)}, async get () { usedShared[${JSON.stringify(key)}].loaded = true - const {${JSON.stringify(key)}: pkgDynamicImport} = importMap + const {${JSON.stringify(key)}: pkgDynamicImport} = importMap const res = await pkgDynamicImport() const exportModule = {...res} // All npm packages pre-built by vite will be converted to esm @@ -82,9 +90,10 @@ export function generateLocalSharedImportMap() { } } `; - }) - .filter((x) => x !== null) - .join(',')} + }) + .filter((x) => x !== null) + .join(',') + } } const usedRemotes = [${Object.keys(getUsedRemotesMap()) .map((key) => { @@ -176,7 +185,7 @@ const hostAutoInitModule = new VirtualModule('hostAutoInit', HOST_AUTO_INIT_TAG) export function writeHostAutoInit() { hostAutoInitModule.writeSync(` const remoteEntryPromise = import("${REMOTE_ENTRY_ID}") - // __tla only serves as a hack for vite-plugin-top-level-await. + // __tla only serves as a hack for vite-plugin-top-level-await. Promise.resolve(remoteEntryPromise) .then(remoteEntry => { return Promise.resolve(remoteEntry.__tla) diff --git a/src/virtualModules/virtualShared_preBuild.ts b/src/virtualModules/virtualShared_preBuild.ts index 6e3de94..95a1a30 100644 --- a/src/virtualModules/virtualShared_preBuild.ts +++ b/src/virtualModules/virtualShared_preBuild.ts @@ -38,7 +38,7 @@ export function getLoadShareModulePath(pkg: string): string { } export function writeLoadShareModule(pkg: string, shareItem: ShareItem, command: string) { loadShareCacheMap[pkg].writeSync(` - + ;() => import(${JSON.stringify(getPreBuildLibImportId(pkg))}).catch(() => {}); // dev uses dynamic import to separate chunks ${command !== 'build' ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ''}