From 9b8e986f7c1d5447d06460afba28c3c9a58fee86 Mon Sep 17 00:00:00 2001 From: Josh Story Date: Tue, 8 Aug 2023 20:57:09 -0700 Subject: [PATCH] more generic forks can now match when a specific renderer match is not found. for instance `File.dom` can match when using renderer `"dom-node"` if `File.dom-node` does not exist. This change also splits the browser and node builds for react-server-dom-esm into two separate renderers. There is not a `"dom-browser-esm"` renderer. This change should alter no semantics. It does however set us up to support more complex and varied renderer configs in future updates and generally lowers the effort to spin up additional configs. --- ...ReactFlightClientConfig.dom-browser-esm.js | 13 + .../ReactFlightClientConfig.dom-node-esm.js | 1 - .../src/forks/ReactFiberConfig.dom-bun.js | 10 - .../ReactFiberConfig.dom-edge-webpack.js | 10 - .../src/forks/ReactFiberConfig.dom-fb.js | 10 - .../src/forks/ReactFiberConfig.dom-legacy.js | 10 - .../forks/ReactFiberConfig.dom-node-esm.js | 10 - .../ReactFiberConfig.dom-node-webpack.js | 10 - .../src/forks/ReactFiberConfig.dom-node.js | 10 - ...dom-browser.js => ReactFiberConfig.dom.js} | 0 .../src/forks/ReactFizzConfig.dom-bun.js | 14 - ...webpack.js => ReactFizzConfig.dom-edge.js} | 0 .../src/forks/ReactFizzConfig.dom-fb.js | 14 - .../src/forks/ReactFizzConfig.dom-node-esm.js | 17 - .../forks/ReactFizzConfig.dom-node-webpack.js | 17 - ....dom-browser.js => ReactFizzConfig.dom.js} | 0 ...eactFlightServerConfig.dom-browser-esm.js} | 2 +- ...js => ReactFlightServerConfig.dom-edge.js} | 0 ...js => ReactServerStreamConfig.dom-edge.js} | 0 .../ReactServerStreamConfig.dom-node-esm.js | 10 - ...eactServerStreamConfig.dom-node-webpack.js | 10 - scripts/flow/createFlowConfigs.js | 76 +++-- scripts/jest/setupHostConfigs.js | 16 +- scripts/rollup/build.js | 291 +++++++++--------- scripts/rollup/forks.js | 86 +++++- scripts/shared/inlinedHostConfigs.js | 24 +- 26 files changed, 340 insertions(+), 321 deletions(-) create mode 100644 packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-bun.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-edge-webpack.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-fb.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-legacy.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-esm.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-webpack.js delete mode 100644 packages/react-reconciler/src/forks/ReactFiberConfig.dom-node.js rename packages/react-reconciler/src/forks/{ReactFiberConfig.dom-browser.js => ReactFiberConfig.dom.js} (100%) delete mode 100644 packages/react-server/src/forks/ReactFizzConfig.dom-bun.js rename packages/react-server/src/forks/{ReactFizzConfig.dom-edge-webpack.js => ReactFizzConfig.dom-edge.js} (100%) delete mode 100644 packages/react-server/src/forks/ReactFizzConfig.dom-fb.js delete mode 100644 packages/react-server/src/forks/ReactFizzConfig.dom-node-esm.js delete mode 100644 packages/react-server/src/forks/ReactFizzConfig.dom-node-webpack.js rename packages/react-server/src/forks/{ReactFizzConfig.dom-browser.js => ReactFizzConfig.dom.js} (100%) rename packages/react-server/src/forks/{ReactFlightServerConfig.dom-node-webpack.js => ReactFlightServerConfig.dom-browser-esm.js} (86%) rename packages/react-server/src/forks/{ReactFlightServerConfig.dom-edge-webpack.js => ReactFlightServerConfig.dom-edge.js} (100%) rename packages/react-server/src/forks/{ReactServerStreamConfig.dom-edge-webpack.js => ReactServerStreamConfig.dom-edge.js} (100%) delete mode 100644 packages/react-server/src/forks/ReactServerStreamConfig.dom-node-esm.js delete mode 100644 packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webpack.js diff --git a/packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js b/packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js new file mode 100644 index 0000000000000..53058d0d18841 --- /dev/null +++ b/packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export * from 'react-client/src/ReactFlightClientConfigBrowser'; +export * from 'react-server-dom-esm/src/ReactFlightClientConfigESMBundler'; +export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM'; +export const usedWithSSR = false; diff --git a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js b/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js index a4a68b8773170..8390c4c06b439 100644 --- a/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js +++ b/packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js @@ -7,7 +7,6 @@ * @flow */ -// This should really have a Node and a Browser fork but to avoid too many configs we limit this to build the same for both export * from 'react-client/src/ReactFlightClientConfigBrowser'; export * from 'react-server-dom-esm/src/ReactFlightClientConfigESMBundler'; export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-bun.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-bun.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-bun.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-edge-webpack.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-edge-webpack.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-edge-webpack.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-fb.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-fb.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-fb.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-legacy.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-legacy.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-legacy.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-esm.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-esm.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-esm.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-webpack.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-webpack.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-webpack.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node.js deleted file mode 100644 index 4932b1a787bb9..0000000000000 --- a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-node.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM'; diff --git a/packages/react-reconciler/src/forks/ReactFiberConfig.dom-browser.js b/packages/react-reconciler/src/forks/ReactFiberConfig.dom.js similarity index 100% rename from packages/react-reconciler/src/forks/ReactFiberConfig.dom-browser.js rename to packages/react-reconciler/src/forks/ReactFiberConfig.dom.js diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-bun.js b/packages/react-server/src/forks/ReactFizzConfig.dom-bun.js deleted file mode 100644 index 5f887770d211e..0000000000000 --- a/packages/react-server/src/forks/ReactFizzConfig.dom-bun.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ -import type {Request} from 'react-server/src/ReactFizzServer'; - -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM'; - -export const supportsRequestStorage = false; -export const requestStorage: AsyncLocalStorage = (null: any); diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-edge-webpack.js b/packages/react-server/src/forks/ReactFizzConfig.dom-edge.js similarity index 100% rename from packages/react-server/src/forks/ReactFizzConfig.dom-edge-webpack.js rename to packages/react-server/src/forks/ReactFizzConfig.dom-edge.js diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-fb.js b/packages/react-server/src/forks/ReactFizzConfig.dom-fb.js deleted file mode 100644 index 5f887770d211e..0000000000000 --- a/packages/react-server/src/forks/ReactFizzConfig.dom-fb.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ -import type {Request} from 'react-server/src/ReactFizzServer'; - -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM'; - -export const supportsRequestStorage = false; -export const requestStorage: AsyncLocalStorage = (null: any); diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-node-esm.js b/packages/react-server/src/forks/ReactFizzConfig.dom-node-esm.js deleted file mode 100644 index 71c6ab5a5586c..0000000000000 --- a/packages/react-server/src/forks/ReactFizzConfig.dom-node-esm.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ -import {AsyncLocalStorage} from 'async_hooks'; - -import type {Request} from 'react-server/src/ReactFizzServer'; - -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM'; - -export const supportsRequestStorage = true; -export const requestStorage: AsyncLocalStorage = - new AsyncLocalStorage(); diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-node-webpack.js b/packages/react-server/src/forks/ReactFizzConfig.dom-node-webpack.js deleted file mode 100644 index 71c6ab5a5586c..0000000000000 --- a/packages/react-server/src/forks/ReactFizzConfig.dom-node-webpack.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ -import {AsyncLocalStorage} from 'async_hooks'; - -import type {Request} from 'react-server/src/ReactFizzServer'; - -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM'; - -export const supportsRequestStorage = true; -export const requestStorage: AsyncLocalStorage = - new AsyncLocalStorage(); diff --git a/packages/react-server/src/forks/ReactFizzConfig.dom-browser.js b/packages/react-server/src/forks/ReactFizzConfig.dom.js similarity index 100% rename from packages/react-server/src/forks/ReactFizzConfig.dom-browser.js rename to packages/react-server/src/forks/ReactFizzConfig.dom.js diff --git a/packages/react-server/src/forks/ReactFlightServerConfig.dom-node-webpack.js b/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-esm.js similarity index 86% rename from packages/react-server/src/forks/ReactFlightServerConfig.dom-node-webpack.js rename to packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-esm.js index 10d36f14a93eb..d52bf8ad7451e 100644 --- a/packages/react-server/src/forks/ReactFlightServerConfig.dom-node-webpack.js +++ b/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-esm.js @@ -10,7 +10,7 @@ import {AsyncLocalStorage} from 'async_hooks'; import type {Request} from 'react-server/src/ReactFlightServer'; -export * from 'react-server-dom-webpack/src/ReactFlightServerConfigWebpackBundler'; +export * from 'react-server-dom-esm/src/ReactFlightServerConfigESMBundler'; export * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM'; export const supportsRequestStorage = true; diff --git a/packages/react-server/src/forks/ReactFlightServerConfig.dom-edge-webpack.js b/packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js similarity index 100% rename from packages/react-server/src/forks/ReactFlightServerConfig.dom-edge-webpack.js rename to packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js diff --git a/packages/react-server/src/forks/ReactServerStreamConfig.dom-edge-webpack.js b/packages/react-server/src/forks/ReactServerStreamConfig.dom-edge.js similarity index 100% rename from packages/react-server/src/forks/ReactServerStreamConfig.dom-edge-webpack.js rename to packages/react-server/src/forks/ReactServerStreamConfig.dom-edge.js diff --git a/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-esm.js b/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-esm.js deleted file mode 100644 index 1a3871aef2e8b..0000000000000 --- a/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-esm.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from '../ReactServerStreamConfigNode'; diff --git a/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webpack.js b/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webpack.js deleted file mode 100644 index 1a3871aef2e8b..0000000000000 --- a/packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webpack.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow - */ - -export * from '../ReactServerStreamConfigNode'; diff --git a/scripts/flow/createFlowConfigs.js b/scripts/flow/createFlowConfigs.js index 8a7c22b6d337c..cb4a89b5d95e3 100644 --- a/scripts/flow/createFlowConfigs.js +++ b/scripts/flow/createFlowConfigs.js @@ -9,6 +9,7 @@ const chalk = require('chalk'); const fs = require('fs'); +const path = require('path'); const mkdirp = require('mkdirp'); const inlinedHostConfigs = require('../shared/inlinedHostConfigs'); @@ -16,6 +17,40 @@ const configTemplate = fs .readFileSync(__dirname + '/config/flowconfig') .toString(); +// stores all forks discovered during config generation +const allForks = new Set(); +// maps forked file to the base path containing it and it's forks (it's parent) +const forkedFiles = new Map(); + +function findForks(file) { + const basePath = path.join(file, '..'); + const forksPath = path.join(basePath, 'forks'); + const forks = fs.readdirSync(path.join('packages', forksPath)); + forks.forEach(f => allForks.add('forks/' + f)); + forkedFiles.set(file, basePath); + return basePath; +} + +function addFork(forks, renderer, file) { + let basePath = forkedFiles.get(file); + if (!basePath) { + basePath = findForks(file); + } + + const baseFilename = file.slice(basePath.length + 1); + + const parts = renderer.split('-'); + while (parts.length) { + const candidate = `forks/${baseFilename}.${parts.join('-')}.js`; + if (allForks.has(candidate)) { + forks.set(candidate, `${baseFilename}$$`); + return; + } + parts.pop(); + } + throw new Error(`Cannot find fork for ${file} for renderer ${renderer}`); +} + function writeConfig( renderer, rendererInfo, @@ -44,34 +79,39 @@ function writeConfig( } ignoredPaths.push(`.*/packages/${otherPath}`); }); + }); + + const forks = new Map(); + addFork(forks, renderer, 'react-reconciler/src/ReactFiberConfig'); + addFork(forks, serverRenderer, 'react-server/src/ReactServerStreamConfig'); + addFork(forks, serverRenderer, 'react-server/src/ReactFizzConfig'); + addFork(forks, flightRenderer, 'react-server/src/ReactFlightServerConfig'); + addFork(forks, flightRenderer, 'react-client/src/ReactFlightClientConfig'); + forks.set( + 'react-devtools-shared/src/config/DevToolsFeatureFlags.default', + 'react-devtools-feature-flags', + ); - if ( - otherRenderer.shortName !== serverRenderer && - otherRenderer.shortName !== flightRenderer - ) { - ignoredPaths.push( - `.*/packages/.*/forks/.*\\.${otherRenderer.shortName}.js`, - ); + allForks.forEach(fork => { + if (!forks.has(fork)) { + ignoredPaths.push(`.*/packages/.*/${fork}`); } }); + let moduleMappings = ''; + forks.forEach((source, target) => { + moduleMappings += `module.name_mapper='${source.slice( + source.lastIndexOf('/') + 1, + )}' -> '${target}'\n`; + }); + const config = configTemplate .replace( '%CI_MAX_WORKERS%\n', // On CI, we seem to need to limit workers. process.env.CI ? 'server.max_workers=4\n' : '', ) - .replace( - '%REACT_RENDERER_FLOW_OPTIONS%', - ` -module.name_mapper='ReactFiberConfig$$' -> 'forks/ReactFiberConfig.${renderer}' -module.name_mapper='ReactServerStreamConfig$$' -> 'forks/ReactServerStreamConfig.${serverRenderer}' -module.name_mapper='ReactFizzConfig$$' -> 'forks/ReactFizzConfig.${serverRenderer}' -module.name_mapper='ReactFlightServerConfig$$' -> 'forks/ReactFlightServerConfig.${flightRenderer}' -module.name_mapper='ReactFlightClientConfig$$' -> 'forks/ReactFlightClientConfig.${flightRenderer}' -module.name_mapper='react-devtools-feature-flags' -> 'react-devtools-shared/src/config/DevToolsFeatureFlags.default' - `.trim(), - ) + .replace('%REACT_RENDERER_FLOW_OPTIONS%', moduleMappings.trim()) .replace('%REACT_RENDERER_FLOW_IGNORES%', ignoredPaths.join('\n')); const disclaimer = ` diff --git a/scripts/jest/setupHostConfigs.js b/scripts/jest/setupHostConfigs.js index 85fe96cd2ac06..5ea6eb0f5810d 100644 --- a/scripts/jest/setupHostConfigs.js +++ b/scripts/jest/setupHostConfigs.js @@ -1,6 +1,7 @@ 'use strict'; const fs = require('fs'); +const nodePath = require('path'); const inlinedHostConfigs = require('../shared/inlinedHostConfigs'); function resolveEntryFork(resolvedEntry, isFBBundle) { @@ -117,7 +118,20 @@ function mockAllConfigs(rendererInfo) { jest.mock(path, () => { let idx = path.lastIndexOf('/'); let forkPath = path.slice(0, idx) + '/forks' + path.slice(idx); - return jest.requireActual(`${forkPath}.${rendererInfo.shortName}.js`); + let parts = rendererInfo.shortName.split('-'); + while (parts.length) { + try { + const candidate = `${forkPath}.${parts.join('-')}.js`; + fs.statSync(nodePath.join(process.cwd(), 'packages', candidate)); + return jest.requireActual(candidate); + } catch (error) { + // try without a part + } + parts.pop(); + } + throw new Error( + `Expected to find a fork for ${path} but did not find one.` + ); }); }); } diff --git a/scripts/rollup/build.js b/scripts/rollup/build.js index 6e6384aba66f8..fe0158a9a477d 100644 --- a/scripts/rollup/build.js +++ b/scripts/rollup/build.js @@ -341,153 +341,162 @@ function getPlugins( pureExternalModules, bundle ) { - const forks = Modules.getForks(bundleType, entry, moduleType, bundle); - const isProduction = isProductionBundleType(bundleType); - const isProfiling = isProfilingBundleType(bundleType); - const isUMDBundle = - bundleType === UMD_DEV || - bundleType === UMD_PROD || - bundleType === UMD_PROFILING; - const isFBWWWBundle = - bundleType === FB_WWW_DEV || - bundleType === FB_WWW_PROD || - bundleType === FB_WWW_PROFILING; - const isRNBundle = - bundleType === RN_OSS_DEV || - bundleType === RN_OSS_PROD || - bundleType === RN_OSS_PROFILING || - bundleType === RN_FB_DEV || - bundleType === RN_FB_PROD || - bundleType === RN_FB_PROFILING; - const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput; - return [ - // Keep dynamic imports as externals - dynamicImports(), - { - name: 'rollup-plugin-flow-remove-types', - transform(code) { - const transformed = flowRemoveTypes(code); - return { - code: transformed.toString(), - map: transformed.generateMap(), - }; - }, - }, - // Shim any modules that need forking in this environment. - useForks(forks), - // Ensure we don't try to bundle any fbjs modules. - forbidFBJSImports(), - // Use Node resolution mechanism. - resolve({ - // skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0 - }), - // Remove license headers from individual modules - stripBanner({ - exclude: 'node_modules/**/*', - }), - // Compile to ES2015. - babel( - getBabelConfig( - updateBabelOptions, - bundleType, - packageName, - externals, - !isProduction, - bundle - ) - ), - // Remove 'use strict' from individual source files. - { - transform(source) { - return source.replace(/['"]use strict["']/g, ''); - }, - }, - // Turn __DEV__ and process.env checks into constants. - replace({ - preventAssignment: true, - values: { - __DEV__: isProduction ? 'false' : 'true', - __PROFILE__: isProfiling || !isProduction ? 'true' : 'false', - __UMD__: isUMDBundle ? 'true' : 'false', - 'process.env.NODE_ENV': isProduction ? "'production'" : "'development'", - __EXPERIMENTAL__, + try { + const forks = Modules.getForks(bundleType, entry, moduleType, bundle); + const isProduction = isProductionBundleType(bundleType); + const isProfiling = isProfilingBundleType(bundleType); + const isUMDBundle = + bundleType === UMD_DEV || + bundleType === UMD_PROD || + bundleType === UMD_PROFILING; + const isFBWWWBundle = + bundleType === FB_WWW_DEV || + bundleType === FB_WWW_PROD || + bundleType === FB_WWW_PROFILING; + const isRNBundle = + bundleType === RN_OSS_DEV || + bundleType === RN_OSS_PROD || + bundleType === RN_OSS_PROFILING || + bundleType === RN_FB_DEV || + bundleType === RN_FB_PROD || + bundleType === RN_FB_PROFILING; + const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput; + return [ + // Keep dynamic imports as externals + dynamicImports(), + { + name: 'rollup-plugin-flow-remove-types', + transform(code) { + const transformed = flowRemoveTypes(code); + return { + code: transformed.toString(), + map: transformed.generateMap(), + }; + }, }, - }), - // The CommonJS plugin *only* exists to pull "art" into "react-art". - // I'm going to port "art" to ES modules to avoid this problem. - // Please don't enable this for anything else! - isUMDBundle && entry === 'react-art' && commonjs(), - // Apply dead code elimination and/or minification. - // closure doesn't yet support leaving ESM imports intact - isProduction && - bundleType !== ESM_PROD && - closure({ - compilation_level: 'SIMPLE', - language_in: 'ECMASCRIPT_2020', - language_out: - bundleType === NODE_ES2015 - ? 'ECMASCRIPT_2020' - : bundleType === BROWSER_SCRIPT - ? 'ECMASCRIPT5' - : 'ECMASCRIPT5_STRICT', - emit_use_strict: - bundleType !== BROWSER_SCRIPT && - bundleType !== ESM_PROD && - bundleType !== ESM_DEV, - env: 'CUSTOM', - warning_level: 'QUIET', - apply_input_source_maps: false, - use_types_for_optimization: false, - process_common_js_modules: false, - rewrite_polyfills: false, - inject_libraries: false, - allow_dynamic_import: true, - - // Don't let it create global variables in the browser. - // https://github.com/facebook/react/issues/10909 - assume_function_wrapper: !isUMDBundle, - renaming: !shouldStayReadable, + // Shim any modules that need forking in this environment. + useForks(forks), + // Ensure we don't try to bundle any fbjs modules. + forbidFBJSImports(), + // Use Node resolution mechanism. + resolve({ + // skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0 }), - // Add the whitespace back if necessary. - shouldStayReadable && - prettier({ - parser: 'flow', - singleQuote: false, - trailingComma: 'none', - bracketSpacing: true, + // Remove license headers from individual modules + stripBanner({ + exclude: 'node_modules/**/*', }), - // License and haste headers, top-level `if` blocks. - { - renderChunk(source) { - return Wrappers.wrapBundle( - source, - bundleType, - globalName, - filename, - moduleType, - bundle.wrapWithModuleBoundaries - ); - }, - }, - // Record bundle size. - sizes({ - getSize: (size, gzip) => { - const currentSizes = Stats.currentBuildResults.bundleSizes; - const recordIndex = currentSizes.findIndex( - record => - record.filename === filename && record.bundleType === bundleType - ); - const index = recordIndex !== -1 ? recordIndex : currentSizes.length; - currentSizes[index] = { - filename, + // Compile to ES2015. + babel( + getBabelConfig( + updateBabelOptions, bundleType, packageName, - size, - gzip, - }; + externals, + !isProduction, + bundle + ) + ), + // Remove 'use strict' from individual source files. + { + transform(source) { + return source.replace(/['"]use strict["']/g, ''); + }, + }, + // Turn __DEV__ and process.env checks into constants. + replace({ + preventAssignment: true, + values: { + __DEV__: isProduction ? 'false' : 'true', + __PROFILE__: isProfiling || !isProduction ? 'true' : 'false', + __UMD__: isUMDBundle ? 'true' : 'false', + 'process.env.NODE_ENV': isProduction + ? "'production'" + : "'development'", + __EXPERIMENTAL__, + }, + }), + // The CommonJS plugin *only* exists to pull "art" into "react-art". + // I'm going to port "art" to ES modules to avoid this problem. + // Please don't enable this for anything else! + isUMDBundle && entry === 'react-art' && commonjs(), + // Apply dead code elimination and/or minification. + // closure doesn't yet support leaving ESM imports intact + isProduction && + bundleType !== ESM_PROD && + closure({ + compilation_level: 'SIMPLE', + language_in: 'ECMASCRIPT_2020', + language_out: + bundleType === NODE_ES2015 + ? 'ECMASCRIPT_2020' + : bundleType === BROWSER_SCRIPT + ? 'ECMASCRIPT5' + : 'ECMASCRIPT5_STRICT', + emit_use_strict: + bundleType !== BROWSER_SCRIPT && + bundleType !== ESM_PROD && + bundleType !== ESM_DEV, + env: 'CUSTOM', + warning_level: 'QUIET', + apply_input_source_maps: false, + use_types_for_optimization: false, + process_common_js_modules: false, + rewrite_polyfills: false, + inject_libraries: false, + allow_dynamic_import: true, + + // Don't let it create global variables in the browser. + // https://github.com/facebook/react/issues/10909 + assume_function_wrapper: !isUMDBundle, + renaming: !shouldStayReadable, + }), + // Add the whitespace back if necessary. + shouldStayReadable && + prettier({ + parser: 'flow', + singleQuote: false, + trailingComma: 'none', + bracketSpacing: true, + }), + // License and haste headers, top-level `if` blocks. + { + renderChunk(source) { + return Wrappers.wrapBundle( + source, + bundleType, + globalName, + filename, + moduleType, + bundle.wrapWithModuleBoundaries + ); + }, }, - }), - ].filter(Boolean); + // Record bundle size. + sizes({ + getSize: (size, gzip) => { + const currentSizes = Stats.currentBuildResults.bundleSizes; + const recordIndex = currentSizes.findIndex( + record => + record.filename === filename && record.bundleType === bundleType + ); + const index = recordIndex !== -1 ? recordIndex : currentSizes.length; + currentSizes[index] = { + filename, + bundleType, + packageName, + size, + gzip, + }; + }, + }), + ].filter(Boolean); + } catch (error) { + console.error( + chalk.red(`There was an error preparing plugins for entry "${entry}"`) + ); + throw error; + } } function shouldSkipBundle(bundle, bundleType) { diff --git a/scripts/rollup/forks.js b/scripts/rollup/forks.js index d51e784f68378..801c876a45030 100644 --- a/scripts/rollup/forks.js +++ b/scripts/rollup/forks.js @@ -1,5 +1,6 @@ 'use strict'; +const fs = require('node:fs'); const {bundleTypes, moduleTypes} = require('./bundles'); const inlinedHostConfigs = require('../shared/inlinedHostConfigs'); @@ -28,6 +29,22 @@ const __EXPERIMENTAL__ = ? RELEASE_CHANNEL === 'experimental' : true; +function findNearestExistingForkFile(path, segmentedIdentifier, suffix) { + const segments = segmentedIdentifier.split('-'); + while (segments.length) { + const candidate = segments.join('-'); + const forkPath = path + candidate + suffix; + try { + fs.statSync(forkPath); + return forkPath; + } catch (error) { + // Try the next candidate. + } + segments.pop(); + } + return null; +} + // If you need to replace a file with another file for a specific environment, // add it to this list with the logic for choosing the right replacement. @@ -261,7 +278,16 @@ const forks = Object.freeze({ // eslint-disable-next-line no-for-of-loops/no-for-of-loops for (let rendererInfo of inlinedHostConfigs) { if (rendererInfo.entryPoints.indexOf(entry) !== -1) { - return `./packages/react-reconciler/src/forks/ReactFiberConfig.${rendererInfo.shortName}.js`; + const foundFork = findNearestExistingForkFile( + './packages/react-reconciler/src/forks/ReactFiberConfig.', + rendererInfo.shortName, + '.js' + ); + if (foundFork) { + return foundFork; + } + // fall through to error + break; } } throw new Error( @@ -289,7 +315,16 @@ const forks = Object.freeze({ if (!rendererInfo.isServerSupported) { return null; } - return `./packages/react-server/src/forks/ReactServerStreamConfig.${rendererInfo.shortName}.js`; + const foundFork = findNearestExistingForkFile( + './packages/react-server/src/forks/ReactServerStreamConfig.', + rendererInfo.shortName, + '.js' + ); + if (foundFork) { + return foundFork; + } + // fall through to error + break; } } throw new Error( @@ -317,7 +352,16 @@ const forks = Object.freeze({ if (!rendererInfo.isServerSupported) { return null; } - return `./packages/react-server/src/forks/ReactFizzConfig.${rendererInfo.shortName}.js`; + const foundFork = findNearestExistingForkFile( + './packages/react-server/src/forks/ReactFizzConfig.', + rendererInfo.shortName, + '.js' + ); + if (foundFork) { + return foundFork; + } + // fall through to error + break; } } throw new Error( @@ -345,7 +389,23 @@ const forks = Object.freeze({ if (!rendererInfo.isServerSupported) { return null; } - return `./packages/react-server/src/forks/ReactFlightServerConfig.${rendererInfo.shortName}.js`; + if (rendererInfo.isFlightSupported === false) { + return new Error( + `Expected not to use ReactFlightServerConfig with "${entry}" entry point ` + + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' + + 'activate flight suppport and add a matching fork implementation for ReactFlightServerConfig.' + ); + } + const foundFork = findNearestExistingForkFile( + './packages/react-server/src/forks/ReactFlightServerConfig.', + rendererInfo.shortName, + '.js' + ); + if (foundFork) { + return foundFork; + } + // fall through to error + break; } } throw new Error( @@ -373,7 +433,23 @@ const forks = Object.freeze({ if (!rendererInfo.isServerSupported) { return null; } - return `./packages/react-client/src/forks/ReactFlightClientConfig.${rendererInfo.shortName}.js`; + if (rendererInfo.isFlightSupported === false) { + return new Error( + `Expected not to use ReactFlightClientConfig with "${entry}" entry point ` + + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' + + 'activate flight suppport and add a matching fork implementation for ReactFlightClientConfig.' + ); + } + const foundFork = findNearestExistingForkFile( + './packages/react-client/src/forks/ReactFlightClientConfig.', + rendererInfo.shortName, + '.js' + ); + if (foundFork) { + return foundFork; + } + // fall through to error + break; } } throw new Error( diff --git a/scripts/shared/inlinedHostConfigs.js b/scripts/shared/inlinedHostConfigs.js index 4b35976aeba29..a6c1772f11c72 100644 --- a/scripts/shared/inlinedHostConfigs.js +++ b/scripts/shared/inlinedHostConfigs.js @@ -93,6 +93,28 @@ module.exports = [ isFlowTyped: true, isServerSupported: true, }, + { + shortName: 'dom-browser-esm', + entryPoints: ['react-server-dom-esm/client.browser'], + paths: [ + 'react-dom', + 'react-dom/client', + 'react-dom/server', + 'react-dom/server.node', + 'react-dom-bindings', + 'react-server-dom-esm', + 'react-server-dom-esm/client', + 'react-server-dom-esm/client.browser', + 'react-devtools', + 'react-devtools-core', + 'react-devtools-shell', + 'react-devtools-shared', + 'react-interactions', + 'shared/ReactDOMSharedInternals', + ], + isFlowTyped: true, + isServerSupported: true, + }, { shortName: 'dom-edge-webpack', entryPoints: [ @@ -160,7 +182,6 @@ module.exports = [ { shortName: 'dom-node-esm', entryPoints: [ - 'react-server-dom-esm/client.browser', 'react-server-dom-esm/server.node', 'react-server-dom-esm/client.node', ], @@ -175,7 +196,6 @@ module.exports = [ 'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node 'react-dom/src/server/ReactDOMFizzStaticNode.js', 'react-server-dom-esm', - 'react-server-dom-esm/client.browser', 'react-server-dom-esm/client.node', 'react-server-dom-esm/server', 'react-server-dom-esm/server.node',