From 3d6d3030914ec7873b107ce86ee6e25a0f11b78b Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 9 Feb 2026 07:38:03 +0000 Subject: [PATCH 01/11] fix(enhanced): default remoteType to script Co-authored-by: Zack Jackson --- .../src/lib/container/ModuleFederationPlugin.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts index c9c4bacf0dc..af53a554f62 100644 --- a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts @@ -27,12 +27,6 @@ import FederationModulesPlugin from './runtime/FederationModulesPlugin'; import { createSchemaValidation } from '../../utils'; import TreeShakingSharedPlugin from '../sharing/tree-shaking/TreeShakingSharedPlugin'; -const isValidExternalsType = require( - normalizeWebpackPath( - 'webpack/schemas/plugins/container/ExternalsType.check.js', - ), -) as typeof import('webpack/schemas/plugins/container/ExternalsType.check.js'); - const { ExternalsPlugin } = require( normalizeWebpackPath('webpack'), ) as typeof import('webpack'); @@ -162,11 +156,7 @@ class ModuleFederationPlugin implements WebpackPluginInstance { new FederationRuntimePlugin(options).apply(compiler); const library = options.library || { type: 'var', name: name }; - const remoteType = - options.remoteType || - (options.library && isValidExternalsType(options.library.type) - ? (options.library.type as ExternalsType) - : ('script' as ExternalsType)); + const remoteType = (options.remoteType ?? 'script') as ExternalsType; const useContainerPlugin = options.exposes && From 7a6822e504534777d34204b9b8c9fb8b12ee1ad1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 9 Feb 2026 07:42:03 +0000 Subject: [PATCH 02/11] test(enhanced): cover remoteType default Co-authored-by: Zack Jackson --- .../container/ModuleFederationPlugin.test.ts | 226 ++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts diff --git a/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts new file mode 100644 index 00000000000..b58fe5dd62f --- /dev/null +++ b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts @@ -0,0 +1,226 @@ +import { rs, type Mock } from '@rstest/core'; +import { createMockCompiler, createWebpackMock } from './utils'; + +const webpack = { + ...createWebpackMock(), + DefinePlugin: class DefinePlugin { + apply = rs.fn(); + constructor(_options: Record) {} + }, +}; + +const mocks = rs.hoisted(() => { + const captured = { + containerReferenceOptions: null as null | { remoteType?: string }, + }; + + const mockContainerReferenceApply = rs.fn(); + + return { + captured, + mockBindLoggerToCompiler: rs.fn(), + mockComposeKeyWithSeparator: rs.fn( + (name: string, version: string) => `${name}-${version}`, + ), + mockInfrastructureLogger: { + warn: rs.fn(), + info: rs.fn(), + log: rs.fn(), + }, + mockGetBuildVersion: rs.fn(() => 'build'), + mockContainerManager: rs.fn().mockImplementation(() => ({ + init: rs.fn(), + containerPluginExposesOptions: {}, + })), + mockRemoteEntryPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockFederationRuntimePlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockFederationModulesPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockContainerPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockContainerReferenceApply, + mockContainerReferencePlugin: rs + .fn() + .mockImplementation((options: { remoteType?: string }) => { + captured.containerReferenceOptions = options; + return { + apply: mockContainerReferenceApply, + }; + }), + mockSharePlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockTreeShakingSharedPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockStartupChunkDependenciesPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockStatsPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + mockDtsPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + addRuntimePlugins: rs.fn(), + })), + mockPrefetchPlugin: rs.fn().mockImplementation(() => ({ + apply: rs.fn(), + })), + }; +}); + +rs.mock('webpack', () => webpack); + +rs.mock('@module-federation/sdk/normalize-webpack-path', () => ({ + normalizeWebpackPath: (path: string) => path, +})); + +rs.mock('@module-federation/sdk', () => ({ + bindLoggerToCompiler: mocks.mockBindLoggerToCompiler, + composeKeyWithSeparator: mocks.mockComposeKeyWithSeparator, + infrastructureLogger: mocks.mockInfrastructureLogger, +})); + +rs.mock('@module-federation/managers', () => ({ + ContainerManager: mocks.mockContainerManager, + utils: { + getBuildVersion: mocks.mockGetBuildVersion, + }, +})); + +rs.mock('@module-federation/manifest', () => ({ + StatsPlugin: mocks.mockStatsPlugin, +})); + +rs.mock('@module-federation/dts-plugin', () => ({ + DtsPlugin: mocks.mockDtsPlugin, +})); + +rs.mock('@module-federation/data-prefetch/cli', () => ({ + PrefetchPlugin: mocks.mockPrefetchPlugin, +})); + +rs.mock('@module-federation/rspack/remote-entry-plugin', () => ({ + RemoteEntryPlugin: mocks.mockRemoteEntryPlugin, +})); + +rs.mock('../../../src/utils', () => ({ + createSchemaValidation: () => () => undefined, +})); + +rs.mock('../../../src/lib/container/runtime/FederationRuntimePlugin', () => ({ + __esModule: true, + default: mocks.mockFederationRuntimePlugin, +})); + +rs.mock('../../../src/lib/container/runtime/FederationModulesPlugin', () => ({ + __esModule: true, + default: mocks.mockFederationModulesPlugin, +})); + +rs.mock('../../../src/lib/container/ContainerPlugin', () => ({ + __esModule: true, + default: mocks.mockContainerPlugin, +})); + +rs.mock('../../../src/lib/container/ContainerReferencePlugin', () => ({ + __esModule: true, + default: mocks.mockContainerReferencePlugin, +})); + +rs.mock('../../../src/lib/sharing/SharePlugin', () => ({ + __esModule: true, + default: mocks.mockSharePlugin, +})); + +rs.mock('../../../src/lib/sharing/tree-shaking/TreeShakingSharedPlugin', () => ({ + __esModule: true, + default: mocks.mockTreeShakingSharedPlugin, +})); + +rs.mock('../../../src/lib/startup/MfStartupChunkDependenciesPlugin', () => ({ + __esModule: true, + default: mocks.mockStartupChunkDependenciesPlugin, +})); + +const ModuleFederationPlugin = + require('../../../src/lib/container/ModuleFederationPlugin').default; + +const getTap = ( + tapMock: Mock, + name: string, +): ((...args: Args) => unknown) | undefined => { + const entry = tapMock.mock.calls.find((call: unknown[]) => call[0] === name); + return entry ? (entry[1] as (...args: Args) => unknown) : undefined; +}; + +describe('ModuleFederationPlugin remoteType defaults', () => { + let mockCompiler: ReturnType; + + beforeEach(() => { + rs.clearAllMocks(); + mocks.captured.containerReferenceOptions = null; + mockCompiler = createMockCompiler(); + mockCompiler.hooks.afterPlugins = { tap: rs.fn() }; + mockCompiler.options.output = { + ...mockCompiler.options.output, + enabledLibraryTypes: [], + }; + mockCompiler.options.plugins = []; + mockCompiler.webpack = { + ...mockCompiler.webpack, + DefinePlugin: webpack.DefinePlugin, + } as any; + }); + + it('defaults remoteType to script when library type is umd', () => { + const plugin = new ModuleFederationPlugin({ + name: 'host', + library: { type: 'umd', name: 'host' }, + remotes: { + hostapp: 'hostapp@http://localhost:3000/mf-manifest.json', + }, + manifest: false, + dts: false, + }); + + plugin.apply(mockCompiler as any); + + const afterPluginsTap = getTap( + mockCompiler.hooks.afterPlugins.tap as unknown as Mock, + 'ModuleFederationPlugin', + ); + afterPluginsTap?.(); + + expect(mocks.captured.containerReferenceOptions?.remoteType).toBe('script'); + }); + + it('respects explicit remoteType', () => { + const plugin = new ModuleFederationPlugin({ + name: 'host', + library: { type: 'umd', name: 'host' }, + remotes: { + hostapp: 'hostapp@http://localhost:3000/mf-manifest.json', + }, + remoteType: 'umd', + manifest: false, + dts: false, + }); + + plugin.apply(mockCompiler as any); + + const afterPluginsTap = getTap( + mockCompiler.hooks.afterPlugins.tap as unknown as Mock, + 'ModuleFederationPlugin', + ); + afterPluginsTap?.(); + + expect(mocks.captured.containerReferenceOptions?.remoteType).toBe('umd'); + }); +}); From 44d291b6fc4e26c9ff514e0279ef99c531cb2c9e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Mon, 9 Feb 2026 07:42:27 +0000 Subject: [PATCH 03/11] chore: add changeset for remoteType default Co-authored-by: Zack Jackson --- .changeset/short-crabs-join.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/short-crabs-join.md diff --git a/.changeset/short-crabs-join.md b/.changeset/short-crabs-join.md new file mode 100644 index 00000000000..9fd2c886951 --- /dev/null +++ b/.changeset/short-crabs-join.md @@ -0,0 +1,5 @@ +--- +"@module-federation/enhanced": patch +--- + +Default `remoteType` to `script` so UMD library builds generate remote references correctly. From 2e769a9f3ee5852e45501ed0472182d509f31868 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Mon, 9 Feb 2026 01:38:18 -0800 Subject: [PATCH 04/11] fix: format ModuleFederationPlugin test to pass nx format:check Co-authored-by: Cursor --- .../unit/container/ModuleFederationPlugin.test.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts index b58fe5dd62f..08607f27d00 100644 --- a/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts +++ b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts @@ -139,10 +139,13 @@ rs.mock('../../../src/lib/sharing/SharePlugin', () => ({ default: mocks.mockSharePlugin, })); -rs.mock('../../../src/lib/sharing/tree-shaking/TreeShakingSharedPlugin', () => ({ - __esModule: true, - default: mocks.mockTreeShakingSharedPlugin, -})); +rs.mock( + '../../../src/lib/sharing/tree-shaking/TreeShakingSharedPlugin', + () => ({ + __esModule: true, + default: mocks.mockTreeShakingSharedPlugin, + }), +); rs.mock('../../../src/lib/startup/MfStartupChunkDependenciesPlugin', () => ({ __esModule: true, From 8983213f39f93c4c1a17f4f5aa93b1f2fbc4967e Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Mon, 9 Feb 2026 02:38:04 -0800 Subject: [PATCH 05/11] fix(enhanced): lazy-require RemoteEntryPlugin and restore remoteType fallback 1. Change RemoteEntryPlugin from a static top-level import to a lazy require inside apply(). This fixes a TDZ (Temporal Dead Zone) error "Cannot access 'RemoteEntryPlugin' before initialization" that occurred in rstest unit tests due to ESM binding initialization order. 2. Restore the original remoteType fallback logic that uses the library type when it is a valid externals type, defaulting to 'script' only for invalid types like 'umd'. This replaces the isValidExternalsType webpack schema import with an inline Set of known valid types. Co-authored-by: Cursor --- .../lib/container/ModuleFederationPlugin.ts | 33 +++++++++++++++++-- .../node_modules/ui-lib-dep/package.json | 2 +- .../node_modules/ui-lib/package.json | 2 +- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts index af53a554f62..b22ced4bd68 100644 --- a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts @@ -20,7 +20,6 @@ import SharePlugin from '../sharing/SharePlugin'; import ContainerPlugin from './ContainerPlugin'; import ContainerReferencePlugin from './ContainerReferencePlugin'; import FederationRuntimePlugin from './runtime/FederationRuntimePlugin'; -import { RemoteEntryPlugin } from '@module-federation/rspack/remote-entry-plugin'; import { ExternalsType } from 'webpack/declarations/WebpackOptions'; import StartupChunkDependenciesPlugin from '../startup/MfStartupChunkDependenciesPlugin'; import FederationModulesPlugin from './runtime/FederationModulesPlugin'; @@ -110,6 +109,8 @@ class ModuleFederationPlugin implements WebpackPluginInstance { throw new Error('ModuleFederationPlugin name is required'); } // must before ModuleFederationPlugin + const { RemoteEntryPlugin } = + require('@module-federation/rspack/remote-entry-plugin') as typeof import('@module-federation/rspack/remote-entry-plugin'); (new RemoteEntryPlugin(options) as unknown as WebpackPluginInstance).apply( compiler, ); @@ -156,7 +157,35 @@ class ModuleFederationPlugin implements WebpackPluginInstance { new FederationRuntimePlugin(options).apply(compiler); const library = options.library || { type: 'var', name: name }; - const remoteType = (options.remoteType ?? 'script') as ExternalsType; + // Default remoteType to 'script' unless the library type itself is a + // well-known externals type that works as a remoteType (e.g. 'var', + // 'module'). Notably, 'umd' is excluded because it isn't a valid + // remoteType for ContainerReferencePlugin. + const validRemoteTypes = new Set([ + 'var', + 'module', + 'assign', + 'this', + 'window', + 'self', + 'global', + 'commonjs', + 'commonjs2', + 'commonjs-module', + 'commonjs-static', + 'amd', + 'amd-require', + 'system', + 'jsonp', + 'import', + 'script', + 'node-commonjs', + 'promise', + ]); + const remoteType = (options.remoteType ?? + (options.library && validRemoteTypes.has(options.library.type) + ? options.library.type + : 'script')) as ExternalsType; const useContainerPlugin = options.exposes && diff --git a/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib-dep/package.json b/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib-dep/package.json index a273d11c0b2..436a74b6795 100644 --- a/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib-dep/package.json +++ b/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib-dep/package.json @@ -3,4 +3,4 @@ "main": "./index.js", "version": "1.0.0", "sideEffects": false -} \ No newline at end of file +} diff --git a/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib/package.json b/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib/package.json index b42492e6ab5..90f9db2691b 100644 --- a/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib/package.json +++ b/packages/enhanced/test/configCases/tree-shaking-share/reshake-share/node_modules/ui-lib/package.json @@ -3,4 +3,4 @@ "main": "./index.js", "version": "1.0.0", "sideEffects": false -} \ No newline at end of file +} From a805d7053b387606054b3ab99909af540d3597b3 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Mon, 9 Feb 2026 05:24:48 -0800 Subject: [PATCH 06/11] fix(enhanced): keep remoteType defaults but force script for manifest --- .../lib/container/ModuleFederationPlugin.ts | 31 +++++++++++++++++-- .../tree-shaking/IndependentSharedPlugin.ts | 13 +++++++- .../container/ModuleFederationPlugin.test.ts | 25 ++++++++++++++- 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts index b22ced4bd68..a2f128a068b 100644 --- a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts @@ -26,6 +26,12 @@ import FederationModulesPlugin from './runtime/FederationModulesPlugin'; import { createSchemaValidation } from '../../utils'; import TreeShakingSharedPlugin from '../sharing/tree-shaking/TreeShakingSharedPlugin'; +const isValidExternalsType = require( + normalizeWebpackPath( + 'webpack/schemas/plugins/container/ExternalsType.check.js', + ), +) as typeof import('webpack/schemas/plugins/container/ExternalsType.check.js'); + const { ExternalsPlugin } = require( normalizeWebpackPath('webpack'), ) as typeof import('webpack'); @@ -109,6 +115,7 @@ class ModuleFederationPlugin implements WebpackPluginInstance { throw new Error('ModuleFederationPlugin name is required'); } // must before ModuleFederationPlugin + // Use runtime require here to avoid import cycles (and to play nicely with test-time mocking). const { RemoteEntryPlugin } = require('@module-federation/rspack/remote-entry-plugin') as typeof import('@module-federation/rspack/remote-entry-plugin'); (new RemoteEntryPlugin(options) as unknown as WebpackPluginInstance).apply( @@ -182,10 +189,28 @@ class ModuleFederationPlugin implements WebpackPluginInstance { 'node-commonjs', 'promise', ]); + + const isManifestRemote = (value: unknown): boolean => { + // Manifest remote syntax is typically: "name@http(s)://.../mf-manifest.json" + if (typeof value !== 'string') return false; + return /mf-manifest\.json(\?|#|$)/.test(value); + }; + + const remotesContainManifest = (() => { + if (!remotes) return false; + if (Array.isArray(remotes)) return remotes.some(isManifestRemote); + // Object form: { [key]: string | ... }. Only handle string values here. + return Object.values(remotes as Record).some( + isManifestRemote, + ); + })(); + const remoteType = (options.remoteType ?? - (options.library && validRemoteTypes.has(options.library.type) - ? options.library.type - : 'script')) as ExternalsType; + (remotesContainManifest + ? 'script' + : options.library && validRemoteTypes.has(options.library.type) + ? options.library.type + : 'script')) as ExternalsType; const useContainerPlugin = options.exposes && diff --git a/packages/enhanced/src/lib/sharing/tree-shaking/IndependentSharedPlugin.ts b/packages/enhanced/src/lib/sharing/tree-shaking/IndependentSharedPlugin.ts index 8254fb95697..323076fd9d1 100644 --- a/packages/enhanced/src/lib/sharing/tree-shaking/IndependentSharedPlugin.ts +++ b/packages/enhanced/src/lib/sharing/tree-shaking/IndependentSharedPlugin.ts @@ -241,6 +241,17 @@ export default class IndependentSharedPlugin { const shareRequestsMap: ShareRequestsMap = await this.createIndependentCompiler(parentCompiler); + const normalizeRequest = (resource: string) => { + // The collector records resolved absolute resources. For independent fallback bundles we want + // webpack to resolve the module from the same context as the parent compilation, otherwise + // some setups end up with a runtime "Cannot find module ..." stub instead of bundling. + if (typeof resource !== 'string' || !resource) return resource; + if (!path.isAbsolute(resource)) return resource; + const rel = path.relative(parentCompiler.context, resource); + if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return resource; + return `./${rel.split(path.sep).join('/')}`; + }; + await Promise.all( sharedOptions.map(async ([shareName, shareConfig]) => { if (!shareConfig.treeShaking) { @@ -258,7 +269,7 @@ export default class IndependentSharedPlugin { currentShare: { shareName, version, - request, + request: normalizeRequest(request), independentShareFileName: sharedConfig?.treeShaking?.filename, }, }); diff --git a/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts index 08607f27d00..dbf1a8ca3be 100644 --- a/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts +++ b/packages/enhanced/test/unit/container/ModuleFederationPlugin.test.ts @@ -182,7 +182,7 @@ describe('ModuleFederationPlugin remoteType defaults', () => { } as any; }); - it('defaults remoteType to script when library type is umd', () => { + it('defaults remoteType to script for manifest remotes (umd library)', () => { const plugin = new ModuleFederationPlugin({ name: 'host', library: { type: 'umd', name: 'host' }, @@ -204,6 +204,29 @@ describe('ModuleFederationPlugin remoteType defaults', () => { expect(mocks.captured.containerReferenceOptions?.remoteType).toBe('script'); }); + it('defaults remoteType to library type for non-manifest remotes', () => { + const plugin = new ModuleFederationPlugin({ + name: 'host', + library: { type: 'var', name: 'host' }, + remotes: { + // Non-manifest remote: should not force "script" + remoteA: 'remoteA@http://localhost:3001/remoteEntry.js', + }, + manifest: false, + dts: false, + }); + + plugin.apply(mockCompiler as any); + + const afterPluginsTap = getTap( + mockCompiler.hooks.afterPlugins.tap as unknown as Mock, + 'ModuleFederationPlugin', + ); + afterPluginsTap?.(); + + expect(mocks.captured.containerReferenceOptions?.remoteType).toBe('var'); + }); + it('respects explicit remoteType', () => { const plugin = new ModuleFederationPlugin({ name: 'host', From 77452d610d6d63b6c36533a13c260f53d54656e7 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 11 Feb 2026 18:59:19 -0800 Subject: [PATCH 07/11] chore(core): add changeset coverage for pr #4397 --- .changeset/auto-pr-4397-coverage.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/auto-pr-4397-coverage.md diff --git a/.changeset/auto-pr-4397-coverage.md b/.changeset/auto-pr-4397-coverage.md new file mode 100644 index 00000000000..f1b7c238f3a --- /dev/null +++ b/.changeset/auto-pr-4397-coverage.md @@ -0,0 +1,5 @@ +--- +'@module-federation/enhanced': patch +--- + +Add contextual changeset coverage for packages modified in PR #4397. From 4c48237ac5c2eaa890ad27d1474774e75e0cfb23 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Wed, 11 Feb 2026 19:10:25 -0800 Subject: [PATCH 08/11] chore(enhanced): remove redundant auto changeset --- .changeset/auto-pr-4397-coverage.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/auto-pr-4397-coverage.md diff --git a/.changeset/auto-pr-4397-coverage.md b/.changeset/auto-pr-4397-coverage.md deleted file mode 100644 index f1b7c238f3a..00000000000 --- a/.changeset/auto-pr-4397-coverage.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@module-federation/enhanced': patch ---- - -Add contextual changeset coverage for packages modified in PR #4397. From 9c02be1f76ed31e840a7611e56b2ca153fdb4842 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 24 Feb 2026 15:11:44 -0800 Subject: [PATCH 09/11] fix(dts-plugin): align workspace entrypoints and RawSource typing Resolve the dts-plugin TYPE-001 failure by correcting package entry paths for workspace dependencies and updating RawSource usage for webpack typings. Co-authored-by: Cursor --- .../dts-plugin/src/plugins/GenerateTypesPlugin.ts | 6 ++---- packages/error-codes/package.json | 8 ++++---- packages/sdk/package.json | 12 ++++++------ 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts b/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts index a8b4aaeed5f..d103436ff60 100644 --- a/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts +++ b/packages/dts-plugin/src/plugins/GenerateTypesPlugin.ts @@ -172,8 +172,7 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { compilation.emitAsset( zipName, new compiler.webpack.sources.RawSource( - fs.readFileSync(zipTypesPath), - false, + fs.readFileSync(zipTypesPath) as unknown as string, ), ); } @@ -186,8 +185,7 @@ export class GenerateTypesPlugin implements WebpackPluginInstance { compilation.emitAsset( apiFileName, new compiler.webpack.sources.RawSource( - fs.readFileSync(apiTypesPath), - false, + fs.readFileSync(apiTypesPath) as unknown as string, ), ); } diff --git a/packages/error-codes/package.json b/packages/error-codes/package.json index 126b794b07c..352010e14a9 100644 --- a/packages/error-codes/package.json +++ b/packages/error-codes/package.json @@ -25,14 +25,14 @@ "browser": { "url": false }, - "main": "./dist/index.cjs.js", - "module": "./dist/index.esm.mjs", + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.esm.mjs", - "require": "./dist/index.cjs.js" + "import": "./dist/index.mjs", + "require": "./dist/index.cjs" } }, "typesVersions": { diff --git a/packages/sdk/package.json b/packages/sdk/package.json index cc3f5bde8d4..85026bc4549 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -23,8 +23,8 @@ }, "author": "zhanghang ", "sideEffects": false, - "main": "./dist/index.cjs.cjs", - "module": "./dist/index.esm.js", + "main": "./dist/index.cjs", + "module": "./dist/index.js", "types": "./dist/index.d.ts", "browser": { "url": false @@ -33,21 +33,21 @@ ".": { "import": { "types": "./dist/index.d.ts", - "default": "./dist/index.esm.js" + "default": "./dist/index.js" }, "require": { "types": "./dist/index.d.ts", - "default": "./dist/index.cjs.cjs" + "default": "./dist/index.cjs" } }, "./normalize-webpack-path": { "import": { "types": "./dist/normalize-webpack-path.d.ts", - "default": "./dist/normalize-webpack-path.esm.js" + "default": "./dist/normalize-webpack-path.js" }, "require": { "types": "./dist/normalize-webpack-path.d.ts", - "default": "./dist/normalize-webpack-path.cjs.cjs" + "default": "./dist/normalize-webpack-path.cjs" } } }, From 3b419b632538278d7c60a9e3b335b858166183d2 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 24 Feb 2026 19:15:58 -0800 Subject: [PATCH 10/11] fix(sdk): align package entrypoints with emitted artifacts Restore sdk and error-codes export paths to the filenames emitted by the current build so CI package resolution no longer fails on these branches. Co-authored-by: Cursor --- packages/error-codes/package.json | 8 ++++---- packages/sdk/package.json | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/error-codes/package.json b/packages/error-codes/package.json index 352010e14a9..126b794b07c 100644 --- a/packages/error-codes/package.json +++ b/packages/error-codes/package.json @@ -25,14 +25,14 @@ "browser": { "url": false }, - "main": "./dist/index.cjs", - "module": "./dist/index.mjs", + "main": "./dist/index.cjs.js", + "module": "./dist/index.esm.mjs", "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.mjs", - "require": "./dist/index.cjs" + "import": "./dist/index.esm.mjs", + "require": "./dist/index.cjs.js" } }, "typesVersions": { diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 85026bc4549..cc3f5bde8d4 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -23,8 +23,8 @@ }, "author": "zhanghang ", "sideEffects": false, - "main": "./dist/index.cjs", - "module": "./dist/index.js", + "main": "./dist/index.cjs.cjs", + "module": "./dist/index.esm.js", "types": "./dist/index.d.ts", "browser": { "url": false @@ -33,21 +33,21 @@ ".": { "import": { "types": "./dist/index.d.ts", - "default": "./dist/index.js" + "default": "./dist/index.esm.js" }, "require": { "types": "./dist/index.d.ts", - "default": "./dist/index.cjs" + "default": "./dist/index.cjs.cjs" } }, "./normalize-webpack-path": { "import": { "types": "./dist/normalize-webpack-path.d.ts", - "default": "./dist/normalize-webpack-path.js" + "default": "./dist/normalize-webpack-path.esm.js" }, "require": { "types": "./dist/normalize-webpack-path.d.ts", - "default": "./dist/normalize-webpack-path.cjs" + "default": "./dist/normalize-webpack-path.cjs.cjs" } } }, From b5480ae80b661069988b147818a1a5e4c8bf6034 Mon Sep 17 00:00:00 2001 From: ScriptedAlchemy Date: Tue, 24 Feb 2026 19:40:33 -0800 Subject: [PATCH 11/11] fix(enhanced): restore typed remoteType for container references Use the computed remoteType when wiring ContainerReferencePlugin and constrain its type to the federation option contract to avoid CI TypeScript failures. Co-authored-by: Cursor --- .../enhanced/src/lib/container/ModuleFederationPlugin.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts index 58393ab4262..856b27f7b73 100644 --- a/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts +++ b/packages/enhanced/src/lib/container/ModuleFederationPlugin.ts @@ -20,7 +20,6 @@ import SharePlugin from '../sharing/SharePlugin'; import ContainerPlugin from './ContainerPlugin'; import ContainerReferencePlugin from './ContainerReferencePlugin'; import FederationRuntimePlugin from './runtime/FederationRuntimePlugin'; -import { ExternalsType } from 'webpack/declarations/WebpackOptions'; import StartupChunkDependenciesPlugin from '../startup/MfStartupChunkDependenciesPlugin'; import FederationModulesPlugin from './runtime/FederationModulesPlugin'; import { createSchemaValidation } from '../../utils'; @@ -210,7 +209,9 @@ class ModuleFederationPlugin implements WebpackPluginInstance { ? 'script' : options.library && validRemoteTypes.has(options.library.type) ? options.library.type - : 'script')) as ExternalsType; + : 'script')) as NonNullable< + moduleFederationPlugin.ModuleFederationPluginOptions['remoteType'] + >; const useContainerPlugin = options.exposes && @@ -263,7 +264,7 @@ class ModuleFederationPlugin implements WebpackPluginInstance { : Object.keys(remotes).length > 0) ) { new ContainerReferencePlugin({ - remoteType: containerRemoteType, + remoteType, shareScope, remotes, }).apply(compiler);