Dedupe module id generation (#20172)
Sebastian Markbåge committed
Nov 10, 2020 at 22:58 UTC
163199d8cc99309e765c85e93c6b9dd1f22c2974
7 files changed
+37
packages/react-noop-renderer/src/ReactNoopFlightServer.js
+3
@@ -45,6 +45,9 @@ const ReactNoopFlightServer = ReactFlightServer({
45
isModuleReference(reference: Object): boolean {
46
return reference.$$typeof === Symbol.for('react.module.reference');
47
},
48
+ getModuleKey(reference: Object): Object {
49
+ return reference;
50
+ },
51
resolveModuleMetaData(
52
config: void,
53
reference: {$$typeof: Symbol, value: any},
packages/react-server/src/ReactFlightServer.js
+9
@@ -14,6 +14,7 @@ import type {
14
BundlerConfig,
15
ModuleMetaData,
16
ModuleReference,
17
+ ModuleKey,
18
} from './ReactFlightServerConfig';
19
20
import {
@@ -28,6 +29,7 @@ import {
29
processSymbolChunk,
30
processErrorChunk,
31
resolveModuleMetaData,
32
+ getModuleKey,
33
isModuleReference,
34
} from './ReactFlightServerConfig';
35
@@ -79,6 +81,7 @@ export type Request = {
81
completedJSONChunks: Array<Chunk>,
82
completedErrorChunks: Array<Chunk>,
83
writtenSymbols: Map<Symbol, number>,
84
+ writtenModules: Map<ModuleKey, number>,
85
flowing: boolean,
86
toJSON: (key: string, value: ReactModel) => ReactJSONValue,
87
};
@@ -101,6 +104,7 @@ export function createRequest(
104
completedJSONChunks: [],
105
completedErrorChunks: [],
106
writtenSymbols: new Map(),
107
+ writtenModules: new Map(),
108
flowing: false,
109
toJSON: function(key: string, value: ReactModel): ReactJSONValue {
110
return resolveModelToJSON(request, this, key, value);
@@ -425,6 +429,11 @@ export function resolveModelToJSON(
429
if (typeof value === 'object') {
430
if (isModuleReference(value)) {
431
const moduleReference: ModuleReference<any> = (value: any);
432
+ const moduleKey: ModuleKey = getModuleKey(moduleReference);
433
+ const existingId = request.writtenModules.get(moduleKey);
434
+ if (existingId !== undefined) {
435
+ return serializeByValueID(existingId);
436
+ }
437
try {
438
const moduleMetaData: ModuleMetaData = resolveModuleMetaData(
439
request.bundlerConfig,
packages/react-server/src/ReactFlightServerBundlerConfigCustom.js
+2
@@ -12,5 +12,7 @@ declare var $$$hostConfig: any;
12
export opaque type BundlerConfig = mixed; // eslint-disable-line no-undef
13
export opaque type ModuleReference<T> = mixed; // eslint-disable-line no-undef
14
export opaque type ModuleMetaData: any = mixed; // eslint-disable-line no-undef
15
+export opaque type ModuleKey: any = mixed; // eslint-disable-line no-undef
16
export const isModuleReference = $$$hostConfig.isModuleReference;
17
+export const getModuleKey = $$$hostConfig.getModuleKey;
18
export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;
packages/react-transport-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js
+8
@@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
38
return reference instanceof JSResourceReference;
39
}
40
41
+export type ModuleKey = ModuleReference<any>;
42
+
43
+export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
44
+ // We use the reference object itself as the key because we assume the
45
+ // object will be cached by the bundler runtime.
46
+ return reference;
47
+}
48
+
49
export function resolveModuleMetaData<T>(
50
config: BundlerConfig,
51
resource: ModuleReference<T>,
packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
+6
@@ -25,8 +25,14 @@ export type ModuleMetaData = {
25
name: string,
26
};
27
28
+export type ModuleKey = string;
29
+
30
const MODULE_TAG = Symbol.for('react.module.reference');
31
32
+export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
33
+ return reference.name;
34
+}
35
+
36
export function isModuleReference(reference: Object): boolean {
37
return reference.$$typeof === MODULE_TAG;
38
}
packages/react-transport-native-relay/src/ReactFlightNativeRelayServerHostConfig.js
+8
@@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
38
return reference instanceof JSResourceReferenceImpl;
39
}
40
41
+export type ModuleKey = ModuleReference<any>;
42
+
43
+export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
44
+ // We use the reference object itself as the key because we assume the
45
+ // object will be cached by the bundler runtime.
46
+ return reference;
47
+}
48
+
49
export function resolveModuleMetaData<T>(
50
config: BundlerConfig,
51
resource: ModuleReference<T>,
scripts/jest/setupHostConfigs.js
+1
@@ -35,6 +35,7 @@ jest.mock('react-server/flight', () => {
35
jest.mock(shimServerFormatConfigPath, () => config);
36
jest.mock('react-server/src/ReactFlightServerBundlerConfigCustom', () => ({
37
isModuleReference: config.isModuleReference,
38
+ getModuleKey: config.getModuleKey,
39
resolveModuleMetaData: config.resolveModuleMetaData,
40
}));
41
jest.mock(shimFlightServerConfigPath, () =>