diff --git a/docusaurus/docs/module-federation.md b/docusaurus/docs/module-federation.md new file mode 100644 index 00000000000..2ec1cdb29e4 --- /dev/null +++ b/docusaurus/docs/module-federation.md @@ -0,0 +1,45 @@ +--- +id: module-federation +title: Module Federation +--- + +**EXPERIMENTAL!** This is feature is subject to change as we evaluate and gather feedback + +Module federation enables an application to expose a module to be consumed by itself or other applications. + +To enable module federation in a create react app add either a *.modulefederationrc.json* or *.modulefederationrc.js* in the root folder - depending on how dynamic the config needs to be. + +The configuration is simply passed to the `ModuleFederationPlugin` [Read more about the configuration](https://webpack.js.org/concepts/module-federation/#modulefederationplugin-high-level) or [Find examples on module-federation](https://github.com/module-federation/module-federation-examples#module-federation-examples) + +Examples: + +App 1 +```json +// .modulefederationrc.json +{ + "name": "app1", + "remotes": { + "app2": "app2@http://localhost:3002/remoteEntry.js" + }, + "shared": ["react", "react-dom"] +} +``` + +App 2 +```js +// .modulefederationrc.js +module.exports = { + name: "app2", + filename: "remoteEntry.js", + exposes: { + "./Button": "./src/Button" + }, + shared: ["react", "react-dom"], +}; +``` + +Note: +Currently there is not a template for creating an app with federated modules, but rename eg. the `index.js` to `bootstrap.js` and add a new `index.js` with the following code: +```js +import("./bootstrap"); +``` \ No newline at end of file diff --git a/docusaurus/website/sidebars.json b/docusaurus/website/sidebars.json index 386a29da1bf..5ee0d8c91af 100644 --- a/docusaurus/website/sidebars.json +++ b/docusaurus/website/sidebars.json @@ -52,6 +52,7 @@ "can-i-use-decorators", "pre-rendering-into-static-html-files", "advanced-configuration", + "module-federation", "alternatives-to-ejecting" ], "Support": ["troubleshooting"] diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index f4470a02f63..9fbb19ccf2d 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -45,6 +45,8 @@ const moduleFileExtensions = [ 'jsx', ]; +const moduleFederationConfigFiles = ['.modulefederationrc.json', '.modulefederationrc.js']; + // Resolve file paths in the same order as webpack const resolveModule = (resolveFn, filePath) => { const extension = moduleFileExtensions.find(extension => @@ -76,6 +78,10 @@ module.exports = { appNodeModules: resolveApp('node_modules'), appWebpackCache: resolveApp('node_modules/.cache'), appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'), + appMFConfigFile: moduleFederationConfigFiles + .map(resolveApp) + .filter(fs.existsSync) + .shift(), swSrc: resolveModule(resolveApp, 'src/service-worker'), publicUrlOrPath, }; @@ -101,6 +107,10 @@ module.exports = { appNodeModules: resolveApp('node_modules'), appWebpackCache: resolveApp('node_modules/.cache'), appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'), + appMFConfigFile: moduleFederationConfigFiles + .map(resolveApp) + .filter(fs.existsSync) + .shift(), swSrc: resolveModule(resolveApp, 'src/service-worker'), publicUrlOrPath, // These properties only exist before ejecting: @@ -139,6 +149,11 @@ if ( appNodeModules: resolveOwn('node_modules'), appWebpackCache: resolveOwn('node_modules/.cache'), appTsBuildInfoFile: resolveOwn('node_modules/.cache/tsconfig.tsbuildinfo'), + appMFConfigFile: moduleFederationConfigFiles + .map(p => `${templatePath}/${p}`) + .map(resolveOwn) + .filter(fs.existsSync) + .shift(), swSrc: resolveModule(resolveOwn, `${templatePath}/src/service-worker`), publicUrlOrPath, // These properties only exist before ejecting: diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 5a76510c2d5..491e3978559 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -795,6 +795,10 @@ module.exports = function (webpackEnv) { }, }, }), + paths.appMFConfigFile && + new webpack.container.ModuleFederationPlugin( + require(paths.appMFConfigFile) + ), ].filter(Boolean), // Turn off performance processing because we utilize // our own hints via the FileSizeReporter