module-federation / core

Module Federation is a concept that allows developers to share code and resources across multiple JavaScript applications
https://module-federation.io/
MIT License
1.43k stars 214 forks source link

Async shared modules not resolved correctly with module federation. #3003

Open HariAbinesh opened 2 days ago

HariAbinesh commented 2 days ago

Describe the bug

NPM Package App1.js

const user = {
    name: "Ashok kumar D",
    age: "30"
};
 export {
    user
 };

NPM Package index.js

const {user} = await import("./app1");
export {
    user
};

While using above mentioned npm. package in App, the static import resolves to parent promise object instead of resolved object.

const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require('@module-federation/enhanced');
const path = require('path');
const deps = require('./package.json').dependencies;

/**
 * @type {import('webpack').Configuration}
 **/
const webpackConfig = {
  entry: './src/index',
  mode: 'development',
  devServer: {
    devMiddleware: {
      writeToDisk: true
    },
    static: {
      directory: path.join(__dirname, 'dist'),

    },
    port: 3001,
  },
  experiments: {
    topLevelAwait: true
  },
  output: {
    publicPath: 'auto',
  },
  module: {
    rules: [
      {
        test: /\.m?js$/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        options: {
          presets: ['@babel/preset-react'],
        },
      },
    ],
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'app1',
      library: { type: 'var', name: 'app1' },
      remotes: {
        app2: 'app2',
      },
      shared: {
        "top-level-await-module-fed-issue": {
          eager: true
        },
        'react-dom': {
          import: 'react-dom', // the "react" package will be used a provided and fallback module
          shareKey: 'react-dom', // under this name the shared module will be placed in the share scope
          shareScope: 'legacy', // share scope with this name will be used
          singleton: true, // only a single version of the shared module is allowed
        },
        // oldReact: {
        //   import: "react", // the "react" package will be used a provided and fallback module
        //   shareKey: "oldReact", // under this name the shared module will be placed in the share scope
        //   shareScope: "legacy", // share scope with this name will be used
        //   singleton: true, // only a single version of the shared module is allowed
        // }
      },
    }),
    new HtmlWebpackPlugin({
      template: './public/index.html',
      app2RemoteEntry: getRemoteEntryUrl(3002),
    }),
  ],
};

module.exports = webpackConfig;

function getRemoteEntryUrl(port) {
  const { CODESANDBOX_SSE, HOSTNAME = '' } = process.env;

  // Check if the example is running on codesandbox
  // https://codesandbox.io/docs/environment
  if (!CODESANDBOX_SSE) {
    return `//localhost:${port}/remoteEntry.js`;
  }

  const parts = HOSTNAME.split('-');
  const codesandboxId = parts[parts.length - 1];

  return `//${codesandboxId}-${port}.sse.codesandbox.io/remoteEntry.js`;
}

Actual App code

import {user} from "top-level-await-module-fed-issue";
import('./bootstrap');
console.log(user);
export { };
Screenshot 2024-09-27 at 3 47 15 PM

What is the expected behavior? Imported modules from module federation should resolve normally whether it's async modules or not

Reproduction

https://github.com/HariAbinesh/top-level-await-module-fed-issue-app

Used Package Manager

npm

System Info

node: 20

Validations

HariAbinesh commented 2 days ago

webpack/webpack#15044

ScriptedAlchemy commented 16 hours ago

The remote is not set to esm output, its set to var - so top level await is not possible in that runtime. Set the federation to library.type = module