diff --git a/.changeset/pink-rings-reply.md b/.changeset/pink-rings-reply.md new file mode 100644 index 00000000000..a4ee4317277 --- /dev/null +++ b/.changeset/pink-rings-reply.md @@ -0,0 +1,5 @@ +--- +'@module-federation/runtime-core': patch +--- + +fix(runtime): preload filter loaded resources diff --git a/packages/modernjs/src/cli/configPlugin.ts b/packages/modernjs/src/cli/configPlugin.ts index 5d99fa9941e..99dc5550d9c 100644 --- a/packages/modernjs/src/cli/configPlugin.ts +++ b/packages/modernjs/src/cli/configPlugin.ts @@ -7,6 +7,8 @@ import { getMFConfig, patchMFConfig, addMyTypes2Ignored, + isWebTarget, + skipByTarget, } from './utils'; export function setEnv(enableSSR: boolean) { @@ -34,21 +36,26 @@ export const moduleFederationConfigPlugin = ( const enableSSR = userConfig.userConfig?.ssr ?? Boolean(modernjsConfig?.server?.ssr); - api.modifyBundlerChain((chain, { isServer }) => { + api.modifyBundlerChain((chain) => { + const target = chain.get('target'); + if (skipByTarget(target)) { + return; + } + const isWeb = isWebTarget(target); // @ts-expect-error chain type is not correct - addMyTypes2Ignored(chain, isServer ? ssrConfig : csrConfig); + addMyTypes2Ignored(chain, !isWeb ? ssrConfig : csrConfig); - const targetMFConfig = isServer ? ssrConfig : csrConfig; + const targetMFConfig = !isWeb ? ssrConfig : csrConfig; patchMFConfig( targetMFConfig, - isServer, + !isWeb, userConfig.remoteIpStrategy || 'ipv4', ); patchBundlerConfig({ // @ts-expect-error chain type is not correct chain, - isServer, + isServer: !isWeb, modernjsConfig, mfConfig, enableSSR, @@ -107,3 +114,5 @@ export const moduleFederationConfigPlugin = ( }); export default moduleFederationConfigPlugin; + +export { isWebTarget, skipByTarget }; diff --git a/packages/modernjs/src/cli/ssrPlugin.ts b/packages/modernjs/src/cli/ssrPlugin.ts index 61cdbe0fd38..25587c4c60a 100644 --- a/packages/modernjs/src/cli/ssrPlugin.ts +++ b/packages/modernjs/src/cli/ssrPlugin.ts @@ -9,7 +9,7 @@ import { updateStatsAndManifest } from './manifest'; import { isDev } from './constant'; import { MODERN_JS_SERVER_DIR } from '../constant'; import logger from './logger'; -import { isWebTarget } from './utils'; +import { isWebTarget, skipByTarget } from './utils'; export function setEnv() { process.env['MF_DISABLE_EMIT_STATS'] = 'true'; @@ -48,7 +48,11 @@ export const moduleFederationSSRPlugin = ( }); return { entrypoint, plugins }; }); - api.modifyBundlerChain((chain, { isServer }) => { + api.modifyBundlerChain((chain) => { + const target = chain.get('target'); + if (skipByTarget(target)) { + return; + } const bundlerType = api.getAppContext().bundlerType === 'rspack' ? 'rspack' : 'webpack'; const MFPlugin = @@ -56,7 +60,7 @@ export const moduleFederationSSRPlugin = ( ? ModuleFederationPlugin : RspackModuleFederationPlugin; - const isWeb = isWebTarget(chain.get('target')); + const isWeb = isWebTarget(target); if (!isWeb) { if (!chain.plugins.has(CHAIN_MF_PLUGIN_ID)) { @@ -79,13 +83,13 @@ export const moduleFederationSSRPlugin = ( } } - if (isDev && !isServer) { + if (isDev && isWeb) { chain.externals({ '@module-federation/node/utils': 'NOT_USED_IN_BROWSER', }); } - if (isServer) { + if (!isWeb) { ssrOutputPath = chain.output.get('path') || path.resolve(process.cwd(), `dist/${MODERN_JS_SERVER_DIR}`); diff --git a/packages/modernjs/src/cli/utils.ts b/packages/modernjs/src/cli/utils.ts index a20ac091c16..38a51cfc69d 100644 --- a/packages/modernjs/src/cli/utils.ts +++ b/packages/modernjs/src/cli/utils.ts @@ -389,3 +389,13 @@ export const isWebTarget = (target: string[] | string) => { } return false; }; + +export const skipByTarget = (target: string[] | string) => { + const IGNORE_TARGET = 'webworker'; + if (Array.isArray(target)) { + return target.includes(IGNORE_TARGET); + } else if (typeof target === 'string') { + return target === IGNORE_TARGET; + } + return false; +}; diff --git a/packages/modernjs/src/runtime/index.ts b/packages/modernjs/src/runtime/index.ts index ab849ad061c..55880d8664c 100644 --- a/packages/modernjs/src/runtime/index.ts +++ b/packages/modernjs/src/runtime/index.ts @@ -1,2 +1,5 @@ export * from '@module-federation/enhanced/runtime'; -export { createRemoteSSRComponent } from './createRemoteSSRComponent'; +export { + createRemoteSSRComponent, + collectSSRAssets, +} from './createRemoteSSRComponent'; diff --git a/packages/runtime-core/src/plugins/generate-preload-assets.ts b/packages/runtime-core/src/plugins/generate-preload-assets.ts index 4ec7b2bfcc3..22f15509f8d 100644 --- a/packages/runtime-core/src/plugins/generate-preload-assets.ts +++ b/packages/runtime-core/src/plugins/generate-preload-assets.ts @@ -4,6 +4,7 @@ import { ProviderModuleInfo, isManifestProvider, getResourceUrl, + isBrowserEnv, } from '@module-federation/sdk'; import { EntryAssets, @@ -101,6 +102,12 @@ function traverseModuleInfo( } } +const isExisted = (type: 'link' | 'script', url: string) => { + return document.querySelector( + `${type}[${type === 'link' ? 'href' : 'src'}="${url}"]`, + ); +}; + // eslint-disable-next-line max-lines-per-function export function generatePreloadAssets( origin: FederationHost, @@ -290,16 +297,16 @@ export function generatePreloadAssets( } const needPreloadJsAssets = jsAssets.filter( - (asset) => !loadedSharedJsAssets.has(asset), + (asset) => !loadedSharedJsAssets.has(asset) && !isExisted('script', asset), ); const needPreloadCssAssets = cssAssets.filter( - (asset) => !loadedSharedCssAssets.has(asset), + (asset) => !loadedSharedCssAssets.has(asset) && !isExisted('link', asset), ); return { cssAssets: needPreloadCssAssets, jsAssetsWithoutEntry: needPreloadJsAssets, - entryAssets, + entryAssets: entryAssets.filter((entry) => !isExisted('script', entry.url)), }; } @@ -316,6 +323,13 @@ export const generatePreloadAssetsPlugin: () => FederationRuntimePlugin = globalSnapshot, remoteSnapshot, } = args; + if (!isBrowserEnv()) { + return { + cssAssets: [], + jsAssetsWithoutEntry: [], + entryAssets: [], + }; + } if (isRemoteInfoWithEntry(remote) && isPureRemoteEntry(remote)) { return {