Skip to content

Commit 05a8772

Browse files
committed
Dedupe module id generation
1 parent 56c3960 commit 05a8772

File tree

7 files changed

+37
-0
lines changed

7 files changed

+37
-0
lines changed

packages/react-noop-renderer/src/ReactNoopFlightServer.js

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ const ReactNoopFlightServer = ReactFlightServer({
4545
isModuleReference(reference: Object): boolean {
4646
return reference.$$typeof === Symbol.for('react.module.reference');
4747
},
48+
getModuleKey(reference: Object): Object {
49+
return reference;
50+
},
4851
resolveModuleMetaData(
4952
config: void,
5053
reference: {$$typeof: Symbol, value: any},

packages/react-server/src/ReactFlightServer.js

+9
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
BundlerConfig,
1515
ModuleMetaData,
1616
ModuleReference,
17+
ModuleKey,
1718
} from './ReactFlightServerConfig';
1819

1920
import {
@@ -28,6 +29,7 @@ import {
2829
processSymbolChunk,
2930
processErrorChunk,
3031
resolveModuleMetaData,
32+
getModuleKey,
3133
isModuleReference,
3234
} from './ReactFlightServerConfig';
3335

@@ -79,6 +81,7 @@ export type Request = {
7981
completedJSONChunks: Array<Chunk>,
8082
completedErrorChunks: Array<Chunk>,
8183
writtenSymbols: Map<Symbol, number>,
84+
writtenModules: Map<ModuleKey, number>,
8285
flowing: boolean,
8386
toJSON: (key: string, value: ReactModel) => ReactJSONValue,
8487
};
@@ -101,6 +104,7 @@ export function createRequest(
101104
completedJSONChunks: [],
102105
completedErrorChunks: [],
103106
writtenSymbols: new Map(),
107+
writtenModules: new Map(),
104108
flowing: false,
105109
toJSON: function(key: string, value: ReactModel): ReactJSONValue {
106110
return resolveModelToJSON(request, this, key, value);
@@ -420,6 +424,11 @@ export function resolveModelToJSON(
420424
if (typeof value === 'object') {
421425
if (isModuleReference(value)) {
422426
const moduleReference: ModuleReference<any> = (value: any);
427+
const moduleKey: ModuleKey = getModuleKey(moduleReference);
428+
const existingId = request.writtenModules.get(moduleKey);
429+
if (existingId !== undefined) {
430+
return serializeByValueID(existingId);
431+
}
423432
try {
424433
const moduleMetaData: ModuleMetaData = resolveModuleMetaData(
425434
request.bundlerConfig,

packages/react-server/src/ReactFlightServerBundlerConfigCustom.js

+2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@ declare var $$$hostConfig: any;
1212
export opaque type BundlerConfig = mixed; // eslint-disable-line no-undef
1313
export opaque type ModuleReference<T> = mixed; // eslint-disable-line no-undef
1414
export opaque type ModuleMetaData: any = mixed; // eslint-disable-line no-undef
15+
export opaque type ModuleKey: any = mixed; // eslint-disable-line no-undef
1516
export const isModuleReference = $$$hostConfig.isModuleReference;
17+
export const getModuleKey = $$$hostConfig.getModuleKey;
1618
export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;

packages/react-transport-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js

+8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
3838
return reference instanceof JSResourceReference;
3939
}
4040

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+
4149
export function resolveModuleMetaData<T>(
4250
config: BundlerConfig,
4351
resource: ModuleReference<T>,

packages/react-transport-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js

+6
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,14 @@ export type ModuleMetaData = {
2525
name: string,
2626
};
2727

28+
export type ModuleKey = string;
29+
2830
const MODULE_TAG = Symbol.for('react.module.reference');
2931

32+
export function getModuleKey(reference: ModuleReference<any>): ModuleKey {
33+
return reference.name;
34+
}
35+
3036
export function isModuleReference(reference: Object): boolean {
3137
return reference.$$typeof === MODULE_TAG;
3238
}

packages/react-transport-native-relay/src/ReactFlightNativeRelayServerHostConfig.js

+8
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ export function isModuleReference(reference: Object): boolean {
3838
return reference instanceof JSResourceReferenceImpl;
3939
}
4040

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+
4149
export function resolveModuleMetaData<T>(
4250
config: BundlerConfig,
4351
resource: ModuleReference<T>,

scripts/jest/setupHostConfigs.js

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ jest.mock('react-server/flight', () => {
3535
jest.mock(shimServerFormatConfigPath, () => config);
3636
jest.mock('react-server/src/ReactFlightServerBundlerConfigCustom', () => ({
3737
isModuleReference: config.isModuleReference,
38+
getModuleKey: config.getModuleKey,
3839
resolveModuleMetaData: config.resolveModuleMetaData,
3940
}));
4041
jest.mock(shimFlightServerConfigPath, () =>

0 commit comments

Comments
 (0)