bhalaji
bhalaji

Reputation: 137

React module federation micro frontend- webpack 5 public path auto is not working

In my react micro frontend project which uses module federation plugin remoteEntry.js path is incorrectly fetched and application crashes.

With hard-coded publicPath: "http://localhost:3000/" in webpack things work as expected.

But due to existing CI/CD setup in my project, publicPath in the webpack config cannot be hard-coded at the build time.

As per various articles it was recommended to use publicPath : auto in the webpack config of the application.

Yes publicPath : auto solves the issue of hard coding at build time.

But during page refresh, remoteEntry.js is fetched from incorrect url.

To simulate the scenario I created simple react application using webpack and module federation plugin

On the initial load remoteEntry.js is fetched from http://localhost:3000/remoteEntry.js as expected

enter image description here

When under nested URL http://localhost:3000/home/foo/about, On refresh main.js and remoteEntry.js is fetched from http://localhost:3000/home/foo/remoteEntry.js - application crashes

enter image description here

Github link for the project simulating the scenario https://github.com/cyberfury10/mf-page-refresh-issue

webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

const deps = require("./package.json").dependencies;
module.exports = {
  output: {
    publicPath: "auto",
  },

  resolve: {
    extensions: [".tsx", ".ts", ".jsx", ".js", ".json"],
  },

  devServer: {
    port: 3000,
    historyApiFallback: true,
  },

  module: {
    rules: [
      {
        test: /\.m?js/,
        type: "javascript/auto",
        resolve: {
          fullySpecified: false,
        },
      },
      {
        test: /\.(css|s[ac]ss)$/i,
        use: ["style-loader", "css-loader", "postcss-loader"],
      },
      {
        test: /\.(ts|tsx|js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
        },
      },
    ],
  },

  plugins: [
    new ModuleFederationPlugin({
      name: "mf_page_refresh_issue",
      filename: "remoteEntry.js",
      remotes: {},
      exposes: {
        './Component' : './src/test-component.js'
      },
      shared: {
        ...deps,
        react: {
          singleton: true,
          requiredVersion: deps.react,
        },
        "react-dom": {
          singleton: true,
          requiredVersion: deps["react-dom"],
        },
      },
    }),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
    }),
  ],
};

I am using "react-router-dom": "^6.3.0" and also tried with "@reach/router": "^1.3.4", but the issue is same

Tried solutions given in https://github.com/module-federation/module-federation-examples/issues/102 but it didn't work

Last suggestion from ScriptedAlchemy in the above link is to use publicPath : auto in 2022

Any help would much appreciated. Thanks in advance.

Upvotes: 4

Views: 5111

Answers (2)

Yogurtu
Yogurtu

Reputation: 3031

When you say "Refresh" I guess you referring to pressing f5 in browser and refreshing a remote.

This is a problem we also have in angular, and usually it's solved by doing redirection settings, so sorry I can't provide the react version of it, but I think is not something specific to angular, in my IIS I add something like this to do URL rewrite, and solves the issue when pressing f5.

In azure app services, or GPC cloud runs, you will have the same but in other settings, depending where you hosting your app.

TLDR: You need to apply URL rewrite to go to "/", and that will solve the issue when somebody press refresh.

<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="AngularJS Routes" stopProcessing="true">
          <match url=".*" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{REQUEST_URI}" pattern="^/(api)" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

And btw. If you using IIS to test, then you also need to install a plug-in for this to work, it is called UrlRewrite and you get it from microsoft: https://www.iis.net/downloads/microsoft/url-rewrite

Upvotes: 0

bhalaji
bhalaji

Reputation: 137

In case anyone is facing the same issue, add another publicPath : '/' in HtmlWebpackPlugin().

something like the following

  new HtmlWebPackPlugin({
    template: './public/index.html',
    favicon: './public/favicon.png',
    assets: './public/assets',
    publicPath: '/',
  }),

Referred workaround from the following link and it helped https://github.com/module-federation/module-federation-examples/pull/2170

Upvotes: 5

Related Questions