Simplify Webpack References by encoding file path + export name as single id (#26300)
We always look up these references in a map so it doesn't matter what their value is. It could be a hash for example. The loaders now encode a single $$id instead of filepath + name. This changes the react-client-manifest to have a single level. The value inside the map is still split into module id + export name because that's what gets looked up in webpack. The react-ssr-manifest is still two levels because that's a reverse lookup.
Sebastian Markbåge committed
Mar 4, 2023 at 19:51 UTC
e0241b66005a7232fa2c2529afa1bd5b27bf8925
18 files changed
+120
-157
fixtures/flight/public/favicon.ico
Binary files /dev/null and b/fixtures/flight/public/favicon.ico differ
fixtures/flight/server/region.js
+2
-2
@@ -98,8 +98,8 @@ app.post('/', bodyParser.text(), async function (req, res) {
98
const {renderToPipeableStream} = await import(
99
'react-server-dom-webpack/server'
100
);
101
- const serverReference = JSON.parse(req.get('rsc-action'));
102
- const {filepath, name} = serverReference;
101
+ const serverReference = req.get('rsc-action');
102
+ const [filepath, name] = serverReference.split('#');
103
const action = (await import(filepath))[name];
104
// Validate that this is actually a function we intended to expose and
105
// not the client trying to invoke arbitrary functions. In a real app,
fixtures/flight/src/index.js
+1
-1
@@ -18,7 +18,7 @@ let data = ReactServerDOMReader.createFromFetch(
18
method: 'POST',
19
headers: {
20
Accept: 'text/x-component',
21
- 'rsc-action': JSON.stringify({filepath: id.id, name: id.name}),
21
+ 'rsc-action': id,
22
},
23
body: JSON.stringify(args),
24
});
packages/react-client/src/ReactFlightClient.js
+6
-4
@@ -473,7 +473,7 @@ function createModelReject<T>(chunk: SomeChunk<T>): (error: mixed) => void {
473
474
function createServerReferenceProxy<A: Iterable<any>, T>(
475
response: Response,
476
- metaData: any,
476
+ metaData: {id: any, bound: Thenable<Array<any>>},
477
): (...A) => Promise<T> {
478
const callServer = response._callServer;
479
const proxy = function (): Promise<T> {
@@ -482,12 +482,14 @@ function createServerReferenceProxy<A: Iterable<any>, T>(
482
const p = metaData.bound;
483
if (p.status === INITIALIZED) {
484
const bound = p.value;
485
- return callServer(metaData, bound.concat(args));
485
+ return callServer(metaData.id, bound.concat(args));
486
}
487
// Since this is a fake Promise whose .then doesn't chain, we have to wrap it.
488
// TODO: Remove the wrapper once that's fixed.
489
- return Promise.resolve(p).then(function (bound) {
490
- return callServer(metaData, bound.concat(args));
489
+ return ((Promise.resolve(p): any): Promise<Array<any>>).then(function (
490
+ bound,
491
+ ) {
492
+ return callServer(metaData.id, bound.concat(args));
493
});
494
};
495
return proxy;
packages/react-server-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js
+2
-2
@@ -19,7 +19,7 @@ import isArray from 'shared/isArray';
19
20
export type ClientReference<T> = JSResourceReference<T>;
21
export type ServerReference<T> = T;
22
-export type ServerReferenceMetadata = {};
22
+export type ServerReferenceId = {};
23
24
import type {
25
Destination,
@@ -69,7 +69,7 @@ export function resolveClientReferenceMetadata<T>(
69
export function resolveServerReferenceMetadata<T>(
70
config: BundlerConfig,
71
resource: ServerReference<T>,
72
-): ServerReferenceMetadata {
72
+): {id: ServerReferenceId, bound: Promise<Array<any>>} {
73
throw new Error('Not implemented.');
74
}
75
packages/react-server-dom-webpack/src/ReactFlightClientNodeBundlerConfig.js
-1
@@ -25,7 +25,6 @@ export opaque type ClientReferenceMetadata = {
25
id: string,
26
chunks: Array<string>,
27
name: string,
28
- async: boolean,
28
};
29
30
// eslint-disable-next-line no-unused-vars
packages/react-server-dom-webpack/src/ReactFlightDOMClientBrowser.js
+1
-4
@@ -20,10 +20,7 @@ import {
20
close,
21
} from 'react-client/src/ReactFlightClientStream';
22
23
-type CallServerCallback = <A, T>(
24
- {filepath: string, name: string},
25
- args: A,
26
-) => Promise<T>;
23
+type CallServerCallback = <A, T>(string, args: A) => Promise<T>;
24
25
export type Options = {
26
callServer?: CallServerCallback,
packages/react-server-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
+10
-25
@@ -10,32 +10,24 @@
10
import type {ReactModel} from 'react-server/src/ReactFlightServer';
11
12
type WebpackMap = {
13
- [filepath: string]: {
14
- [name: string]: ClientReferenceMetadata,
15
- },
13
+ [id: string]: ClientReferenceMetadata,
14
};
15
16
export type BundlerConfig = WebpackMap;
17
18
export type ServerReference<T: Function> = T & {
19
$$typeof: symbol,
22
- $$filepath: string,
23
- $$name: string,
20
+ $$id: string,
21
$$bound: Array<ReactModel>,
22
};
23
27
-export type ServerReferenceMetadata = {
28
- id: string,
29
- name: string,
30
- bound: Promise<Array<ReactModel>>,
31
-};
24
+export type ServerReferenceId = string;
25
26
// eslint-disable-next-line no-unused-vars
27
export type ClientReference<T> = {
28
$$typeof: symbol,
36
- filepath: string,
37
- name: string,
38
- async: boolean,
29
+ $$id: string,
30
+ $$async: boolean,
31
};
32
33
export type ClientReferenceMetadata = {
@@ -53,12 +45,7 @@ const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
45
export function getClientReferenceKey(
46
reference: ClientReference<any>,
47
): ClientReferenceKey {
56
- return (
57
- reference.filepath +
58
- '#' +
59
- reference.name +
60
- (reference.async ? '#async' : '')
61
- );
48
+ return reference.$$async ? reference.$$id + '#async' : reference.$$id;
49
}
50
51
export function isClientReference(reference: Object): boolean {
@@ -73,9 +60,8 @@ export function resolveClientReferenceMetadata<T>(
60
config: BundlerConfig,
61
clientReference: ClientReference<T>,
62
): ClientReferenceMetadata {
76
- const resolvedModuleData =
77
- config[clientReference.filepath][clientReference.name];
78
- if (clientReference.async) {
63
+ const resolvedModuleData = config[clientReference.$$id];
64
+ if (clientReference.$$async) {
65
return {
66
id: resolvedModuleData.id,
67
chunks: resolvedModuleData.chunks,
@@ -90,10 +76,9 @@ export function resolveClientReferenceMetadata<T>(
76
export function resolveServerReferenceMetadata<T>(
77
config: BundlerConfig,
78
serverReference: ServerReference<T>,
93
-): ServerReferenceMetadata {
79
+): {id: ServerReferenceId, bound: Promise<Array<any>>} {
80
return {
95
- id: serverReference.$$filepath,
96
- name: serverReference.$$name,
81
+ id: serverReference.$$id,
82
bound: Promise.resolve(serverReference.$$bound),
83
};
84
}
packages/react-server-dom-webpack/src/ReactFlightWebpackNodeLoader.js
+2
-4
@@ -187,8 +187,7 @@ function transformServerModule(
187
}
188
newSrc += 'Object.defineProperties(' + local + ',{';
189
newSrc += '$$typeof: {value: Symbol.for("react.server.reference")},';
190
- newSrc += '$$filepath: {value: ' + JSON.stringify(url) + '},';
191
- newSrc += '$$name: { value: ' + JSON.stringify(exported) + '},';
190
+ newSrc += '$$id: {value: ' + JSON.stringify(url + '#' + exported) + '},';
191
newSrc += '$$bound: { value: [] }';
192
newSrc += '});\n';
193
});
@@ -343,9 +342,8 @@ async function transformClientModule(
342
');';
343
}
344
newSrc += '},{';
346
- newSrc += 'name: { value: ' + JSON.stringify(name) + '},';
345
newSrc += '$$typeof: {value: CLIENT_REFERENCE},';
348
- newSrc += 'filepath: {value: ' + JSON.stringify(url) + '}';
346
+ newSrc += '$$id: {value: ' + JSON.stringify(url + '#' + name) + '}';
347
newSrc += '});\n';
348
}
349
return newSrc;
packages/react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js
+28
-50
@@ -29,8 +29,7 @@ module.exports = function register() {
29
// $FlowFixMe[method-unbinding]
30
const args = Array.prototype.slice.call(arguments, 1);
31
newFn.$$typeof = SERVER_REFERENCE;
32
- newFn.$$filepath = this.$$filepath;
33
- newFn.$$name = this.$$name;
32
+ newFn.$$id = this.$$id;
33
newFn.$$bound = this.$$bound.concat(args);
34
}
35
return newFn;
@@ -44,14 +43,14 @@ module.exports = function register() {
43
// These names are a little too common. We should probably have a way to
44
// have the Flight runtime extract the inner target instead.
45
return target.$$typeof;
47
- case 'filepath':
48
- return target.filepath;
46
+ case '$$id':
47
+ return target.$$id;
48
+ case '$$async':
49
+ return target.$$async;
50
case 'name':
51
return target.name;
52
case 'displayName':
53
return undefined;
53
- case 'async':
54
- return target.async;
54
// We need to special case this because createElement reads it if we pass this
55
// reference.
56
case 'defaultProps':
@@ -69,20 +68,8 @@ module.exports = function register() {
68
`that itself renders a Client Context Provider.`,
69
);
70
}
72
- let expression;
73
- switch (target.name) {
74
- case '':
75
- // eslint-disable-next-line react-internal/safe-string-coercion
76
- expression = String(name);
77
- break;
78
- case '*':
79
- // eslint-disable-next-line react-internal/safe-string-coercion
80
- expression = String(name);
81
- break;
82
- default:
83
- // eslint-disable-next-line react-internal/safe-string-coercion
84
- expression = String(target.name) + '.' + String(name);
85
- }
71
+ // eslint-disable-next-line react-internal/safe-string-coercion
72
+ const expression = String(target.name) + '.' + String(name);
73
throw new Error(
74
`Cannot access ${expression} on the server. ` +
75
'You cannot dot into a client module from a server component. ' +
@@ -103,15 +90,13 @@ module.exports = function register() {
90
switch (name) {
91
// These names are read by the Flight runtime if you end up using the exports object.
92
case '$$typeof':
106
- // These names are a little too common. We should probably have a way to
107
- // have the Flight runtime extract the inner target instead.
93
return target.$$typeof;
109
- case 'filepath':
110
- return target.filepath;
94
+ case '$$id':
95
+ return target.$$id;
96
+ case '$$async':
97
+ return target.$$async;
98
case 'name':
99
return target.name;
113
- case 'async':
114
- return target.async;
100
// We need to special case this because createElement reads it if we pass this
101
// reference.
102
case 'defaultProps':
@@ -125,7 +110,7 @@ module.exports = function register() {
110
case '__esModule':
111
// Something is conditionally checking which export to use. We'll pretend to be
112
// an ESM compat module but then we'll check again on the client.
128
- const moduleId = target.filepath;
113
+ const moduleId = target.$$id;
114
target.default = Object.defineProperties(
115
(function () {
116
throw new Error(
@@ -136,12 +121,11 @@ module.exports = function register() {
121
);
122
}: any),
123
{
124
+ $$typeof: {value: CLIENT_REFERENCE},
125
// This a placeholder value that tells the client to conditionally use the
126
// whole object or just the default export.
141
- name: {value: ''},
142
- $$typeof: {value: CLIENT_REFERENCE},
143
- filepath: {value: target.filepath},
144
- async: {value: target.async},
127
+ $$id: {value: target.$$id + '#'},
128
+ $$async: {value: target.$$async},
129
},
130
);
131
return true;
@@ -150,17 +134,15 @@ module.exports = function register() {
134
// Use a cached value
135
return target.then;
136
}
153
- if (!target.async) {
137
+ if (!target.$$async) {
138
// If this module is expected to return a Promise (such as an AsyncModule) then
139
// we should resolve that with a client reference that unwraps the Promise on
140
// the client.
141
142
const clientReference = Object.defineProperties(({}: any), {
159
- // Represents the whole Module object instead of a particular import.
160
- name: {value: '*'},
143
$$typeof: {value: CLIENT_REFERENCE},
162
- filepath: {value: target.filepath},
163
- async: {value: true},
144
+ $$id: {value: target.$$id},
145
+ $$async: {value: true},
146
});
147
const proxy = new Proxy(clientReference, proxyHandlers);
148
@@ -176,10 +158,9 @@ module.exports = function register() {
158
// If this is not used as a Promise but is treated as a reference to a `.then`
159
// export then we should treat it as a reference to that name.
160
{
179
- name: {value: 'then'},
161
$$typeof: {value: CLIENT_REFERENCE},
181
- filepath: {value: target.filepath},
182
- async: {value: false},
162
+ $$id: {value: target.$$id + '#then'},
163
+ $$async: {value: false},
164
},
165
));
166
return then;
@@ -206,8 +187,8 @@ module.exports = function register() {
187
{
188
name: {value: name},
189
$$typeof: {value: CLIENT_REFERENCE},
209
- filepath: {value: target.filepath},
210
- async: {value: target.async},
190
+ $$id: {value: target.$$id + '#' + name},
191
+ $$async: {value: target.$$async},
192
},
193
);
194
cachedReference = target[name] = new Proxy(
@@ -284,11 +265,10 @@ module.exports = function register() {
265
if (useClient) {
266
const moduleId: string = (url.pathToFileURL(filename).href: any);
267
const clientReference = Object.defineProperties(({}: any), {
287
- // Represents the whole Module object instead of a particular import.
288
- name: {value: '*'},
268
$$typeof: {value: CLIENT_REFERENCE},
290
- filepath: {value: moduleId},
291
- async: {value: false},
269
+ // Represents the whole Module object instead of a particular import.
270
+ $$id: {value: moduleId},
271
+ $$async: {value: false},
272
});
273
// $FlowFixMe[incompatible-call] found when upgrading Flow
274
this.exports = new Proxy(clientReference, proxyHandlers);
@@ -306,10 +286,9 @@ module.exports = function register() {
286
if (typeof exports === 'function') {
287
// The module exports a function directly,
288
Object.defineProperties((exports: any), {
309
- // Represents the whole Module object instead of a particular import.
289
$$typeof: {value: SERVER_REFERENCE},
311
- $$filepath: {value: moduleId},
312
- $$name: {value: '*'},
290
+ // Represents the whole Module object instead of a particular import.
291
+ $$id: {value: moduleId},
292
$$bound: {value: []},
293
});
294
} else {
@@ -320,8 +299,7 @@ module.exports = function register() {
299
if (typeof value === 'function') {
300
Object.defineProperties((value: any), {
301
$$typeof: {value: SERVER_REFERENCE},
323
- $$filepath: {value: moduleId},
324
- $$name: {value: key},
302
+ $$id: {value: moduleId + '#' + key},
303
$$bound: {value: []},
304
});
305
}
packages/react-server-dom-webpack/src/ReactFlightWebpackPlugin.js
+28
-20
@@ -220,9 +220,7 @@ export default class ReactFlightWebpackPlugin {
220
}
221
222
const clientManifest: {
223
- [string]: {
224
- [string]: {chunks: $FlowFixMe, id: string, name: string},
225
- },
223
+ [string]: {chunks: $FlowFixMe, id: string, name: string},
224
} = {};
225
const ssrManifest: {
226
[string]: {
@@ -248,25 +246,35 @@ export default class ReactFlightWebpackPlugin {
246
.getExportsInfo(module)
247
.getProvidedExports();
248
251
- const clientExports: {
252
- [string]: {chunks: $FlowFixMe, id: $FlowFixMe, name: string},
253
- } = {};
254
-
255
- const ssrExports: {
256
- [string]: {specifier: string, name: string},
257
- } = {};
258
-
249
const href = pathToFileURL(module.resource).href;
250
251
if (href !== undefined) {
262
- ['', '*']
263
- .concat(
264
- Array.isArray(moduleProvidedExports)
265
- ? moduleProvidedExports
266
- : [],
267
- )
268
- .forEach(function (name) {
269
- clientExports[name] = {
252
+ const ssrExports: {
253
+ [string]: {specifier: string, name: string},
254
+ } = {};
255
+
256
+ clientManifest[href] = {
257
+ id,
258
+ chunks: chunkIds,
259
+ name: '*',
260
+ };
261
+ ssrExports['*'] = {
262
+ specifier: href,
263
+ name: '*',
264
+ };
265
+ clientManifest[href + '#'] = {
266
+ id,
267
+ chunks: chunkIds,
268
+ name: '',
269
+ };
270
+ ssrExports[''] = {
271
+ specifier: href,
272
+ name: '',
273
+ };
274
+
275
+ if (Array.isArray(moduleProvidedExports)) {
276
+ moduleProvidedExports.forEach(function (name) {
277
+ clientManifest[href + '#' + name] = {
278
id,
279
chunks: chunkIds,
280
name: name,
@@ -276,8 +284,8 @@ export default class ReactFlightWebpackPlugin {
284
name: name,
285
};
286
});
287
+ }
288
280
- clientManifest[href] = clientExports;
289
ssrManifest[id] = ssrExports;
290
}
291
}
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMBrowser-test.js
+1
-1
@@ -755,7 +755,7 @@ describe('ReactFlightDOMBrowser', () => {
755
});
756
757
function requireServerRef(ref) {
758
- const metaData = webpackServerMap[ref.id][ref.name];
758
+ const metaData = webpackServerMap[ref];
759
const mod = __webpack_require__(metaData.id);
760
if (metaData.name === '*') {
761
return mod;
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMEdge-test.js
+2
-2
@@ -61,12 +61,12 @@ describe('ReactFlightDOMEdge', () => {
61
const ClientComponentOnTheServer = clientExports(ClientComponent);
62
63
// In the SSR bundle this module won't exist. We simulate this by deleting it.
64
- const clientId = webpackMap[ClientComponentOnTheClient.filepath]['*'].id;
64
+ const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;
65
delete webpackModules[clientId];
66
67
// Instead, we have to provide a translation from the client meta data to the SSR
68
// meta data.
69
- const ssrMetadata = webpackMap[ClientComponentOnTheServer.filepath]['*'];
69
+ const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];
70
const translationMap = {
71
[clientId]: {
72
'*': ssrMetadata,
packages/react-server-dom-webpack/src/__tests__/ReactFlightDOMNode-test.js
+2
-2
@@ -67,12 +67,12 @@ describe('ReactFlightDOMNode', () => {
67
const ClientComponentOnTheServer = clientExports(ClientComponent);
68
69
// In the SSR bundle this module won't exist. We simulate this by deleting it.
70
- const clientId = webpackMap[ClientComponentOnTheClient.filepath]['*'].id;
70
+ const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;
71
delete webpackModules[clientId];
72
73
// Instead, we have to provide a translation from the client meta data to the SSR
74
// meta data.
75
- const ssrMetadata = webpackMap[ClientComponentOnTheServer.filepath]['*'];
75
+ const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];
76
const translationMap = {
77
[clientId]: {
78
'*': ssrMetadata,
packages/react-server-dom-webpack/src/__tests__/utils/WebpackMock.js
+27
-33
@@ -48,16 +48,14 @@ exports.clientModuleError = function clientModuleError(moduleError) {
48
webpackErroredModules[idx] = moduleError;
49
const path = url.pathToFileURL(idx).href;
50
webpackClientMap[path] = {
51
- '': {
52
- id: idx,
53
- chunks: [],
54
- name: '',
55
- },
56
- '*': {
57
- id: idx,
58
- chunks: [],
59
- name: '*',
60
- },
51
+ id: idx,
52
+ chunks: [],
53
+ name: '*',
54
+ };
55
+ webpackClientMap[path + '#'] = {
56
+ id: idx,
57
+ chunks: [],
58
+ name: '',
59
};
60
const mod = {exports: {}};
61
nodeCompile.call(mod, '"use client"', idx);
@@ -69,22 +67,20 @@ exports.clientExports = function clientExports(moduleExports) {
67
webpackClientModules[idx] = moduleExports;
68
const path = url.pathToFileURL(idx).href;
69
webpackClientMap[path] = {
72
- '': {
73
- id: idx,
74
- chunks: [],
75
- name: '',
76
- },
77
- '*': {
78
- id: idx,
79
- chunks: [],
80
- name: '*',
81
- },
70
+ id: idx,
71
+ chunks: [],
72
+ name: '*',
73
+ };
74
+ webpackClientMap[path + '#'] = {
75
+ id: idx,
76
+ chunks: [],
77
+ name: '',
78
};
79
if (typeof moduleExports.then === 'function') {
80
moduleExports.then(
81
asyncModuleExports => {
82
for (const name in asyncModuleExports) {
87
- webpackClientMap[path][name] = {
83
+ webpackClientMap[path + '#' + name] = {
84
id: idx,
85
chunks: [],
86
name: name,
@@ -95,7 +91,7 @@ exports.clientExports = function clientExports(moduleExports) {
91
);
92
}
93
for (const name in moduleExports) {
98
- webpackClientMap[path][name] = {
94
+ webpackClientMap[path + '#' + name] = {
95
id: idx,
96
chunks: [],
97
name: name,
@@ -112,19 +108,17 @@ exports.serverExports = function serverExports(moduleExports) {
108
webpackServerModules[idx] = moduleExports;
109
const path = url.pathToFileURL(idx).href;
110
webpackServerMap[path] = {
115
- '': {
116
- id: idx,
117
- chunks: [],
118
- name: '',
119
- },
120
- '*': {
121
- id: idx,
122
- chunks: [],
123
- name: '*',
124
- },
111
+ id: idx,
112
+ chunks: [],
113
+ name: '*',
114
+ };
115
+ webpackServerMap[path + '#'] = {
116
+ id: idx,
117
+ chunks: [],
118
+ name: '',
119
};
120
for (const name in moduleExports) {
127
- webpackServerMap[path][name] = {
121
+ webpackServerMap[path + '#' + name] = {
122
id: idx,
123
chunks: [],
124
name: name,
packages/react-server-native-relay/src/ReactFlightNativeRelayServerHostConfig.js
+2
-2
@@ -16,7 +16,7 @@ import JSResourceReferenceImpl from 'JSResourceReferenceImpl';
16
17
export type ClientReference<T> = JSResourceReference<T>;
18
export type ServerReference<T> = T;
19
-export type ServerReferenceMetadata = {};
19
+export type ServerReferenceId = {};
20
21
import type {
22
Destination,
@@ -66,7 +66,7 @@ export function resolveClientReferenceMetadata<T>(
66
export function resolveServerReferenceMetadata<T>(
67
config: BundlerConfig,
68
resource: ServerReference<T>,
69
-): ServerReferenceMetadata {
69
+): {id: ServerReferenceId, bound: Promise<Array<any>>} {
70
throw new Error('Not implemented.');
71
}
72
packages/react-server/src/ReactFlightServer.js
+5
-3
@@ -15,7 +15,7 @@ import type {
15
ClientReference,
16
ClientReferenceKey,
17
ServerReference,
18
- ServerReferenceMetadata,
18
+ ServerReferenceId,
19
} from './ReactFlightServerConfig';
20
import type {ContextSnapshot} from './ReactFlightNewContext';
21
import type {ThenableState} from './ReactFlightThenable';
@@ -590,8 +590,10 @@ function serializeServerReference(
590
if (existingId !== undefined) {
591
return serializeServerReferenceID(existingId);
592
}
593
- const serverReferenceMetadata: ServerReferenceMetadata =
594
- resolveServerReferenceMetadata(request.bundlerConfig, serverReference);
593
+ const serverReferenceMetadata: {
594
+ id: ServerReferenceId,
595
+ bound: Promise<Array<any>>,
596
+ } = resolveServerReferenceMetadata(request.bundlerConfig, serverReference);
597
request.pendingChunks++;
598
const metadataId = request.nextChunkId++;
599
// We assume that this object doesn't suspend.
packages/react-server/src/ReactFlightServerBundlerConfigCustom.js
+1
-1
@@ -13,7 +13,7 @@ export opaque type BundlerConfig = mixed;
13
export opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars
14
export opaque type ServerReference<T> = mixed; // eslint-disable-line no-unused-vars
15
export opaque type ClientReferenceMetadata: any = mixed;
16
-export opaque type ServerReferenceMetadata: any = mixed;
16
+export opaque type ServerReferenceId: any = mixed;
17
export opaque type ClientReferenceKey: any = mixed;
18
export const isClientReference = $$$hostConfig.isClientReference;
19
export const isServerReference = $$$hostConfig.isServerReference;