Skip to content

Conversation

@y-okt
Copy link

@y-okt y-okt commented Nov 22, 2025

Description

When using Module Federation with .mjs files, default exports are incorrectly resolved. Instead of receiving the actual default export value, consumers receive the ESM namespace object.

Example

// In a .mjs file consuming a shared/remote module
import something from "some-package";

// Expected: typeof something === "function" (the actual default export)
// Actual:   typeof something === "object" (the namespace object with __esModule: true)

Testing with the reproduction codes,
スクリーンショット 2025-11-23 2 28 43

Root Cause

Webpack normally inspects buildMeta to determine the exact export type at compile time and generates appropriate code to access module.default.
However, in Module Federation contexts:

  1. Shared modules (ConsumeSharedModule)
    The actual module is resolved at runtime, so webpack cannot determine the export type at compile time.

  2. Remote modules (RemoteModule)
    The module comes from a federated remote, making compile-time analysis impossible.

Without knowing the export type, webpack defaults to treating these as strict ESM modules and returns the namespace object instead of unwrapping the default export.

Previous Approach (Removed)

The previous fix attempted to copy buildMeta / buildInfo from fallback modules at runtime in ConsumeSharedPlugin.ts.
This worked for shared modules with fallbacks but failed for remote modules, which have no fallback to copy metadata from.

Solution

Override getExportsType() in both RemoteModule and ConsumeSharedModule to return "dynamic".
This tells webpack to generate __webpack_require__.n() at compile time, which properly handles ESM/CJS interoperability by:

  • Checking if the module has __esModule flag at runtime
  • Returning module.default for ESM modules
  • Returning the module itself for CJS modules

This approach works for both shared modules and remote modules, since it doesn't depend on fallback metadata.

Related Issue

#4238

In webpack,
webpack/webpack#16125
webpack/webpack#20189

Types of changes

  • Docs change / refactoring / dependency upgrade
  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)

Checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • [] I have updated the documentation.

@changeset-bot
Copy link

changeset-bot bot commented Nov 22, 2025

🦋 Changeset detected

Latest commit: d317461

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 37 packages
Name Type
@module-federation/enhanced Patch
@module-federation/modern-js Patch
@module-federation/nextjs-mf Patch
@module-federation/node Patch
@module-federation/rsbuild-plugin Patch
@module-federation/rspress-plugin Patch
@module-federation/storybook-addon Patch
@module-federation/modernjsapp Patch
remote5 Patch
remote6 Patch
website-new Patch
@module-federation/runtime Patch
@module-federation/rspack Patch
@module-federation/webpack-bundler-runtime Patch
@module-federation/sdk Patch
@module-federation/runtime-tools Patch
@module-federation/managers Patch
@module-federation/manifest Patch
@module-federation/dts-plugin Patch
@module-federation/third-party-dts-extractor Patch
@module-federation/devtools Patch
@module-federation/bridge-react Patch
@module-federation/bridge-vue3 Patch
@module-federation/bridge-shared Patch
@module-federation/bridge-react-webpack-plugin Patch
@module-federation/retry-plugin Patch
@module-federation/data-prefetch Patch
@module-federation/error-codes Patch
@module-federation/inject-external-runtime-core-plugin Patch
@module-federation/runtime-core Patch
create-module-federation Patch
@module-federation/cli Patch
@module-federation/metro Patch
@module-federation/metro-plugin-rnef Patch
@module-federation/metro-plugin-rnc-cli Patch
@module-federation/esbuild Patch
@module-federation/utilities Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Nov 22, 2025

Deploy Preview for module-federation-docs ready!

Name Link
🔨 Latest commit d317461
🔍 Latest deploy log https://app.netlify.com/projects/module-federation-docs/deploys/69336f0d0282a20008ff0cee
😎 Deploy Preview https://deploy-preview-4239--module-federation-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@y-okt y-okt force-pushed the fix-resolve-mjs-on-federation-remote branch 2 times, most recently from ef448c7 to eb21d4c Compare November 22, 2025 17:18
@y-okt y-okt changed the title fix(webpack-bundler-runtime): fix the bug in which mjs is wrongly handled fix(webpack-bundler-runtime): fix the bug that mjs is wrongly handled Nov 22, 2025
y-okt added 2 commits December 2, 2025 19:42
… mjs files

Fix ESM interop issue where .mjs files received module namespace objects
instead of default exports when using Module Federation with remotes.

The runtime now intelligently unwraps ESM namespace objects for
object/function default exports while preserving the namespace for
primitive defaults to maintain named export accessibility.
fix mjs handling issue by introducing dynamic override
@y-okt y-okt force-pushed the fix-resolve-mjs-on-federation-remote branch from eb21d4c to 696a637 Compare December 2, 2025 13:01
},
);

// Add finishModules hook to copy buildMeta/buildInfo from fallback modules *after* webpack's export analysis
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for this change is that:

  1. since I introduced "dynamic", this tells webpack to generate __wepack_require__.n() at compile time, which properly handles the ESM/CJS interop. The deleted codes are to inherit the ESM/CJS detection from the actual shared module, which is no longer necessary
  2. As explained in the description section, this can't deal with federation-remote case
  3. Instead of copying buildMeta at runtime, it's better to deal with it at compilation time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant