Skip to content

Instantly share code, notes, and snippets.

@kziemski
Forked from marcosmapf/webpack.production.js
Created October 24, 2025 21:16
Show Gist options
  • Save kziemski/8d46251727243c86ac4d7428e0da9e39 to your computer and use it in GitHub Desktop.
Save kziemski/8d46251727243c86ac4d7428e0da9e39 to your computer and use it in GitHub Desktop.
Webpack configuration that enables App usage inside Shadow Dom and as a Module Federation
/*
* Webpack bundle configuration that enables project export as UMD library and Module Federated container
*
* Custom styleTagTransform script is defined at https://gist.github.com/marcosmapf/904986dde911148e39a17a59dc3dd132
* The 'from' option attribute is used inside styleTagTransform as a reference to the project's root element
*/
const { join } = require('path')
const { container, EnvironmentPlugin } = require('webpack')
const ModuleFederationPlugin = container.ModuleFederationPlugin
const { PATHS } = require('../constants.js')
const common = require('../webpack.common.js')
const pkjson = require(join(PATHS.ROOT, 'package.json'))
require('dotenv').config({
path: join(PATHS.ENV, `/.${process.env.NODE_ENV}`)
})
const isDevelopment = process.env.NODE_ENV === 'development'
const environmentVars = [
'variablesHere'
]
module.exports = {
entry: join(PATHS.STARTUP, 'umd', './index.tsx'),
mode: 'production',
output: {
filename: 'bundle.js',
chunkFilename: '[contenthash].[name].bundle.js',
library: '@enterprise/app-name',
libraryTarget: 'umd',
path: PATHS.BUILD,
},
resolve: {
extensions: ['.js', '.ts', '.tsx', '.json'],
alias: {
'@cosmos': PATHS.COSMOS,
'assets': PATHS.ASSETS,
'components': PATHS.COMPONENTS,
'config': PATHS.CONFIG,
'hooks': PATHS.HOOKS,
'languages': PATHS.LANGUAGES,
'pages': PATHS.PAGES,
'root': PATHS.ROOT,
'startup': PATHS.STARTUP,
'typings': PATHS.TYPINGS,
'utils': PATHS.UTILS,
},
fallback: {
path: false,
fs: false,
url: false
}
},
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
loader: 'ts-loader',
options: {
compilerOptions: {
noEmit: false
}
}
},
{
test: /\.(s?)css$/,
use: [
{
loader: `${PATHS.CUSTOM_SCRIPTS}/style-loader`, // Irrelevant for most projects, you can probably use style-loader directly
options: {
attributes: { from: process.env.PROJECT_NAME },
styleTagTransform: `${PATHS.CUSTOM_SCRIPTS}/styleTagTransform`
}
},
'css-loader',
'postcss-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|gif|ico)$/,
loader: 'asset/resource',
},
{
test: /\.svg$/,
use: ['@svgr/webpack'],
}
]
},
plugins: [
new EnvironmentPlugin(environmentVars),
new ModuleFederationPlugin({
name: 'app_1', // Name of the current app, considered the host project
filename: 'remoteEntry.js',
exposes: {
'./Main': join(PATHS.STARTUP, 'module-federation/index.tsx'), // exposed module name
},
remotes: {
App2: 'app_2@http://app-uri.com/remoteEntry.js'
},
shared: {
react: {
requiredVersion: pkjson.dependencies.react,
},
'react-dom': {
requiredVersion: pkjson.dependencies['react-dom'],
},
'react-router-dom': {
requiredVersion: pkjson.dependencies['react-router-dom'],
},
},
}),
],
optimization: {
splitChunks: {
chunks: 'async',
maxAsyncRequests: 30,
maxInitialRequests: 30,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
chunks: 'async',
filename: '[contenthash].vendors.bundle.js',
},
},
},
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment