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/create-react-app/yarn.lock.cached b/packages/create-react-app/yarn.lock.cached index 18a5289f7dc..f79b7af4ef4 100644 --- a/packages/create-react-app/yarn.lock.cached +++ b/packages/create-react-app/yarn.lock.cached @@ -1270,6 +1270,20 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== +"@humanwhocodes/config-array@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.5.0.tgz#1407967d4c6eecd7388f83acf1eaf4d0c6e58ef9" + integrity sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg== + dependencies: + "@humanwhocodes/object-schema" "^1.2.0" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/object-schema@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz#87de7af9c231826fdd68ac7258f77c429e0e5fcf" + integrity sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -4105,7 +4119,7 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== @@ -4597,9 +4611,10 @@ internal-slot@^1.0.3: resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" + default-gateway "^6.0.0" + ipaddr.js "^1.9.1" + is-ip "^3.1.0" + p-event "^4.2.0" ip-regex@^4.0.0: version "4.3.0" diff --git a/packages/eslint-config-react-app/index.js b/packages/eslint-config-react-app/index.js index 603a68b0201..c727e66b2bf 100644 --- a/packages/eslint-config-react-app/index.js +++ b/packages/eslint-config-react-app/index.js @@ -7,6 +7,8 @@ 'use strict'; +require('./patch'); + // Inspired by https://github.com/airbnb/javascript but less opinionated. // We use eslint-loader so even warnings are very visible. diff --git a/packages/eslint-config-react-app/package.json b/packages/eslint-config-react-app/package.json index 1f9c9eea0cb..dfd73a919de 100644 --- a/packages/eslint-config-react-app/package.json +++ b/packages/eslint-config-react-app/package.json @@ -14,7 +14,8 @@ "files": [ "base.js", "index.js", - "jest.js" + "jest.js", + "patch.js" ], "peerDependencies": { "eslint": "^7.30.0" diff --git a/packages/eslint-config-react-app/patch.js b/packages/eslint-config-react-app/patch.js new file mode 100644 index 00000000000..7e37ebc86a0 --- /dev/null +++ b/packages/eslint-config-react-app/patch.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +// Fix eslint shareable config (https://github.com/eslint/eslint/issues/3458) +require('@rushstack/eslint-patch/modern-module-resolution'); diff --git a/packages/react-scripts/config/paths.js b/packages/react-scripts/config/paths.js index f4470a02f63..b2ac89593a7 100644 --- a/packages/react-scripts/config/paths.js +++ b/packages/react-scripts/config/paths.js @@ -45,6 +45,10 @@ const moduleFileExtensions = [ 'jsx', ]; +const moduleFederationConfigFiles = [ + 'modulefederation.config.js', +]; + // Resolve file paths in the same order as webpack const resolveModule = (resolveFn, filePath) => { const extension = moduleFileExtensions.find(extension => @@ -73,6 +77,10 @@ module.exports = { yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveModule(resolveApp, 'src/setupTests'), proxySetup: resolveApp('src/setupProxy.js'), + appMFConfigFile: moduleFederationConfigFiles + .map(resolveApp) + .filter(fs.existsSync) + .shift(), appNodeModules: resolveApp('node_modules'), appWebpackCache: resolveApp('node_modules/.cache'), appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'), @@ -98,6 +106,10 @@ module.exports = { yarnLockFile: resolveApp('yarn.lock'), testsSetup: resolveModule(resolveApp, 'src/setupTests'), proxySetup: resolveApp('src/setupProxy.js'), + appMFConfigFile: moduleFederationConfigFiles + .map(resolveApp) + .filter(fs.existsSync) + .shift(), appNodeModules: resolveApp('node_modules'), appWebpackCache: resolveApp('node_modules/.cache'), appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'), @@ -136,6 +148,11 @@ if ( yarnLockFile: resolveOwn(`${templatePath}/yarn.lock`), testsSetup: resolveModule(resolveOwn, `${templatePath}/src/setupTests`), proxySetup: resolveOwn(`${templatePath}/src/setupProxy.js`), + appMFConfigFile: moduleFederationConfigFiles + .map(p => `${templatePath}/${p}`) + .map(resolveOwn) + .filter(fs.existsSync) + .shift(), appNodeModules: resolveOwn('node_modules'), appWebpackCache: resolveOwn('node_modules/.cache'), appTsBuildInfoFile: resolveOwn('node_modules/.cache/tsconfig.tsbuildinfo'), diff --git a/packages/react-scripts/config/webpack.config.js b/packages/react-scripts/config/webpack.config.js index 6bc8b2cee11..251bb0ce5ab 100644 --- a/packages/react-scripts/config/webpack.config.js +++ b/packages/react-scripts/config/webpack.config.js @@ -38,6 +38,8 @@ const getCacheIdentifier = require('react-dev-utils/getCacheIdentifier'); // @remove-on-eject-end const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash'); +const ExternalTemplateRemotesPlugin = require('external-remotes-plugin'); + // Source maps are resource heavy and can cause out of memory issue for large source files. const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false'; @@ -58,6 +60,9 @@ const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false'; const emitErrorsAsWarnings = process.env.ESLINT_NO_DEV_ERRORS === 'true'; const disableESLintPlugin = process.env.DISABLE_ESLINT_PLUGIN === 'true'; +const shouldUseExternalTemplateRemotesPlugin = + process.env.EXTERNAL_TEMPLATE_REMOTES === 'true'; + const imageInlineSizeLimit = parseInt( process.env.IMAGE_INLINE_SIZE_LIMIT || '10000' ); @@ -201,10 +206,7 @@ module.exports = function (webpackEnv) { ? 'static/js/[name].[contenthash:8].chunk.js' : isEnvDevelopment && 'static/js/[name].chunk.js', assetModuleFilename: 'static/media/[name].[hash][ext]', - // webpack uses `publicPath` to determine where the app is being served from. - // It requires a trailing slash, or the file assets will get an incorrect path. - // We inferred the "public path" (such as / or /my-project) from homepage. - publicPath: paths.publicUrlOrPath, + publicPath: 'auto', // Point sourcemap entries to original disk location (format as URL on Windows) devtoolModuleFilenameTemplate: isEnvProduction ? info => @@ -322,6 +324,11 @@ module.exports = function (webpackEnv) { ], }, module: { + generator: { + 'asset/resource': { + publicPath: paths.publicUrlOrPath, + }, + }, strictExportPresence: true, rules: [ // Handle node_modules packages that contain sourcemaps @@ -586,7 +593,13 @@ module.exports = function (webpackEnv) { { inject: true, template: paths.appHtml, + publicPath: paths.publicUrlOrPath, }, + paths.appMFConfigFile + ? { + excludeChunks: [require(paths.appMFConfigFile).name], + } + : undefined, isEnvProduction ? { minify: { @@ -763,6 +776,13 @@ module.exports = function (webpackEnv) { }, }, }), + paths.appMFConfigFile && + new webpack.container.ModuleFederationPlugin( + require(paths.appMFConfigFile) + ), + paths.appMFConfigFile && + shouldUseExternalTemplateRemotesPlugin && + new ExternalTemplateRemotesPlugin(), ].filter(Boolean), // Turn off performance processing because we utilize // our own hints via the FileSizeReporter diff --git a/packages/react-scripts/package.json b/packages/react-scripts/package.json index e3a876e1673..97dc00247fa 100644 --- a/packages/react-scripts/package.json +++ b/packages/react-scripts/package.json @@ -46,6 +46,7 @@ "eslint": "^7.30.0", "eslint-config-react-app": "^6.0.0", "eslint-webpack-plugin": "^2.5.4", + "external-remotes-plugin": "^1.0.0", "file-loader": "^6.2.0", "fs-extra": "^10.0.0", "html-webpack-plugin": "5.3.2",