I am trying to split a big monolith React app into micro-frontends using webpack module federation. I already have the remote module deployed and working great when running the dev server locally, everything works perfectly fine. But after running yarn build and deploying the consumer app, it fails with the following error:
Uncaught (in promise) ChunkLoadError: Loading chunk 935 failed.
When commenting out the lazy loaded remote module, everything works fine.
Anyone have any idea how to get webpack to build correctly with a remotely loaded module?
This is my consumer component:
import WorkOrderTrackingErrorBoundary from './work_order_tracking_error_boundary'
const WorkOrderTracking = lazy(() => import('dMove/WorkOrderTracking'))
const WorkOrderTrackingPage = (props) => {
const spinner = (
<SpinnerContainer>
<Spinner type="bars" color="#3e145e" width="48px"/>
</SpinnerContainer>
)
return (
<Suspense fallback={spinner}>
<WorkOrderTrackingErrorBoundary>
<WorkOrderTracking/>
</WorkOrderTrackingErrorBoundary>
</Suspense>
);
};
export default WorkOrderTrackingPage;
and this is my webpack.prod.config.js file:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const StringReplacePlugin = require('string-replace-webpack-plugin');
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin")
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const paths = require('./paths');
const path = require('path');
module.exports = {
bail: true,
mode: 'production',
devtool: 'source-map',
module: {
rules: [
{
oneOf: [
{
test: /\.(js|jsx)$/,
exclude: paths.appNodeModules,
use: {
loader: 'babel-loader'
}
},
{
test: /\.html$/,
use: [
{
loader: 'html-loader'
}
]
},
{
test: [
/\.bmp$/,
/\.gif$/,
/\.jpe?g$/,
/\.png$/,
/\.svg$/
],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]'
}
},
{
exclude: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
]
},
{
include: [paths.appResources, paths.appNodeModules],
test: /\.css$/,
use: [
{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader' // translates CSS into CommonJS
}
]
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]'
}
}
]
}
]
},
plugins: [
new ModuleFederationPlugin({
name: "dView", // name of this project
filename: "remoteEntry.js", // entry file to this project, remoteEntry.js is the conventional name
exposes: {
// components exposed out for other projects to consume
},
remotes: {
// projects to consume
dMove: "dMove@https://dmove-dev.3dsignals.io/remoteEntry.js"
},
shared: {
// shared modules between projects
react: {singleton: true},
"react-dom": {singleton: true}
}
}),
new webpack.DefinePlugin({
"GET_API_TOKEN_URL": JSON.stringify("/security/getAPIToken"),
"GET_REFRESH_TOKEN_URL": JSON.stringify("/security/refreshToken"),
"LOGIN_WITH_FOREIGN_IDM": JSON.stringify("/security/foreignLogin"),
"MAPBOX_API_TOKEN": JSON.stringify("pk.eyJ1IjoiM2RzZGV2b3BzIiwiYSI6ImNrazB2ZHJ2bTBsOTMydnJ1cG40dXc2NjYifQ.pGAk7cQ-ekRJY9KSSrW3lg")
}),
new StringReplacePlugin(),
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
}
}),
new NodePolyfillPlugin()
],
output: {
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].[contenthash].chunk.js',
publicPath: '/',
path: paths.appBuild,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')
},
entry: [
'@babel/polyfill',
paths.appIndexJs
],
resolve: {
modules: [
'node_modules',
paths.appNodeModules,
paths.appSrc,
paths.appResources
],
extensions: [
'.web.js',
'.mjs',
'.js',
'.json',
'.web.jsx',
'.jsx',
'tsx',
'ts'
]
}
};