mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
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.
This commit is contained in:
parent
25685d8a90
commit
e0241b6600
BIN
fixtures/flight/public/favicon.ico
Normal file
BIN
fixtures/flight/public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
|
|
@ -98,8 +98,8 @@ app.post('/', bodyParser.text(), async function (req, res) {
|
|||
const {renderToPipeableStream} = await import(
|
||||
'react-server-dom-webpack/server'
|
||||
);
|
||||
const serverReference = JSON.parse(req.get('rsc-action'));
|
||||
const {filepath, name} = serverReference;
|
||||
const serverReference = req.get('rsc-action');
|
||||
const [filepath, name] = serverReference.split('#');
|
||||
const action = (await import(filepath))[name];
|
||||
// Validate that this is actually a function we intended to expose and
|
||||
// not the client trying to invoke arbitrary functions. In a real app,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ let data = ReactServerDOMReader.createFromFetch(
|
|||
method: 'POST',
|
||||
headers: {
|
||||
Accept: 'text/x-component',
|
||||
'rsc-action': JSON.stringify({filepath: id.id, name: id.name}),
|
||||
'rsc-action': id,
|
||||
},
|
||||
body: JSON.stringify(args),
|
||||
});
|
||||
|
|
|
|||
10
packages/react-client/src/ReactFlightClient.js
vendored
10
packages/react-client/src/ReactFlightClient.js
vendored
|
|
@ -473,7 +473,7 @@ function createModelReject<T>(chunk: SomeChunk<T>): (error: mixed) => void {
|
|||
|
||||
function createServerReferenceProxy<A: Iterable<any>, T>(
|
||||
response: Response,
|
||||
metaData: any,
|
||||
metaData: {id: any, bound: Thenable<Array<any>>},
|
||||
): (...A) => Promise<T> {
|
||||
const callServer = response._callServer;
|
||||
const proxy = function (): Promise<T> {
|
||||
|
|
@ -482,12 +482,14 @@ function createServerReferenceProxy<A: Iterable<any>, T>(
|
|||
const p = metaData.bound;
|
||||
if (p.status === INITIALIZED) {
|
||||
const bound = p.value;
|
||||
return callServer(metaData, bound.concat(args));
|
||||
return callServer(metaData.id, bound.concat(args));
|
||||
}
|
||||
// Since this is a fake Promise whose .then doesn't chain, we have to wrap it.
|
||||
// TODO: Remove the wrapper once that's fixed.
|
||||
return Promise.resolve(p).then(function (bound) {
|
||||
return callServer(metaData, bound.concat(args));
|
||||
return ((Promise.resolve(p): any): Promise<Array<any>>).then(function (
|
||||
bound,
|
||||
) {
|
||||
return callServer(metaData.id, bound.concat(args));
|
||||
});
|
||||
};
|
||||
return proxy;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import isArray from 'shared/isArray';
|
|||
|
||||
export type ClientReference<T> = JSResourceReference<T>;
|
||||
export type ServerReference<T> = T;
|
||||
export type ServerReferenceMetadata = {};
|
||||
export type ServerReferenceId = {};
|
||||
|
||||
import type {
|
||||
Destination,
|
||||
|
|
@ -69,7 +69,7 @@ export function resolveClientReferenceMetadata<T>(
|
|||
export function resolveServerReferenceMetadata<T>(
|
||||
config: BundlerConfig,
|
||||
resource: ServerReference<T>,
|
||||
): ServerReferenceMetadata {
|
||||
): {id: ServerReferenceId, bound: Promise<Array<any>>} {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ export opaque type ClientReferenceMetadata = {
|
|||
id: string,
|
||||
chunks: Array<string>,
|
||||
name: string,
|
||||
async: boolean,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
|
|
|
|||
|
|
@ -20,10 +20,7 @@ import {
|
|||
close,
|
||||
} from 'react-client/src/ReactFlightClientStream';
|
||||
|
||||
type CallServerCallback = <A, T>(
|
||||
{filepath: string, name: string},
|
||||
args: A,
|
||||
) => Promise<T>;
|
||||
type CallServerCallback = <A, T>(string, args: A) => Promise<T>;
|
||||
|
||||
export type Options = {
|
||||
callServer?: CallServerCallback,
|
||||
|
|
|
|||
|
|
@ -10,32 +10,24 @@
|
|||
import type {ReactModel} from 'react-server/src/ReactFlightServer';
|
||||
|
||||
type WebpackMap = {
|
||||
[filepath: string]: {
|
||||
[name: string]: ClientReferenceMetadata,
|
||||
},
|
||||
[id: string]: ClientReferenceMetadata,
|
||||
};
|
||||
|
||||
export type BundlerConfig = WebpackMap;
|
||||
|
||||
export type ServerReference<T: Function> = T & {
|
||||
$$typeof: symbol,
|
||||
$$filepath: string,
|
||||
$$name: string,
|
||||
$$id: string,
|
||||
$$bound: Array<ReactModel>,
|
||||
};
|
||||
|
||||
export type ServerReferenceMetadata = {
|
||||
id: string,
|
||||
name: string,
|
||||
bound: Promise<Array<ReactModel>>,
|
||||
};
|
||||
export type ServerReferenceId = string;
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
export type ClientReference<T> = {
|
||||
$$typeof: symbol,
|
||||
filepath: string,
|
||||
name: string,
|
||||
async: boolean,
|
||||
$$id: string,
|
||||
$$async: boolean,
|
||||
};
|
||||
|
||||
export type ClientReferenceMetadata = {
|
||||
|
|
@ -53,12 +45,7 @@ const SERVER_REFERENCE_TAG = Symbol.for('react.server.reference');
|
|||
export function getClientReferenceKey(
|
||||
reference: ClientReference<any>,
|
||||
): ClientReferenceKey {
|
||||
return (
|
||||
reference.filepath +
|
||||
'#' +
|
||||
reference.name +
|
||||
(reference.async ? '#async' : '')
|
||||
);
|
||||
return reference.$$async ? reference.$$id + '#async' : reference.$$id;
|
||||
}
|
||||
|
||||
export function isClientReference(reference: Object): boolean {
|
||||
|
|
@ -73,9 +60,8 @@ export function resolveClientReferenceMetadata<T>(
|
|||
config: BundlerConfig,
|
||||
clientReference: ClientReference<T>,
|
||||
): ClientReferenceMetadata {
|
||||
const resolvedModuleData =
|
||||
config[clientReference.filepath][clientReference.name];
|
||||
if (clientReference.async) {
|
||||
const resolvedModuleData = config[clientReference.$$id];
|
||||
if (clientReference.$$async) {
|
||||
return {
|
||||
id: resolvedModuleData.id,
|
||||
chunks: resolvedModuleData.chunks,
|
||||
|
|
@ -90,10 +76,9 @@ export function resolveClientReferenceMetadata<T>(
|
|||
export function resolveServerReferenceMetadata<T>(
|
||||
config: BundlerConfig,
|
||||
serverReference: ServerReference<T>,
|
||||
): ServerReferenceMetadata {
|
||||
): {id: ServerReferenceId, bound: Promise<Array<any>>} {
|
||||
return {
|
||||
id: serverReference.$$filepath,
|
||||
name: serverReference.$$name,
|
||||
id: serverReference.$$id,
|
||||
bound: Promise.resolve(serverReference.$$bound),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,8 +187,7 @@ function transformServerModule(
|
|||
}
|
||||
newSrc += 'Object.defineProperties(' + local + ',{';
|
||||
newSrc += '$$typeof: {value: Symbol.for("react.server.reference")},';
|
||||
newSrc += '$$filepath: {value: ' + JSON.stringify(url) + '},';
|
||||
newSrc += '$$name: { value: ' + JSON.stringify(exported) + '},';
|
||||
newSrc += '$$id: {value: ' + JSON.stringify(url + '#' + exported) + '},';
|
||||
newSrc += '$$bound: { value: [] }';
|
||||
newSrc += '});\n';
|
||||
});
|
||||
|
|
@ -343,9 +342,8 @@ async function transformClientModule(
|
|||
');';
|
||||
}
|
||||
newSrc += '},{';
|
||||
newSrc += 'name: { value: ' + JSON.stringify(name) + '},';
|
||||
newSrc += '$$typeof: {value: CLIENT_REFERENCE},';
|
||||
newSrc += 'filepath: {value: ' + JSON.stringify(url) + '}';
|
||||
newSrc += '$$id: {value: ' + JSON.stringify(url + '#' + name) + '}';
|
||||
newSrc += '});\n';
|
||||
}
|
||||
return newSrc;
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@ module.exports = function register() {
|
|||
// $FlowFixMe[method-unbinding]
|
||||
const args = Array.prototype.slice.call(arguments, 1);
|
||||
newFn.$$typeof = SERVER_REFERENCE;
|
||||
newFn.$$filepath = this.$$filepath;
|
||||
newFn.$$name = this.$$name;
|
||||
newFn.$$id = this.$$id;
|
||||
newFn.$$bound = this.$$bound.concat(args);
|
||||
}
|
||||
return newFn;
|
||||
|
|
@ -44,14 +43,14 @@ module.exports = function register() {
|
|||
// These names are a little too common. We should probably have a way to
|
||||
// have the Flight runtime extract the inner target instead.
|
||||
return target.$$typeof;
|
||||
case 'filepath':
|
||||
return target.filepath;
|
||||
case '$$id':
|
||||
return target.$$id;
|
||||
case '$$async':
|
||||
return target.$$async;
|
||||
case 'name':
|
||||
return target.name;
|
||||
case 'displayName':
|
||||
return undefined;
|
||||
case 'async':
|
||||
return target.async;
|
||||
// We need to special case this because createElement reads it if we pass this
|
||||
// reference.
|
||||
case 'defaultProps':
|
||||
|
|
@ -69,20 +68,8 @@ module.exports = function register() {
|
|||
`that itself renders a Client Context Provider.`,
|
||||
);
|
||||
}
|
||||
let expression;
|
||||
switch (target.name) {
|
||||
case '':
|
||||
// eslint-disable-next-line react-internal/safe-string-coercion
|
||||
expression = String(name);
|
||||
break;
|
||||
case '*':
|
||||
// eslint-disable-next-line react-internal/safe-string-coercion
|
||||
expression = String(name);
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line react-internal/safe-string-coercion
|
||||
expression = String(target.name) + '.' + String(name);
|
||||
}
|
||||
// eslint-disable-next-line react-internal/safe-string-coercion
|
||||
const expression = String(target.name) + '.' + String(name);
|
||||
throw new Error(
|
||||
`Cannot access ${expression} on the server. ` +
|
||||
'You cannot dot into a client module from a server component. ' +
|
||||
|
|
@ -103,15 +90,13 @@ module.exports = function register() {
|
|||
switch (name) {
|
||||
// These names are read by the Flight runtime if you end up using the exports object.
|
||||
case '$$typeof':
|
||||
// These names are a little too common. We should probably have a way to
|
||||
// have the Flight runtime extract the inner target instead.
|
||||
return target.$$typeof;
|
||||
case 'filepath':
|
||||
return target.filepath;
|
||||
case '$$id':
|
||||
return target.$$id;
|
||||
case '$$async':
|
||||
return target.$$async;
|
||||
case 'name':
|
||||
return target.name;
|
||||
case 'async':
|
||||
return target.async;
|
||||
// We need to special case this because createElement reads it if we pass this
|
||||
// reference.
|
||||
case 'defaultProps':
|
||||
|
|
@ -125,7 +110,7 @@ module.exports = function register() {
|
|||
case '__esModule':
|
||||
// Something is conditionally checking which export to use. We'll pretend to be
|
||||
// an ESM compat module but then we'll check again on the client.
|
||||
const moduleId = target.filepath;
|
||||
const moduleId = target.$$id;
|
||||
target.default = Object.defineProperties(
|
||||
(function () {
|
||||
throw new Error(
|
||||
|
|
@ -136,12 +121,11 @@ module.exports = function register() {
|
|||
);
|
||||
}: any),
|
||||
{
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
// This a placeholder value that tells the client to conditionally use the
|
||||
// whole object or just the default export.
|
||||
name: {value: ''},
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
filepath: {value: target.filepath},
|
||||
async: {value: target.async},
|
||||
$$id: {value: target.$$id + '#'},
|
||||
$$async: {value: target.$$async},
|
||||
},
|
||||
);
|
||||
return true;
|
||||
|
|
@ -150,17 +134,15 @@ module.exports = function register() {
|
|||
// Use a cached value
|
||||
return target.then;
|
||||
}
|
||||
if (!target.async) {
|
||||
if (!target.$$async) {
|
||||
// If this module is expected to return a Promise (such as an AsyncModule) then
|
||||
// we should resolve that with a client reference that unwraps the Promise on
|
||||
// the client.
|
||||
|
||||
const clientReference = Object.defineProperties(({}: any), {
|
||||
// Represents the whole Module object instead of a particular import.
|
||||
name: {value: '*'},
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
filepath: {value: target.filepath},
|
||||
async: {value: true},
|
||||
$$id: {value: target.$$id},
|
||||
$$async: {value: true},
|
||||
});
|
||||
const proxy = new Proxy(clientReference, proxyHandlers);
|
||||
|
||||
|
|
@ -176,10 +158,9 @@ module.exports = function register() {
|
|||
// If this is not used as a Promise but is treated as a reference to a `.then`
|
||||
// export then we should treat it as a reference to that name.
|
||||
{
|
||||
name: {value: 'then'},
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
filepath: {value: target.filepath},
|
||||
async: {value: false},
|
||||
$$id: {value: target.$$id + '#then'},
|
||||
$$async: {value: false},
|
||||
},
|
||||
));
|
||||
return then;
|
||||
|
|
@ -206,8 +187,8 @@ module.exports = function register() {
|
|||
{
|
||||
name: {value: name},
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
filepath: {value: target.filepath},
|
||||
async: {value: target.async},
|
||||
$$id: {value: target.$$id + '#' + name},
|
||||
$$async: {value: target.$$async},
|
||||
},
|
||||
);
|
||||
cachedReference = target[name] = new Proxy(
|
||||
|
|
@ -284,11 +265,10 @@ module.exports = function register() {
|
|||
if (useClient) {
|
||||
const moduleId: string = (url.pathToFileURL(filename).href: any);
|
||||
const clientReference = Object.defineProperties(({}: any), {
|
||||
// Represents the whole Module object instead of a particular import.
|
||||
name: {value: '*'},
|
||||
$$typeof: {value: CLIENT_REFERENCE},
|
||||
filepath: {value: moduleId},
|
||||
async: {value: false},
|
||||
// Represents the whole Module object instead of a particular import.
|
||||
$$id: {value: moduleId},
|
||||
$$async: {value: false},
|
||||
});
|
||||
// $FlowFixMe[incompatible-call] found when upgrading Flow
|
||||
this.exports = new Proxy(clientReference, proxyHandlers);
|
||||
|
|
@ -306,10 +286,9 @@ module.exports = function register() {
|
|||
if (typeof exports === 'function') {
|
||||
// The module exports a function directly,
|
||||
Object.defineProperties((exports: any), {
|
||||
// Represents the whole Module object instead of a particular import.
|
||||
$$typeof: {value: SERVER_REFERENCE},
|
||||
$$filepath: {value: moduleId},
|
||||
$$name: {value: '*'},
|
||||
// Represents the whole Module object instead of a particular import.
|
||||
$$id: {value: moduleId},
|
||||
$$bound: {value: []},
|
||||
});
|
||||
} else {
|
||||
|
|
@ -320,8 +299,7 @@ module.exports = function register() {
|
|||
if (typeof value === 'function') {
|
||||
Object.defineProperties((value: any), {
|
||||
$$typeof: {value: SERVER_REFERENCE},
|
||||
$$filepath: {value: moduleId},
|
||||
$$name: {value: key},
|
||||
$$id: {value: moduleId + '#' + key},
|
||||
$$bound: {value: []},
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,9 +220,7 @@ export default class ReactFlightWebpackPlugin {
|
|||
}
|
||||
|
||||
const clientManifest: {
|
||||
[string]: {
|
||||
[string]: {chunks: $FlowFixMe, id: string, name: string},
|
||||
},
|
||||
[string]: {chunks: $FlowFixMe, id: string, name: string},
|
||||
} = {};
|
||||
const ssrManifest: {
|
||||
[string]: {
|
||||
|
|
@ -248,25 +246,35 @@ export default class ReactFlightWebpackPlugin {
|
|||
.getExportsInfo(module)
|
||||
.getProvidedExports();
|
||||
|
||||
const clientExports: {
|
||||
[string]: {chunks: $FlowFixMe, id: $FlowFixMe, name: string},
|
||||
} = {};
|
||||
|
||||
const ssrExports: {
|
||||
[string]: {specifier: string, name: string},
|
||||
} = {};
|
||||
|
||||
const href = pathToFileURL(module.resource).href;
|
||||
|
||||
if (href !== undefined) {
|
||||
['', '*']
|
||||
.concat(
|
||||
Array.isArray(moduleProvidedExports)
|
||||
? moduleProvidedExports
|
||||
: [],
|
||||
)
|
||||
.forEach(function (name) {
|
||||
clientExports[name] = {
|
||||
const ssrExports: {
|
||||
[string]: {specifier: string, name: string},
|
||||
} = {};
|
||||
|
||||
clientManifest[href] = {
|
||||
id,
|
||||
chunks: chunkIds,
|
||||
name: '*',
|
||||
};
|
||||
ssrExports['*'] = {
|
||||
specifier: href,
|
||||
name: '*',
|
||||
};
|
||||
clientManifest[href + '#'] = {
|
||||
id,
|
||||
chunks: chunkIds,
|
||||
name: '',
|
||||
};
|
||||
ssrExports[''] = {
|
||||
specifier: href,
|
||||
name: '',
|
||||
};
|
||||
|
||||
if (Array.isArray(moduleProvidedExports)) {
|
||||
moduleProvidedExports.forEach(function (name) {
|
||||
clientManifest[href + '#' + name] = {
|
||||
id,
|
||||
chunks: chunkIds,
|
||||
name: name,
|
||||
|
|
@ -276,8 +284,8 @@ export default class ReactFlightWebpackPlugin {
|
|||
name: name,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
clientManifest[href] = clientExports;
|
||||
ssrManifest[id] = ssrExports;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -755,7 +755,7 @@ describe('ReactFlightDOMBrowser', () => {
|
|||
});
|
||||
|
||||
function requireServerRef(ref) {
|
||||
const metaData = webpackServerMap[ref.id][ref.name];
|
||||
const metaData = webpackServerMap[ref];
|
||||
const mod = __webpack_require__(metaData.id);
|
||||
if (metaData.name === '*') {
|
||||
return mod;
|
||||
|
|
|
|||
|
|
@ -61,12 +61,12 @@ describe('ReactFlightDOMEdge', () => {
|
|||
const ClientComponentOnTheServer = clientExports(ClientComponent);
|
||||
|
||||
// In the SSR bundle this module won't exist. We simulate this by deleting it.
|
||||
const clientId = webpackMap[ClientComponentOnTheClient.filepath]['*'].id;
|
||||
const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;
|
||||
delete webpackModules[clientId];
|
||||
|
||||
// Instead, we have to provide a translation from the client meta data to the SSR
|
||||
// meta data.
|
||||
const ssrMetadata = webpackMap[ClientComponentOnTheServer.filepath]['*'];
|
||||
const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];
|
||||
const translationMap = {
|
||||
[clientId]: {
|
||||
'*': ssrMetadata,
|
||||
|
|
|
|||
|
|
@ -67,12 +67,12 @@ describe('ReactFlightDOMNode', () => {
|
|||
const ClientComponentOnTheServer = clientExports(ClientComponent);
|
||||
|
||||
// In the SSR bundle this module won't exist. We simulate this by deleting it.
|
||||
const clientId = webpackMap[ClientComponentOnTheClient.filepath]['*'].id;
|
||||
const clientId = webpackMap[ClientComponentOnTheClient.$$id].id;
|
||||
delete webpackModules[clientId];
|
||||
|
||||
// Instead, we have to provide a translation from the client meta data to the SSR
|
||||
// meta data.
|
||||
const ssrMetadata = webpackMap[ClientComponentOnTheServer.filepath]['*'];
|
||||
const ssrMetadata = webpackMap[ClientComponentOnTheServer.$$id];
|
||||
const translationMap = {
|
||||
[clientId]: {
|
||||
'*': ssrMetadata,
|
||||
|
|
|
|||
|
|
@ -48,16 +48,14 @@ exports.clientModuleError = function clientModuleError(moduleError) {
|
|||
webpackErroredModules[idx] = moduleError;
|
||||
const path = url.pathToFileURL(idx).href;
|
||||
webpackClientMap[path] = {
|
||||
'': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
},
|
||||
'*': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
},
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
};
|
||||
webpackClientMap[path + '#'] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
};
|
||||
const mod = {exports: {}};
|
||||
nodeCompile.call(mod, '"use client"', idx);
|
||||
|
|
@ -69,22 +67,20 @@ exports.clientExports = function clientExports(moduleExports) {
|
|||
webpackClientModules[idx] = moduleExports;
|
||||
const path = url.pathToFileURL(idx).href;
|
||||
webpackClientMap[path] = {
|
||||
'': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
},
|
||||
'*': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
},
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
};
|
||||
webpackClientMap[path + '#'] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
};
|
||||
if (typeof moduleExports.then === 'function') {
|
||||
moduleExports.then(
|
||||
asyncModuleExports => {
|
||||
for (const name in asyncModuleExports) {
|
||||
webpackClientMap[path][name] = {
|
||||
webpackClientMap[path + '#' + name] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: name,
|
||||
|
|
@ -95,7 +91,7 @@ exports.clientExports = function clientExports(moduleExports) {
|
|||
);
|
||||
}
|
||||
for (const name in moduleExports) {
|
||||
webpackClientMap[path][name] = {
|
||||
webpackClientMap[path + '#' + name] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: name,
|
||||
|
|
@ -112,19 +108,17 @@ exports.serverExports = function serverExports(moduleExports) {
|
|||
webpackServerModules[idx] = moduleExports;
|
||||
const path = url.pathToFileURL(idx).href;
|
||||
webpackServerMap[path] = {
|
||||
'': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
},
|
||||
'*': {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
},
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '*',
|
||||
};
|
||||
webpackServerMap[path + '#'] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: '',
|
||||
};
|
||||
for (const name in moduleExports) {
|
||||
webpackServerMap[path][name] = {
|
||||
webpackServerMap[path + '#' + name] = {
|
||||
id: idx,
|
||||
chunks: [],
|
||||
name: name,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import JSResourceReferenceImpl from 'JSResourceReferenceImpl';
|
|||
|
||||
export type ClientReference<T> = JSResourceReference<T>;
|
||||
export type ServerReference<T> = T;
|
||||
export type ServerReferenceMetadata = {};
|
||||
export type ServerReferenceId = {};
|
||||
|
||||
import type {
|
||||
Destination,
|
||||
|
|
@ -66,7 +66,7 @@ export function resolveClientReferenceMetadata<T>(
|
|||
export function resolveServerReferenceMetadata<T>(
|
||||
config: BundlerConfig,
|
||||
resource: ServerReference<T>,
|
||||
): ServerReferenceMetadata {
|
||||
): {id: ServerReferenceId, bound: Promise<Array<any>>} {
|
||||
throw new Error('Not implemented.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import type {
|
|||
ClientReference,
|
||||
ClientReferenceKey,
|
||||
ServerReference,
|
||||
ServerReferenceMetadata,
|
||||
ServerReferenceId,
|
||||
} from './ReactFlightServerConfig';
|
||||
import type {ContextSnapshot} from './ReactFlightNewContext';
|
||||
import type {ThenableState} from './ReactFlightThenable';
|
||||
|
|
@ -590,8 +590,10 @@ function serializeServerReference(
|
|||
if (existingId !== undefined) {
|
||||
return serializeServerReferenceID(existingId);
|
||||
}
|
||||
const serverReferenceMetadata: ServerReferenceMetadata =
|
||||
resolveServerReferenceMetadata(request.bundlerConfig, serverReference);
|
||||
const serverReferenceMetadata: {
|
||||
id: ServerReferenceId,
|
||||
bound: Promise<Array<any>>,
|
||||
} = resolveServerReferenceMetadata(request.bundlerConfig, serverReference);
|
||||
request.pendingChunks++;
|
||||
const metadataId = request.nextChunkId++;
|
||||
// We assume that this object doesn't suspend.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ export opaque type BundlerConfig = mixed;
|
|||
export opaque type ClientReference<T> = mixed; // eslint-disable-line no-unused-vars
|
||||
export opaque type ServerReference<T> = mixed; // eslint-disable-line no-unused-vars
|
||||
export opaque type ClientReferenceMetadata: any = mixed;
|
||||
export opaque type ServerReferenceMetadata: any = mixed;
|
||||
export opaque type ServerReferenceId: any = mixed;
|
||||
export opaque type ClientReferenceKey: any = mixed;
|
||||
export const isClientReference = $$$hostConfig.isClientReference;
|
||||
export const isServerReference = $$$hostConfig.isServerReference;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user