Issue 1:
Bug report

If you declare shared modules that consist of multiple internal libraries, and define shareKey for this module, you may get run-time JS exceptions Type error: fn is not a function, because ModuleFederationPlugin will register more internal libraries under the same shareKey, which will make some shared libraries inaccessible.

If the current behavior is a bug, please provide the steps to reproduce.

Some shared modules consist of multiple separated libraries. For example, declaring rxjs module as shared:

shared: {
[ 'rxjs' ]
}

In this case ModuleFederationPlugin will generate and register two separated JS libraries: rxjs and rxjs/operators, and register them like so:

register("rxjs", "6.6.7", () => .... __webpack_require__(/*! ./node_modules/rxjs/_esm2015/index.js */ 5906)
register("rxjs/operators", "6.6.7", () => ... __webpack_require__(/*! ./node_modules/rxjs/_esm2015/operators/index.js */ 6370)

This works as expected. But there is a problem when you use shareKey in config:

shared: {
[ 'rxjs': { shareKey: 'rxjs for Angular 13' } ]
}

In this case ModuleFederationPlugin will register both libraries under the same key:

register("rxjs for Angular 13", "6.6.7", () => .... __webpack_require__(/*! ./node_modules/rxjs/_esm2015/index.js */ 5906)
register("rxjs for Angular 13", "6.6.7", () => ... __webpack_require__(/*! ./node_modules/rxjs/_esm2015/operators/index.js */ 6370)

This will produce unexpected run-time JS errors: Type error: fn is not a function, whenever a function from the first library is called, because the function will be looked-up in the second library because it will override the first registered library due to the same key.

What is the expected behavior?

ModuleFederationPlugin should correcly register and resolve multiple libraries (because developers are not aware if shared module consists with more libraries).

There is currently a workaround for this problem if you need to use shareKey: you must explicitely define all internal libraries for a shared module, and define them unique shareKeys:

shared: {
[
'rxjs': { shareKey: 'rxjs for Angular 13' },
'rxjs/operators': { shareKey: 'rxjs/operators for Angular 13' },
]
}

Other relevant information:

webpack version: 5.73.0

Node.js version: 16.15.1

Operating System: Windows 10

Additional tools:

Issue 2:
Bug report

What is the current behavior?

When using Module Federation, sharing a dependency and your other dependencies are using it too but in different versions, it won't respect semver matching and use the same version for everything.

For example, even when it is explicitly defined to be shared with ^8.3.2 in the top-level, it matches the 3.4.0 version that another deep dependency consumes.

3.4.0 does not satisfy constraint ^8.3.2

If the current behavior is a bug, please provide the steps to reproduce.

Repo that reproduces the issue - https://github.com/tzachbon/mf-shared-deep-dependency

This example tries to reproduce the problem when sharing a dependency that exists in multiple versions across the node modules but resolves the request incorrectly.

In this example repo, I use uuid package.

└─┬ @startup-code/app1@0.0.0 -> ./app1
├─┬ lib@1.0.0 -> ./lib
│ └── uuid@3.4.0
├── uuid@8.3.2
└─┬ webpack-dev-server@4.8.1
└─┬ sockjs@0.3.24
└── uuid@8.3.2 deduped

This graph shows that the root uuid is 8.3.2 and the version under lib is 3.4.0.

lib uses the v3 method from uuid.

This method exists only in version 8.3.2.

By default, if we build this project, serve it and click on new uuid, everything crashes as expected:

But when we use Module Federation and share this package from app1 like this:

[
new ModuleFederationPlugin({
name: 'app1',
shared: {
lib: deps['lib'],
uuid: deps['uuid'], // <-- resolve to ^8.3.2
react: { singleton: true, requiredVersion: deps.react },
'react-dom': { singleton: true, requiredVersion: deps['react-dom'] },
},
})
]

We can see that the runtime understands the difference between the packages:

But when we click on new uuid which crashed our app, it works (not the desired behavior)...

When we look inside the index file, we can see the moduleToHandlerMapping resolve it incorrectly:

And when we remove the uuid entry from the shared section in ModuleFederationPlugin we can see that the app behaves as expected:

For some reason, even when it is explicitly defined to be shared with ^8.3.2, it matches the 3.4.0 version that lib consumes.

What is the expected behavior?

I would expect that each dependency would get the correct package resolution according to the node resolution algorithm.

In our example -

top level (App) - 8.3.2

lib - 3.4.0

Other relevant information:

webpack version: 5.72.1

Node.js version: v16.15.0

NPM version: 8.5.5

Operating System: MacOS Monterey 12.4

Also asked in the Module Federation examples repo -

module-federation/module-federation-examples#2033