Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Webpack Module Federation #12284

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
21 changes: 21 additions & 0 deletions docusaurus/docs/webpack-module-federation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
id: webpack-module-federation
title: Webpack Module Federation
---

[Webpack Module Federation](https://webpack.js.org/concepts/module-federation) is a feature made available in Webpack 5.

## Configuring Webpack Module Federation
To get started, create `src/setupModuleFederation.js` and place the following contents in it:
```js
module.exports = {
name: 'test',
library: { type: 'var', name: 'test' },
filename: 'remoteEntry.js',
exposes: { '.': './src/App.js' }
}
```

You can now modify this configuration to suit your needs. [See here](https://webpack.js.org/plugins/module-federation-plugin#sharing-hints) for Module Federation Plugin's configuraiton options.

> **Note:** Since Micro-frontend apps do not typically have their own `index.html` (unless they're using iframes), the `index.html` file in the public folder is an optional file and can be removed if not applicable to your app.
1 change: 1 addition & 0 deletions docusaurus/website/sidebars.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
],
"Deployment": ["deployment"],
"Advanced Usage": [
"webpack-module-federation",
"custom-templates",
"can-i-use-decorators",
"pre-rendering-into-static-html-files",
Expand Down
3 changes: 3 additions & 0 deletions packages/react-scripts/config/paths.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ module.exports = {
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
mfSetup: resolveApp('src/setupModuleFederation.js'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
appWebpackCache: resolveApp('node_modules/.cache'),
Expand All @@ -97,6 +98,7 @@ module.exports = {
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
mfSetup: resolveApp('src/setupModuleFederation.js'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
appWebpackCache: resolveApp('node_modules/.cache'),
Expand Down Expand Up @@ -135,6 +137,7 @@ if (
appJsConfig: resolveOwn(`${templatePath}/jsconfig.json`),
yarnLockFile: resolveOwn(`${templatePath}/yarn.lock`),
testsSetup: resolveModule(resolveOwn, `${templatePath}/src/setupTests`),
mfSetup: resolveOwn(`${templatePath}/src/setupModuleFederation.js`),
proxySetup: resolveOwn(`${templatePath}/src/setupProxy.js`),
appNodeModules: resolveOwn('node_modules'),
appWebpackCache: resolveOwn('node_modules/.cache'),
Expand Down
63 changes: 34 additions & 29 deletions packages/react-scripts/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -605,43 +605,46 @@ module.exports = function (webpackEnv) {
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
fs.existsSync(paths.appHtml) &&
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
// https://github.com/facebook/create-react-app/issues/5358
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
shouldInlineRuntimeChunk &&
isEnvProduction &&
raspy8766 marked this conversation as resolved.
Show resolved Hide resolved
fs.existsSync(paths.appHtml) &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// It will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
fs.existsSync(paths.appHtml) &&
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
Expand Down Expand Up @@ -788,6 +791,8 @@ module.exports = function (webpackEnv) {
},
},
}),
fs.existsSync(paths.mfSetup) &&
new webpack.container.ModuleFederationPlugin(require(paths.mfSetup)),
].filter(Boolean),
// Turn off performance processing because we utilize
// our own hints via the FileSizeReporter
Expand Down
2 changes: 1 addition & 1 deletion packages/react-scripts/scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
const isInteractive = process.stdout.isTTY;

// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
if (!checkRequiredFiles([paths.appIndexJs])) {
process.exit(1);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/react-scripts/scripts/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;

// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
if (!checkRequiredFiles([paths.appIndexJs])) {
process.exit(1);
}

Expand Down