I am working on a React Webpack micro-frontend project using module federation. I am able to run the micro-frontend separately.
Host application is running on port http://localhost:3000/ and micro frontend application is running on http://localhost:3001. Images are on port 3001, and I added images in the 3001 component. On port http://localhost:3001, images are loading, but on the HOST app, images are getting 404 errors.
Expectation: All React components are in the MF app (http://localhost:3001/). I need to access all images from 3001.
If I add images to the 3000 port, then images are working fine. But I need images from port 3001.
HOST application webpack.config.js – HOST application port is: http://localhost:3000/
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const { webpack } = require('webpack');
const { ModuleFederationPlugin } = require('webpack').container;
const packageJson = require('./package.json');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
publicPath: '/'
},
devServer: {
port: 3000,
hot: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /.(?:js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react', '@babel/preset-env'],
plugins: ["@babel/plugin-transform-runtime", require.resolve('react-refresh/babel')]
}
}
},
{
test: /.(?:css|scss)$/,
include: path.resolve(__dirname, 'src'),
use: [
{ loader: "style-loader" },
{ loader: "css-loader", options: { sourceMap: true } },
{ loader: "postcss-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { sourceMap: true } },
],
},
{
test: /.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
limit: false,
},
},
],
},
{
test: /.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: false,
},
},
],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.scss', '.css'],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
new ReactRefreshWebpackPlugin(),
new ModuleFederationPlugin({
name: 'McmpCore',
filename: 'remoteEntry.js',
remotes: {
'supportPotal': 'McmpPortal@http://localhost:3001/remoteEntry.js'
},
shared: { ...packageJson.dependencies }
}),
],
}
Micro Frontend app webpack config and it’s port is (http://localhost:3001/)
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const { webpack } = require('webpack');
const { ModuleFederationPlugin } = require('webpack').container;
const packageJson = require('./package.json');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.tsx',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js',
},
devServer: {
port: 3001,
hot: true,
historyApiFallback: true,
},
module: {
rules: [
{
test: /.(?:js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-react', '@babel/preset-env', '@babel/preset-typescript'],
plugins: [
"@babel/plugin-transform-runtime",
require.resolve('react-refresh/babel')
]
}
}
},
{
test: /.(?:css|scss)$/,
include: path.resolve(__dirname, 'src'),
use: [
{ loader: "style-loader" },
{ loader: "css-loader", options: { sourceMap: true } },
{ loader: "postcss-loader", options: { sourceMap: true } },
{ loader: "sass-loader", options: { sourceMap: true } },
],
},
{
test: /.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
options: {
limit: false,
},
},
],
},
{
test: /.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: false,
},
},
],
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js', '.scss', '.css'],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
new ReactRefreshWebpackPlugin(),
new ModuleFederationPlugin({
name: 'McmpPortal',
filename: 'remoteEntry.js',
exposes: {
'./SupportPortal': './src/App.tsx',
},
shared: { ...packageJson.dependencies }
}),
],
}
Micro frontend component is where I added images
const Info = () => {
return (
<div className='home-info'>
<div className={`info left ${TW_CLASS.BOX_SHADOW} `}>
<div className='user-info'>
<div className='user-img'>
<img src={`/images/default.png`} className='shadow-md shadow-gray-400' />
</div>
<div>
<h4>John Doe</h4>
<p>Senior Technical Executive</p>
</div>
</div>
<div className='services'>
<h4 className='mb-3.5'>Active Services</h4>
<div className='grid grid-cols-2 gap-4'>
<div className='active-services'>
<div>
<p><strong>Consulting Services</strong></p>
<p>Expiry Date: 12 Dec 2024</p>
</div>
<div>
<p><strong>Azure Managed Services - Gold</strong></p>
<p>Expiry Date: 12 Dec 2024</p>
</div>
<div>
<p><strong>Azure Managed Services - Platinum</strong></p>
<p>Expiry Date: 12 Dec 2024</p>
</div>
</div>
<div className='service-information-cards'>
<h6>SLA</h6>
<ul>
<li>Scope of Services to be covered</li>
<li>Perfomance metrics</li>
<li>Penalities for contact breach</li>
<li>Customer responsibilities</li>
<li>Service provide responsibilities</li>
</ul>
</div>
</div>
</div>
</div>
<div className={`info right ${TW_CLASS.BOX_SHADOW} `}>
<h4>Support Portal</h4>
<p>Text</p>
</div>
</div>
)
}
Noventiq is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.