webpack is not able to serve file correctly when a public path is set

20 Views Asked by At

I have an angular shell application and a react micro front end (MFE) that uses webpack and module federation. I have a problem with the remote entry pathing. When I set the MFE webpack output config like this:

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: 'auto',
},

And the shell like this:

loadRemoteModule({
  remoteEntry: "http://localhost:3000/remoteEntry.js",
  remoteName: "prompt_mfe",
  exposedModule: "./Prompt",
});

It works fine. However, I need the MFE to be served under the /mfe-prompt/ path. But if I configure it like this:

output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    publicPath: '/mfe-prompt/',
},

And the shell like this:

 loadRemoteModule({
  remoteEntry: "http://localhost:3000/mfe-prompt/remoteEntry.js",
  remoteName: "prompt_mfe",
  exposedModule: "./Prompt",
});

It does not import the MFE properly. Instead, I see the following error on the network tab:

GET http://localhost:4201/mfe-prompt/src_containers_Prompt_Prompt_tsx.bundle.js net::ERR_ABORTED 404 (Not Found)

I don't understand why, when I set the public path, the file becomes src_containers_Prompt_Prompt_tsx.bundle.js instead of remoteEntry.js, and I also don't understand the 404. If I go to that GET path in the browser, it exists and I can see the JS content. Is there further configuration I need to do when I set the public path? Something missing? Below are my complete webpack files:

Shell application:

import { container } from 'webpack';
const deps = require('./package.json').dependencies;

module.exports = {
  output: {
    publicPath: 'http://localhost:4201/',
    uniqueName: 'musicapp',
    scriptType: 'text/javascript',
  },
  optimization: {
    runtimeChunk: false,
  },
  devServer: {
    port: 4201,
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
    hot: true,
  },
  plugins: [
    new container.ModuleFederationPlugin({
      name: 'angular-shell',
      filename: 'remoteEntry.js',
      remotes: {
        prompt_mfe: `prompt_mfe@http://localhost:3000/mfe-prompt/remoteEntry.js`,
      },
      shared: {
        react: { singleton: true, eager: true, requiredVersion: deps.react },
        'react-dom': {
          singleton: true,
          eager: true,
          requiredVersion: deps['react-dom'],
        },
        'react-router-dom': {
          singleton: true,
          eager: true,
          requiredVersion: deps['react-router-dom'],
        },
        '@dds/react': {
          singleton: true,
          eager: true,
          requiredVersion: deps['@dds/react'],
        },
        'prop-types': {
          singleton: true,
          eager: true,
          requiredVersion: deps['prop-types'],
        },
      },
    }),
  ],
};

MFE:

const HtmlWebPackPlugin = require('html-webpack-plugin');
const { ModuleFederationPlugin } = require('webpack').container;

const path = require('path');
const deps = require('./package.json').dependencies;

const htmlPlugin = new HtmlWebPackPlugin({
    template: './public/index.html',
    filename: './index.html',
    publicPath: '/mfe-prompt/'
});

module.exports = {
    mode: 'development',
    entry: './src/index.tsx',
    resolve: {
        extensions: ['.ts', '.tsx', '.js'],
        modules: [path.resolve(__dirname, 'src'), 'node_modules'],
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/mfe-prompt/',
    },
    devServer: {
        static: path.join(__dirname, 'dist'),
        port: 3000,
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },
    module: {
        rules: [
            {
                test: /\.(ts|tsx|js)$/,
                exclude: /node_modules/,
                loader: 'ts-loader',
            },
            {
                test: /\.s[ac]ss$/i,
                use: ['style-loader', 'css-loader', 'sass-loader'],
            },
        ],
    },
    plugins: [
        htmlPlugin,
        new ModuleFederationPlugin({
            name: 'prompt_mfe',
            filename: 'remoteEntry.js',
            exposes: {
                './Prompt': './src/containers/Prompt/Prompt.tsx',
            },
            shared: {
                react: { singleton: true, eager: true, requiredVersion: deps.react },
                'react-dom': {
                    singleton: true,
                    eager: true,
                    requiredVersion: deps['react-dom'],
                },
                'react-router-dom': {
                    singleton: true,
                    eager: true,
                    requiredVersion: deps['react-router-dom'],
                },
                '@dds/react': {
                    singleton: true,
                    eager: true,
                    requiredVersion: deps['@dds/react'],
                },
                'prop-types': {
                    singleton: true,
                    eager: true,
                    requiredVersion: deps['prop-types'],
                },
            },
        }),
    ],
};
0

There are 0 best solutions below