webpack / webpack.js.org

Repository for webpack documentation and more!
https://webpack.js.org
Creative Commons Attribution 4.0 International
2.21k stars 3.31k forks source link

Webpack 5.x: Module Federation shared/singleton w/ amCharts lib 4 broken? #4432

Open marc-polizzi opened 3 years ago

marc-polizzi commented 3 years ago

Bug report

What is the current behavior?

The amCharts 4 lib chunk (defined as a shared/singleton module) is being loaded twice.

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

You can check the following small project:

git

1) npm start amcharts4 to export the module 2) npm start reporting to import that module

You'll see in the image attached to the README.md file of the project that the amcharts4 lib chunk is loaded twice and that in the Chrome devTools console that the amCharts 4 options.license object is duplicated.

What is the expected behavior?

The amCharts 4 lib chunk being loaded once as it is setup as a shared singleton dependency:

        new ModuleFederationPlugin({
            name: "amCharts4",
            filename: "remoteEntry.js",
            exposes: {
                "./PluginDefinition": "./src/PluginDefinition",
            },
            shared: {
                "@amcharts/amcharts4": {singleton: true},
            },
        }),

Other relevant information: webpack version: 5.12 Node.js version: 14.15.4 Operating System: Linux Z370-A 5.8.0-36-generic webpack/webpack#40~20.04.1-Ubuntu SMP Wed Jan 6 10:15:55 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux Additional tools:

alexander-akait commented 3 years ago

Example of usage https://github.com/module-federation/module-federation-examples/tree/master/shared-context

marc-polizzi commented 3 years ago

Thank you for the link but not sure to understand how it is related to this issue.

I've updated a bit the example project to include React/ReactDOM as a similar shared dependency.

The charts plugin is exporting a list of React components and an amCharts component. The reporting is using both React and amCharts as well and then import the plugin.

Both React/ReactDOM and amCharts4 libraries are setup as shared modules for the Module Federation.

Then I can see the React/amCharts4 chunks are loaded first for the reporting and then once the plugin has been imported (via its remoteEntry.js) again the amCharts4 chunk is loaded while the React/ReactDOM are not (as expected).

The setup for the amCharts4 library is the same as for the React/ReactDOM libraries:

        shared: {
            "react": "^17.0.1",
            "react-dom": "^17.0.1",
            "@amcharts/amcharts4": "^4.10.13",
        },

Looking at the remoteEntry.js I can see that the React/ReactDOM library is not handled the same way as the amCharts4 library. Would that be an issue with the way the amCharts4 module has been built?

Note that we have contacted our amCharts support who told us to log an issue over here.

alexander-akait commented 3 years ago

You use library (@amcharts/amcharts4/core) in both builds, so you got two versions, don't use library subpath ('/core') directly, remote should export this library (so it will be use library from remote container) or you can move this in other container

marc-polizzi commented 3 years ago

Sorry but I guess I'm missing something. I thought the meaning of the following is to share common module between the host and the remote:

            shared: {
                "react": {
                    requiredVersion: "^17.0.1",
                    singleton: true,
                },
                "@amcharts/amcharts4": {
                    requiredVersion: "^4.10.13",
                    singleton: true,
                },
            },

And the "singleton" flag to ensure a single module is being used as explained in the types.d.ts of webpack:

    /**
     * Allow only a single version of the shared module in share scope (disabled by default).
     */
    singleton?: boolean;

In my case everything looks good for React/ReactDOM (and by the way other libraries...) but not for amCharts 4.

I do not understand why the behavior would be different for amCharts; everything looks the same for me (package.json, webpack config, the way the libraries are being used, etc...).

sokra commented 3 years ago

"@amcharts/amcharts4/core": { ... }

alexander-akait commented 3 years ago

Change import * as am4core from "@amcharts/amcharts4/core"; to import * as am4core from "@amcharts/amcharts4"; or above example

marc-polizzi commented 3 years ago

Thank you: got it. I've mismatched package names and actual Webpack module names.

Now it works as expected. Thanks again.

alexander-akait commented 3 years ago

Let's docs it

alexander-akait commented 3 years ago

What we need to docs:

new ModuleFederationPlugin({
            name: "amCharts4",
            filename: "remoteEntry.js",
            exposes: {
                "./PluginDefinition": "./src/PluginDefinition",
            },
            shared: {
                "@amcharts/amcharts4": {singleton: true},
            },
}),

You need specify import * as am4core from "@amcharts/amcharts4"; not import * as am4core from "@amcharts/amcharts4/core";, if you want to use import * as am4core from "@amcharts/amcharts4/core"; you need:

new ModuleFederationPlugin({
            name: "amCharts4",
            filename: "remoteEntry.js",
            exposes: {
                "./PluginDefinition": "./src/PluginDefinition",
            },
            shared: {
                "@amcharts/amcharts4/core": {singleton: true},
            },
}),
alexander-akait commented 3 years ago

Can be documented here https://webpack.js.org/concepts/module-federation/#troubleshooting

lili21 commented 3 years ago

I guess it doesn't work well with babel-plugin-lodash, any plan to support this?