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',