@samitouri / QOS-React-1 / commits / 5623f2acf9

Updating forking implementation to match against more general fork implementations (#27205)

Search for more generic fork files if an exact match does not exist. If `forks/MyFile.dom.js` exists but `forks/MyFile.dom-node.js` does not then use it when trying to resolve forks for the `"dom-node"` renderer in flow, tests, and build consolidate certain fork files that were identical and make semantic sense to be generalized add `dom-browser-esm` bundle and use it for `react-server-dom-esm/client.browser` build

Josh Story committed Aug 17, 2023 at 15:17 UTC 5623f2acf93d762b0b67dab76668b564a6f3b21e
26 files changed +340 -321
packages/react-client/src/forks/ReactFlightClientConfig.dom-browser-esm.js new
+13
@@ -0,0 +1,13 @@
1 +/**
2 + * Copyright (c) Meta Platforms, Inc. and affiliates.
3 + *
4 + * This source code is licensed under the MIT license found in the
5 + * LICENSE file in the root directory of this source tree.
6 + *
7 + * @flow
8 + */
9 +
10 +export * from 'react-client/src/ReactFlightClientConfigBrowser';
11 +export * from 'react-server-dom-esm/src/ReactFlightClientConfigESMBundler';
12 +export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
13 +export const usedWithSSR = false;
packages/react-client/src/forks/ReactFlightClientConfig.dom-node-esm.js
-1
@@ -7,7 +7,6 @@
7 * @flow
8 */
9
10 -// 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
10 export * from 'react-client/src/ReactFlightClientConfigBrowser';
11 export * from 'react-server-dom-esm/src/ReactFlightClientConfigESMBundler';
12 export * from 'react-dom-bindings/src/shared/ReactFlightClientConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-bun.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-edge-webpack.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-fb.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-legacy.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-esm.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-node-webpack.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom-node.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from 'react-dom-bindings/src/client/ReactFiberConfigDOM';
packages/react-reconciler/src/forks/ReactFiberConfig.dom.js renamed
packages/react-server/src/forks/ReactFizzConfig.dom-bun.js deleted
-14
@@ -1,14 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -import type {Request} from 'react-server/src/ReactFizzServer';
10 -
11 -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
12 -
13 -export const supportsRequestStorage = false;
14 -export const requestStorage: AsyncLocalStorage<Request> = (null: any);
packages/react-server/src/forks/ReactFizzConfig.dom-edge.js renamed
packages/react-server/src/forks/ReactFizzConfig.dom-fb.js deleted
-14
@@ -1,14 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -import type {Request} from 'react-server/src/ReactFizzServer';
10 -
11 -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
12 -
13 -export const supportsRequestStorage = false;
14 -export const requestStorage: AsyncLocalStorage<Request> = (null: any);
packages/react-server/src/forks/ReactFizzConfig.dom-node-esm.js deleted
-17
@@ -1,17 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -import {AsyncLocalStorage} from 'async_hooks';
10 -
11 -import type {Request} from 'react-server/src/ReactFizzServer';
12 -
13 -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
14 -
15 -export const supportsRequestStorage = true;
16 -export const requestStorage: AsyncLocalStorage<Request> =
17 - new AsyncLocalStorage();
packages/react-server/src/forks/ReactFizzConfig.dom-node-webpack.js deleted
-17
@@ -1,17 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -import {AsyncLocalStorage} from 'async_hooks';
10 -
11 -import type {Request} from 'react-server/src/ReactFizzServer';
12 -
13 -export * from 'react-dom-bindings/src/server/ReactFizzConfigDOM';
14 -
15 -export const supportsRequestStorage = true;
16 -export const requestStorage: AsyncLocalStorage<Request> =
17 - new AsyncLocalStorage();
packages/react-server/src/forks/ReactFizzConfig.dom.js renamed
packages/react-server/src/forks/ReactFlightServerConfig.dom-browser-esm.js renamed
+1 -1
@@ -10,7 +10,7 @@ import {AsyncLocalStorage} from 'async_hooks';
10
11 import type {Request} from 'react-server/src/ReactFlightServer';
12
13 -export * from 'react-server-dom-webpack/src/ReactFlightServerConfigWebpackBundler';
13 +export * from 'react-server-dom-esm/src/ReactFlightServerConfigESMBundler';
14 export * from 'react-dom-bindings/src/server/ReactFlightServerConfigDOM';
15
16 export const supportsRequestStorage = true;
packages/react-server/src/forks/ReactFlightServerConfig.dom-edge.js renamed
packages/react-server/src/forks/ReactServerStreamConfig.dom-edge.js renamed
packages/react-server/src/forks/ReactServerStreamConfig.dom-node-esm.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from '../ReactServerStreamConfigNode';
packages/react-server/src/forks/ReactServerStreamConfig.dom-node-webpack.js deleted
-10
@@ -1,10 +0,0 @@
1 -/**
2 - * Copyright (c) Meta Platforms, Inc. and affiliates.
3 - *
4 - * This source code is licensed under the MIT license found in the
5 - * LICENSE file in the root directory of this source tree.
6 - *
7 - * @flow
8 - */
9 -
10 -export * from '../ReactServerStreamConfigNode';
scripts/flow/createFlowConfigs.js
+58 -18
@@ -9,6 +9,7 @@
9
10 const chalk = require('chalk');
11 const fs = require('fs');
12 +const path = require('path');
13 const mkdirp = require('mkdirp');
14 const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
15
@@ -16,6 +17,40 @@ const configTemplate = fs
17 .readFileSync(__dirname + '/config/flowconfig')
18 .toString();
19
20 +// stores all forks discovered during config generation
21 +const allForks = new Set();
22 +// maps forked file to the base path containing it and it's forks (it's parent)
23 +const forkedFiles = new Map();
24 +
25 +function findForks(file) {
26 + const basePath = path.join(file, '..');
27 + const forksPath = path.join(basePath, 'forks');
28 + const forks = fs.readdirSync(path.join('packages', forksPath));
29 + forks.forEach(f => allForks.add('forks/' + f));
30 + forkedFiles.set(file, basePath);
31 + return basePath;
32 +}
33 +
34 +function addFork(forks, renderer, file) {
35 + let basePath = forkedFiles.get(file);
36 + if (!basePath) {
37 + basePath = findForks(file);
38 + }
39 +
40 + const baseFilename = file.slice(basePath.length + 1);
41 +
42 + const parts = renderer.split('-');
43 + while (parts.length) {
44 + const candidate = `forks/${baseFilename}.${parts.join('-')}.js`;
45 + if (allForks.has(candidate)) {
46 + forks.set(candidate, `${baseFilename}$$`);
47 + return;
48 + }
49 + parts.pop();
50 + }
51 + throw new Error(`Cannot find fork for ${file} for renderer ${renderer}`);
52 +}
53 +
54 function writeConfig(
55 renderer,
56 rendererInfo,
@@ -44,34 +79,39 @@ function writeConfig(
79 }
80 ignoredPaths.push(`.*/packages/${otherPath}`);
81 });
82 + });
83 +
84 + const forks = new Map();
85 + addFork(forks, renderer, 'react-reconciler/src/ReactFiberConfig');
86 + addFork(forks, serverRenderer, 'react-server/src/ReactServerStreamConfig');
87 + addFork(forks, serverRenderer, 'react-server/src/ReactFizzConfig');
88 + addFork(forks, flightRenderer, 'react-server/src/ReactFlightServerConfig');
89 + addFork(forks, flightRenderer, 'react-client/src/ReactFlightClientConfig');
90 + forks.set(
91 + 'react-devtools-shared/src/config/DevToolsFeatureFlags.default',
92 + 'react-devtools-feature-flags',
93 + );
94
48 - if (
49 - otherRenderer.shortName !== serverRenderer &&
50 - otherRenderer.shortName !== flightRenderer
51 - ) {
52 - ignoredPaths.push(
53 - `.*/packages/.*/forks/.*\\.${otherRenderer.shortName}.js`,
54 - );
95 + allForks.forEach(fork => {
96 + if (!forks.has(fork)) {
97 + ignoredPaths.push(`.*/packages/.*/${fork}`);
98 }
99 });
100
101 + let moduleMappings = '';
102 + forks.forEach((source, target) => {
103 + moduleMappings += `module.name_mapper='${source.slice(
104 + source.lastIndexOf('/') + 1,
105 + )}' -> '${target}'\n`;
106 + });
107 +
108 const config = configTemplate
109 .replace(
110 '%CI_MAX_WORKERS%\n',
111 // On CI, we seem to need to limit workers.
112 process.env.CI ? 'server.max_workers=4\n' : '',
113 )
64 - .replace(
65 - '%REACT_RENDERER_FLOW_OPTIONS%',
66 - `
67 -module.name_mapper='ReactFiberConfig$$' -> 'forks/ReactFiberConfig.${renderer}'
68 -module.name_mapper='ReactServerStreamConfig$$' -> 'forks/ReactServerStreamConfig.${serverRenderer}'
69 -module.name_mapper='ReactFizzConfig$$' -> 'forks/ReactFizzConfig.${serverRenderer}'
70 -module.name_mapper='ReactFlightServerConfig$$' -> 'forks/ReactFlightServerConfig.${flightRenderer}'
71 -module.name_mapper='ReactFlightClientConfig$$' -> 'forks/ReactFlightClientConfig.${flightRenderer}'
72 -module.name_mapper='react-devtools-feature-flags' -> 'react-devtools-shared/src/config/DevToolsFeatureFlags.default'
73 - `.trim(),
74 - )
114 + .replace('%REACT_RENDERER_FLOW_OPTIONS%', moduleMappings.trim())
115 .replace('%REACT_RENDERER_FLOW_IGNORES%', ignoredPaths.join('\n'));
116
117 const disclaimer = `
scripts/jest/setupHostConfigs.js
+15 -1
@@ -1,6 +1,7 @@
1 'use strict';
2
3 const fs = require('fs');
4 +const nodePath = require('path');
5 const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
6
7 function resolveEntryFork(resolvedEntry, isFBBundle) {
@@ -117,7 +118,20 @@ function mockAllConfigs(rendererInfo) {
118 jest.mock(path, () => {
119 let idx = path.lastIndexOf('/');
120 let forkPath = path.slice(0, idx) + '/forks' + path.slice(idx);
120 - return jest.requireActual(`${forkPath}.${rendererInfo.shortName}.js`);
121 + let parts = rendererInfo.shortName.split('-');
122 + while (parts.length) {
123 + try {
124 + const candidate = `${forkPath}.${parts.join('-')}.js`;
125 + fs.statSync(nodePath.join(process.cwd(), 'packages', candidate));
126 + return jest.requireActual(candidate);
127 + } catch (error) {
128 + // try without a part
129 + }
130 + parts.pop();
131 + }
132 + throw new Error(
133 + `Expected to find a fork for ${path} but did not find one.`
134 + );
135 });
136 });
137 }
scripts/rollup/build.js
+150 -141
@@ -341,153 +341,162 @@ function getPlugins(
341 pureExternalModules,
342 bundle
343 ) {
344 - const forks = Modules.getForks(bundleType, entry, moduleType, bundle);
345 - const isProduction = isProductionBundleType(bundleType);
346 - const isProfiling = isProfilingBundleType(bundleType);
347 - const isUMDBundle =
348 - bundleType === UMD_DEV ||
349 - bundleType === UMD_PROD ||
350 - bundleType === UMD_PROFILING;
351 - const isFBWWWBundle =
352 - bundleType === FB_WWW_DEV ||
353 - bundleType === FB_WWW_PROD ||
354 - bundleType === FB_WWW_PROFILING;
355 - const isRNBundle =
356 - bundleType === RN_OSS_DEV ||
357 - bundleType === RN_OSS_PROD ||
358 - bundleType === RN_OSS_PROFILING ||
359 - bundleType === RN_FB_DEV ||
360 - bundleType === RN_FB_PROD ||
361 - bundleType === RN_FB_PROFILING;
362 - const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
363 - return [
364 - // Keep dynamic imports as externals
365 - dynamicImports(),
366 - {
367 - name: 'rollup-plugin-flow-remove-types',
368 - transform(code) {
369 - const transformed = flowRemoveTypes(code);
370 - return {
371 - code: transformed.toString(),
372 - map: transformed.generateMap(),
373 - };
374 - },
375 - },
376 - // Shim any modules that need forking in this environment.
377 - useForks(forks),
378 - // Ensure we don't try to bundle any fbjs modules.
379 - forbidFBJSImports(),
380 - // Use Node resolution mechanism.
381 - resolve({
382 - // skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0
383 - }),
384 - // Remove license headers from individual modules
385 - stripBanner({
386 - exclude: 'node_modules/**/*',
387 - }),
388 - // Compile to ES2015.
389 - babel(
390 - getBabelConfig(
391 - updateBabelOptions,
392 - bundleType,
393 - packageName,
394 - externals,
395 - !isProduction,
396 - bundle
397 - )
398 - ),
399 - // Remove 'use strict' from individual source files.
400 - {
401 - transform(source) {
402 - return source.replace(/['"]use strict["']/g, '');
403 - },
404 - },
405 - // Turn __DEV__ and process.env checks into constants.
406 - replace({
407 - preventAssignment: true,
408 - values: {
409 - __DEV__: isProduction ? 'false' : 'true',
410 - __PROFILE__: isProfiling || !isProduction ? 'true' : 'false',
411 - __UMD__: isUMDBundle ? 'true' : 'false',
412 - 'process.env.NODE_ENV': isProduction ? "'production'" : "'development'",
413 - __EXPERIMENTAL__,
344 + try {
345 + const forks = Modules.getForks(bundleType, entry, moduleType, bundle);
346 + const isProduction = isProductionBundleType(bundleType);
347 + const isProfiling = isProfilingBundleType(bundleType);
348 + const isUMDBundle =
349 + bundleType === UMD_DEV ||
350 + bundleType === UMD_PROD ||
351 + bundleType === UMD_PROFILING;
352 + const isFBWWWBundle =
353 + bundleType === FB_WWW_DEV ||
354 + bundleType === FB_WWW_PROD ||
355 + bundleType === FB_WWW_PROFILING;
356 + const isRNBundle =
357 + bundleType === RN_OSS_DEV ||
358 + bundleType === RN_OSS_PROD ||
359 + bundleType === RN_OSS_PROFILING ||
360 + bundleType === RN_FB_DEV ||
361 + bundleType === RN_FB_PROD ||
362 + bundleType === RN_FB_PROFILING;
363 + const shouldStayReadable = isFBWWWBundle || isRNBundle || forcePrettyOutput;
364 + return [
365 + // Keep dynamic imports as externals
366 + dynamicImports(),
367 + {
368 + name: 'rollup-plugin-flow-remove-types',
369 + transform(code) {
370 + const transformed = flowRemoveTypes(code);
371 + return {
372 + code: transformed.toString(),
373 + map: transformed.generateMap(),
374 + };
375 + },
376 },
415 - }),
416 - // The CommonJS plugin *only* exists to pull "art" into "react-art".
417 - // I'm going to port "art" to ES modules to avoid this problem.
418 - // Please don't enable this for anything else!
419 - isUMDBundle && entry === 'react-art' && commonjs(),
420 - // Apply dead code elimination and/or minification.
421 - // closure doesn't yet support leaving ESM imports intact
422 - isProduction &&
423 - bundleType !== ESM_PROD &&
424 - closure({
425 - compilation_level: 'SIMPLE',
426 - language_in: 'ECMASCRIPT_2020',
427 - language_out:
428 - bundleType === NODE_ES2015
429 - ? 'ECMASCRIPT_2020'
430 - : bundleType === BROWSER_SCRIPT
431 - ? 'ECMASCRIPT5'
432 - : 'ECMASCRIPT5_STRICT',
433 - emit_use_strict:
434 - bundleType !== BROWSER_SCRIPT &&
435 - bundleType !== ESM_PROD &&
436 - bundleType !== ESM_DEV,
437 - env: 'CUSTOM',
438 - warning_level: 'QUIET',
439 - apply_input_source_maps: false,
440 - use_types_for_optimization: false,
441 - process_common_js_modules: false,
442 - rewrite_polyfills: false,
443 - inject_libraries: false,
444 - allow_dynamic_import: true,
445 -
446 - // Don't let it create global variables in the browser.
447 - // https://github.com/facebook/react/issues/10909
448 - assume_function_wrapper: !isUMDBundle,
449 - renaming: !shouldStayReadable,
377 + // Shim any modules that need forking in this environment.
378 + useForks(forks),
379 + // Ensure we don't try to bundle any fbjs modules.
380 + forbidFBJSImports(),
381 + // Use Node resolution mechanism.
382 + resolve({
383 + // skip: externals, // TODO: options.skip was removed in @rollup/plugin-node-resolve 3.0.0
384 }),
451 - // Add the whitespace back if necessary.
452 - shouldStayReadable &&
453 - prettier({
454 - parser: 'flow',
455 - singleQuote: false,
456 - trailingComma: 'none',
457 - bracketSpacing: true,
385 + // Remove license headers from individual modules
386 + stripBanner({
387 + exclude: 'node_modules/**/*',
388 }),
459 - // License and haste headers, top-level `if` blocks.
460 - {
461 - renderChunk(source) {
462 - return Wrappers.wrapBundle(
463 - source,
464 - bundleType,
465 - globalName,
466 - filename,
467 - moduleType,
468 - bundle.wrapWithModuleBoundaries
469 - );
470 - },
471 - },
472 - // Record bundle size.
473 - sizes({
474 - getSize: (size, gzip) => {
475 - const currentSizes = Stats.currentBuildResults.bundleSizes;
476 - const recordIndex = currentSizes.findIndex(
477 - record =>
478 - record.filename === filename && record.bundleType === bundleType
479 - );
480 - const index = recordIndex !== -1 ? recordIndex : currentSizes.length;
481 - currentSizes[index] = {
482 - filename,
389 + // Compile to ES2015.
390 + babel(
391 + getBabelConfig(
392 + updateBabelOptions,
393 bundleType,
394 packageName,
485 - size,
486 - gzip,
487 - };
395 + externals,
396 + !isProduction,
397 + bundle
398 + )
399 + ),
400 + // Remove 'use strict' from individual source files.
401 + {
402 + transform(source) {
403 + return source.replace(/['"]use strict["']/g, '');
404 + },
405 + },
406 + // Turn __DEV__ and process.env checks into constants.
407 + replace({
408 + preventAssignment: true,
409 + values: {
410 + __DEV__: isProduction ? 'false' : 'true',
411 + __PROFILE__: isProfiling || !isProduction ? 'true' : 'false',
412 + __UMD__: isUMDBundle ? 'true' : 'false',
413 + 'process.env.NODE_ENV': isProduction
414 + ? "'production'"
415 + : "'development'",
416 + __EXPERIMENTAL__,
417 + },
418 + }),
419 + // The CommonJS plugin *only* exists to pull "art" into "react-art".
420 + // I'm going to port "art" to ES modules to avoid this problem.
421 + // Please don't enable this for anything else!
422 + isUMDBundle && entry === 'react-art' && commonjs(),
423 + // Apply dead code elimination and/or minification.
424 + // closure doesn't yet support leaving ESM imports intact
425 + isProduction &&
426 + bundleType !== ESM_PROD &&
427 + closure({
428 + compilation_level: 'SIMPLE',
429 + language_in: 'ECMASCRIPT_2020',
430 + language_out:
431 + bundleType === NODE_ES2015
432 + ? 'ECMASCRIPT_2020'
433 + : bundleType === BROWSER_SCRIPT
434 + ? 'ECMASCRIPT5'
435 + : 'ECMASCRIPT5_STRICT',
436 + emit_use_strict:
437 + bundleType !== BROWSER_SCRIPT &&
438 + bundleType !== ESM_PROD &&
439 + bundleType !== ESM_DEV,
440 + env: 'CUSTOM',
441 + warning_level: 'QUIET',
442 + apply_input_source_maps: false,
443 + use_types_for_optimization: false,
444 + process_common_js_modules: false,
445 + rewrite_polyfills: false,
446 + inject_libraries: false,
447 + allow_dynamic_import: true,
448 +
449 + // Don't let it create global variables in the browser.
450 + // https://github.com/facebook/react/issues/10909
451 + assume_function_wrapper: !isUMDBundle,
452 + renaming: !shouldStayReadable,
453 + }),
454 + // Add the whitespace back if necessary.
455 + shouldStayReadable &&
456 + prettier({
457 + parser: 'flow',
458 + singleQuote: false,
459 + trailingComma: 'none',
460 + bracketSpacing: true,
461 + }),
462 + // License and haste headers, top-level `if` blocks.
463 + {
464 + renderChunk(source) {
465 + return Wrappers.wrapBundle(
466 + source,
467 + bundleType,
468 + globalName,
469 + filename,
470 + moduleType,
471 + bundle.wrapWithModuleBoundaries
472 + );
473 + },
474 },
489 - }),
490 - ].filter(Boolean);
475 + // Record bundle size.
476 + sizes({
477 + getSize: (size, gzip) => {
478 + const currentSizes = Stats.currentBuildResults.bundleSizes;
479 + const recordIndex = currentSizes.findIndex(
480 + record =>
481 + record.filename === filename && record.bundleType === bundleType
482 + );
483 + const index = recordIndex !== -1 ? recordIndex : currentSizes.length;
484 + currentSizes[index] = {
485 + filename,
486 + bundleType,
487 + packageName,
488 + size,
489 + gzip,
490 + };
491 + },
492 + }),
493 + ].filter(Boolean);
494 + } catch (error) {
495 + console.error(
496 + chalk.red(`There was an error preparing plugins for entry "${entry}"`)
497 + );
498 + throw error;
499 + }
500 }
501
502 function shouldSkipBundle(bundle, bundleType) {
scripts/rollup/forks.js
+81 -5
@@ -1,5 +1,6 @@
1 'use strict';
2
3 +const fs = require('node:fs');
4 const {bundleTypes, moduleTypes} = require('./bundles');
5 const inlinedHostConfigs = require('../shared/inlinedHostConfigs');
6
@@ -28,6 +29,22 @@ const __EXPERIMENTAL__ =
29 ? RELEASE_CHANNEL === 'experimental'
30 : true;
31
32 +function findNearestExistingForkFile(path, segmentedIdentifier, suffix) {
33 + const segments = segmentedIdentifier.split('-');
34 + while (segments.length) {
35 + const candidate = segments.join('-');
36 + const forkPath = path + candidate + suffix;
37 + try {
38 + fs.statSync(forkPath);
39 + return forkPath;
40 + } catch (error) {
41 + // Try the next candidate.
42 + }
43 + segments.pop();
44 + }
45 + return null;
46 +}
47 +
48 // If you need to replace a file with another file for a specific environment,
49 // add it to this list with the logic for choosing the right replacement.
50
@@ -261,7 +278,16 @@ const forks = Object.freeze({
278 // eslint-disable-next-line no-for-of-loops/no-for-of-loops
279 for (let rendererInfo of inlinedHostConfigs) {
280 if (rendererInfo.entryPoints.indexOf(entry) !== -1) {
264 - return `./packages/react-reconciler/src/forks/ReactFiberConfig.${rendererInfo.shortName}.js`;
281 + const foundFork = findNearestExistingForkFile(
282 + './packages/react-reconciler/src/forks/ReactFiberConfig.',
283 + rendererInfo.shortName,
284 + '.js'
285 + );
286 + if (foundFork) {
287 + return foundFork;
288 + }
289 + // fall through to error
290 + break;
291 }
292 }
293 throw new Error(
@@ -289,7 +315,16 @@ const forks = Object.freeze({
315 if (!rendererInfo.isServerSupported) {
316 return null;
317 }
292 - return `./packages/react-server/src/forks/ReactServerStreamConfig.${rendererInfo.shortName}.js`;
318 + const foundFork = findNearestExistingForkFile(
319 + './packages/react-server/src/forks/ReactServerStreamConfig.',
320 + rendererInfo.shortName,
321 + '.js'
322 + );
323 + if (foundFork) {
324 + return foundFork;
325 + }
326 + // fall through to error
327 + break;
328 }
329 }
330 throw new Error(
@@ -317,7 +352,16 @@ const forks = Object.freeze({
352 if (!rendererInfo.isServerSupported) {
353 return null;
354 }
320 - return `./packages/react-server/src/forks/ReactFizzConfig.${rendererInfo.shortName}.js`;
355 + const foundFork = findNearestExistingForkFile(
356 + './packages/react-server/src/forks/ReactFizzConfig.',
357 + rendererInfo.shortName,
358 + '.js'
359 + );
360 + if (foundFork) {
361 + return foundFork;
362 + }
363 + // fall through to error
364 + break;
365 }
366 }
367 throw new Error(
@@ -345,7 +389,23 @@ const forks = Object.freeze({
389 if (!rendererInfo.isServerSupported) {
390 return null;
391 }
348 - return `./packages/react-server/src/forks/ReactFlightServerConfig.${rendererInfo.shortName}.js`;
392 + if (rendererInfo.isFlightSupported === false) {
393 + return new Error(
394 + `Expected not to use ReactFlightServerConfig with "${entry}" entry point ` +
395 + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' +
396 + 'activate flight suppport and add a matching fork implementation for ReactFlightServerConfig.'
397 + );
398 + }
399 + const foundFork = findNearestExistingForkFile(
400 + './packages/react-server/src/forks/ReactFlightServerConfig.',
401 + rendererInfo.shortName,
402 + '.js'
403 + );
404 + if (foundFork) {
405 + return foundFork;
406 + }
407 + // fall through to error
408 + break;
409 }
410 }
411 throw new Error(
@@ -373,7 +433,23 @@ const forks = Object.freeze({
433 if (!rendererInfo.isServerSupported) {
434 return null;
435 }
376 - return `./packages/react-client/src/forks/ReactFlightClientConfig.${rendererInfo.shortName}.js`;
436 + if (rendererInfo.isFlightSupported === false) {
437 + return new Error(
438 + `Expected not to use ReactFlightClientConfig with "${entry}" entry point ` +
439 + 'in ./scripts/shared/inlinedHostConfigs.js. Update the renderer config to ' +
440 + 'activate flight suppport and add a matching fork implementation for ReactFlightClientConfig.'
441 + );
442 + }
443 + const foundFork = findNearestExistingForkFile(
444 + './packages/react-client/src/forks/ReactFlightClientConfig.',
445 + rendererInfo.shortName,
446 + '.js'
447 + );
448 + if (foundFork) {
449 + return foundFork;
450 + }
451 + // fall through to error
452 + break;
453 }
454 }
455 throw new Error(
scripts/shared/inlinedHostConfigs.js
+22 -2
@@ -93,6 +93,28 @@ module.exports = [
93 isFlowTyped: true,
94 isServerSupported: true,
95 },
96 + {
97 + shortName: 'dom-browser-esm',
98 + entryPoints: ['react-server-dom-esm/client.browser'],
99 + paths: [
100 + 'react-dom',
101 + 'react-dom/client',
102 + 'react-dom/server',
103 + 'react-dom/server.node',
104 + 'react-dom-bindings',
105 + 'react-server-dom-esm',
106 + 'react-server-dom-esm/client',
107 + 'react-server-dom-esm/client.browser',
108 + 'react-devtools',
109 + 'react-devtools-core',
110 + 'react-devtools-shell',
111 + 'react-devtools-shared',
112 + 'react-interactions',
113 + 'shared/ReactDOMSharedInternals',
114 + ],
115 + isFlowTyped: true,
116 + isServerSupported: true,
117 + },
118 {
119 shortName: 'dom-edge-webpack',
120 entryPoints: [
@@ -160,7 +182,6 @@ module.exports = [
182 {
183 shortName: 'dom-node-esm',
184 entryPoints: [
163 - 'react-server-dom-esm/client.browser',
185 'react-server-dom-esm/server.node',
186 'react-server-dom-esm/client.node',
187 ],
@@ -175,7 +196,6 @@ module.exports = [
196 'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
197 'react-dom/src/server/ReactDOMFizzStaticNode.js',
198 'react-server-dom-esm',
178 - 'react-server-dom-esm/client.browser',
199 'react-server-dom-esm/client.node',
200 'react-server-dom-esm/server',
201 'react-server-dom-esm/server.node',