'Use the same port in Module Federated React Application
I've 3 applications which are embedded on the same spring service (built by yarn maven plugin) with the following configuration:
App Shell
module.exports = {
mode: 'production',
entry: './src/index',
cache: false,
devtool: false,
optimization: {
minimize: true,
},
output: {
publicPath: 'http://localhost:8000/gui/shell/',
clean: true,
pathinfo: false,
path: path.resolve(__dirname, 'build/'),
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
},
module: {
rules: [
{
test: /\.m?js/,
type: 'javascript/auto',
resolve: {
fullySpecified: false,
},
},
{
test: /\.css$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
],
},
{
test: /\.json$/,
loader: 'json-loader',
},
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
'style-loader',
// Translates CSS into CommonJS
'css-loader',
// Compiles Sass to CSS
'sass-loader',
],
},
{
test: /\.(woff(2)?|ttf|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/',
},
},
],
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'frontend_shell',
filename: 'remoteEntry.js',
remotes: {
store: 'store@http://localhost:8000/store/remoteEntry.js',
appOneRemote: 'appOneRemote@http://localhost:8000/appOneRemote/remoteEntry.js',
},
exposes: {
'./translate': './src/utility/i18n/translate.js',
'./useAllUserInfo': './src/hooks/useAllUserInfo.js',
'./useDarkMode': './src/hooks/useDarkMode.js',
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
eager: true,
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom'],
eager: true,
},
},
}),
new HtmlWebPackPlugin({
template: './public/index.html',
inject: 'body',
hash: true,
minify: true,
}),
new ESLintPlugin({
extensions: ['js', 'jsx'],
}),
],
};
App remote 1
module.exports = {
mode: 'production',
entry: './src/index',
cache: false,
devtool: false,
optimization: {
minimize: true,
},
output: {
publicPath: 'http://localhost:8000/appOneRemote/',
clean: true,
pathinfo: false,
path: path.resolve(__dirname, 'build/'),
},
resolve: {
extensions: ['.js', '.mjs', '.jsx', '.css'],
alias: {
events: 'events',
},
},
module: {
rules: [
{
test: /\.m?js/,
type: 'javascript/auto',
resolve: {
fullySpecified: false,
},
},
{
test: /\.css$/i,
use: [
'style-loader', 'css-loader',
],
},
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.svg$/,
use: ['@svgr/webpack'],
},
{
test: /\.json$/,
loader: 'json-loader',
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'appOneRemote',
filename: 'remoteEntry.js',
remotes: {
store: 'store@http://localhost:8000/store/remoteEntry.js',
shell: 'frontend_shell@http://localhost:8000/gui/shell/remoteEntry.js',
},
exposes: {
'./ManageUser': './src/pages/ManageUser/ManageUser.jsx',
},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
eager: true,
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom'],
eager: true,
},
},
}),
new HtmlWebPackPlugin({
template: './public/index.html',
}),
new ESLintPlugin({
extensions: ['js', 'jsx'],
}),
],
};
App remote 2
module.exports = {
mode: 'production',
entry: './src/index',
cache: false,
devtool: false,
optimization: {
minimize: true,
},
output: {
publicPath: 'http://localhost:8000/store/',
clean: true,
pathinfo: false,
path: path.resolve(__dirname, 'build/'),
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js', '.json'],
},
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',
},
},
{
test: /\.json$/,
loader: 'json-loader',
},
],
},
plugins: [
new ModuleFederationPlugin({
name: 'store',
filename: 'remoteEntry.js',
remotes: {},
exposes: { './store': './src/store' },
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
'react-dom': {
singleton: true,
requiredVersion: deps['react-dom'],
},
'react-redux': {
singleton: true,
},
},
}),
new HtmlWebPackPlugin({
template: './public/index.html',
}),
new ESLintPlugin({
extensions: ['js', 'jsx'],
}),
],
};
This is exactly what I get in the console: Warning:
Initialization of sharing external failed: ScriptExternalLoadError: Loading script failed.
(error: http://localhost:8000/appOneRemote/remoteEntry.js)
Warning:
Initialization of sharing external failed: ScriptExternalLoadError: Loading script failed.
(error: http://localhost:8000/store/remoteEntry.js)
Error:
Uncaught (in promise) ScriptExternalLoadError: Loading script failed.
(error: http://localhost:8000/store/remoteEntry.js)
while loading "./store" from 83878
at Object.83878 (main.js?1154643655f4125db28e:2:130241)
Also I can retrieve my shell remote entry here: http://localhost:8000/gui/shell/remoteEntry.js, but I got a 404 in the following: http://localhost:8000/store/remoteEntry.js http://localhost:8000/appOneRemote/remoteEntry.js
Any ideas?
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
