Skip to content

Resolve module (mjs) incorrectly when we load a module from remote #4238

@y-okt

Description

@y-okt

Summary

The minimum reproduction code is here: https://github.com/y-okt/webpack-module-federation-esm-repro. Special thanks to @naruaway, who originally created this repository.

This issue is the same as webpack's issue. @module-federation/enhanced v0.21.6 incorrectly handles default imports in .mjs files when consuming shared modules in a federation setup with remotes.

Description

When using Module Federation with both remotes AND shared modules, .mjs files that import a default export from a shared module receive the module namespace object instead of the default export value.

Expected

// pure-esm.mjs
import something from "test-pkg-123";
console.log(typeof something); // Expected: "function"

Actual

// pure-esm.mjs
import something from "test-pkg-123";
console.log(typeof something); // Actual: "object" (module namespace)
console.log(something[Symbol.toStringTag]); // "Module"
console.log(something.__esModule); // true

Solution

Logic of the Cause

I guess the following is the reason it is caused.

For .mjs files when NO remotes:

  • Webpack knows the exact module type from buildMeta (code)
  • Generated code: t.default
  • Result: Correctly accesses default property

For .mjs files when remotes are configured:

  • Webpack can't guarantee the module type at runtime
  • Webpack assumes strict ESM and generates c
  • c is the module namespace object
  • Result: .js file receives the namespace object, not the default export

When remotes are configured, in both consumes.ts and installInitialConsumes.ts, module.exports = result; directly assigns factory result without checkign for ESM default export.

Solution

I'm thinking of implementing the following logics.

  1. object/function default exports -> Unwrap the default and make it the primary export, with named exports attached as properties and a circular .default reference
  2. primitive default exports -> Keep the original ESM namespace object to preserve named exports
Image

Reproduction

https://github.com/y-okt/webpack-module-federation-esm-repro

Used Package Manager

pnpm

System Info

System:
    OS: macOS 15.3.2
    CPU: (10) arm64 Apple M4
    Memory: 1.90 GB / 32.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.17.0 - /Users/y-okt/.nvm/versions/node/v22.17.0/bin/node
    Yarn: 1.22.22 - /Users/y-okt/.nvm/versions/node/v22.17.0/bin/yarn
    npm: 10.9.2 - /Users/y-okt/.nvm/versions/node/v22.17.0/bin/npm
    pnpm: 8.11.0 - /opt/homebrew/bin/pnpm
  Browsers:
    Chrome: 142.0.7444.176
    Safari: 18.3.1

Validations

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions