Skip to content

Commit

Permalink
Wire up bundler configs
Browse files Browse the repository at this point in the history
This allows different flight server and clients to have different configs
depending on bundler to serialize and resolve modules.
  • Loading branch information
sebmarkbage committed Mar 18, 2020
1 parent aae83a4 commit 0d94205
Show file tree
Hide file tree
Showing 26 changed files with 259 additions and 32 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ module.exports = {
nativeFabricUIManager: true,
},
},
{
files: ['packages/react-flight-dom-webpack/**/*.js'],
globals: {
'__webpack_chunk_load__': true,
},
},
],

globals: {
Expand Down
7 changes: 7 additions & 0 deletions packages/react-client/src/ReactFlightClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@

import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';

// import type {ModuleMetaData} from './ReactFlightClientHostConfig';

// import {
// requireModuleIfAvailable,
// waitForModule,
// } from './ReactFlightClientHostConfig';

export type ReactModelRoot<T> = {|
model: T,
|};
Expand Down
30 changes: 30 additions & 0 deletions packages/react-client/src/ReactFlightClientHostConfigNoStream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export type StringDecoder = void;

export const supportsBinaryStreams = false;

export function createStringDecoder(): void {
throw new Error('Should never be called');
}

export function readPartialStringChunk(
decoder: StringDecoder,
buffer: Uint8Array,
): string {
throw new Error('Should never be called');
}

export function readFinalStringChunk(
decoder: StringDecoder,
buffer: Uint8Array,
): string {
throw new Error('Should never be called');
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@
// really an argument to a top-level wrapping function.

declare var $$$hostConfig: any;

export opaque type ModuleMetaData = mixed; // eslint-disable-line no-undef
export const requireModuleIfAvailable = $$$hostConfig.requireModuleIfAvailable;
export const waitForModule = $$$hostConfig.waitForModule;

export opaque type Source = mixed; // eslint-disable-line no-undef
export opaque type StringDecoder = mixed; // eslint-disable-line no-undef

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-client/src/ReactFlightClientHostConfigBrowser';
export * from 'react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig';
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig';
export * from '../ReactFlightClientHostConfigNoStream';
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
*/

export * from 'react-client/src/ReactFlightClientHostConfigBrowser';
export * from 'react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig';
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,9 @@
* @flow
*/

export type StringDecoder = void;
export {
requireModuleIfAvailable,
waitForModule,
} from 'ReactFlightDOMRelayClientIntegration';

export const supportsBinaryStreams = false;

export function createStringDecoder(): void {
throw new Error('Should never be called');
}

export function readPartialStringChunk(
decoder: StringDecoder,
buffer: Uint8Array,
): string {
throw new Error('Should never be called');
}

export function readFinalStringChunk(
decoder: StringDecoder,
buffer: Uint8Array,
): string {
throw new Error('Should never be called');
}
export type {ModuleMetaData} from 'ReactFlightDOMRelayClientIntegration';
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {Destination} from './ReactFlightDOMRelayServerHostConfig';
import {createRequest, startWork} from 'react-server/src/ReactFlightServer';

function render(model: ReactModel, destination: Destination): void {
let request = createRequest(model, destination);
let request = createRequest(model, destination, undefined);
startWork(request);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,34 @@

import type {Request, ReactModel} from 'react-server/src/ReactFlightServer';

import type {Destination} from 'ReactFlightDOMRelayServerIntegration';
import type {
Destination,
ModuleReference,
ModuleMetaData,
} from 'ReactFlightDOMRelayServerIntegration';

import {resolveModelToJSON} from 'react-server/src/ReactFlightServer';

import {emitModel, emitError} from 'ReactFlightDOMRelayServerIntegration';

export type {Destination} from 'ReactFlightDOMRelayServerIntegration';
import {
emitModel,
emitError,
resolveResourceMetaData,
} from 'ReactFlightDOMRelayServerIntegration';

export type {
Destination,
ModuleReference,
ModuleMetaData,
} from 'ReactFlightDOMRelayServerIntegration';

export type BundlerConfig = void;

export function resolveModuleMetaData(
config: BundlerConfig,
resource: ModuleReference,
): ModuleMetaData {
return resolveResourceMetaData(resource);
}

type JSONValue =
| string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

function getFakeModule() {
return function FakeModule(props, data) {
return data;
};
}

const ReactFlightDOMRelayClientIntegration = {
requireModuleIfAvailable(jsResource) {
return getFakeModule();
},
waitForModule(jsResource) {
return Promise.resolve(getFakeModule());
},
};

module.exports = ReactFlightDOMRelayClientIntegration;
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const ReactFlightDOMRelayServerIntegration = {
});
},
close(destination) {},
resolveResourceMetaData(resource) {
return resource;
},
};

module.exports = ReactFlightDOMRelayServerIntegration;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export type ModuleMetaData = {
id: string,
chunks: Array<Array<string>>,
};

export type Thenable = {
then(resolve: () => mixed, reject: (mixed) => mixed): mixed,
...
};

export function requireModuleIfAvailable<T>(
moduleData: ModuleMetaData,
): T | null {
let entry = require.cache[moduleData.id];
if (entry) {
return entry.exports.default;
}
// Ideally Webpack would let us inspect that all chunks have loaded and
// just call require synchronously here. Unfortunately, the chunk cache
// doesn't expose this information without creating a Promise first.
// This causes an unfortunate exponential many-pass render since each
// level in the tree will restart to initialize that module.
// This will lead to unacceptable performance in React and will need
// changes to Webpack.
return null;
}

export function waitForModule(moduleData: ModuleMetaData): Thenable {
let chunks = moduleData.chunks[0]; // First candidate
if (chunks.length === 1) {
return __webpack_chunk_load__(chunks[0]);
} else {
let promises = [];
for (let i = 0; i < chunks.length; i++) {
promises.push(__webpack_chunk_load__(chunks[i]));
}
return Promise.all(promises);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
*/

import type {ReactModel} from 'react-server/src/ReactFlightServer';
import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig';

import {
createRequest,
startWork,
startFlowing,
} from 'react-server/src/ReactFlightServer';

function renderToReadableStream(model: ReactModel): ReadableStream {
function renderToReadableStream(
model: ReactModel,
webpackMap: BundlerConfig,
): ReadableStream {
let request;
return new ReadableStream({
start(controller) {
request = createRequest(model, controller);
request = createRequest(model, controller, webpackMap);
startWork(request);
},
pull(controller) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
*/

import type {ReactModel} from 'react-server/src/ReactFlightServer';
import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig';
import type {Writable} from 'stream';

import {
Expand All @@ -20,8 +21,12 @@ function createDrainHandler(destination, request) {
return () => startFlowing(request);
}

function pipeToNodeWritable(model: ReactModel, destination: Writable): void {
let request = createRequest(model, destination);
function pipeToNodeWritable(
model: ReactModel,
destination: Writable,
webpackMap: BundlerConfig,
): void {
let request = createRequest(model, destination, webpackMap);
destination.on('drain', createDrainHandler(destination, request));
startWork(request);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

type WebpackMap = {
[filename: string]: ModuleMetaData,
};

export type BundlerConfig = WebpackMap;

export type ModuleReference = string;

export type ModuleMetaData = {
id: string,
chunks: Array<Array<string>>,
};

export function resolveModuleMetaData(
config: BundlerConfig,
modulePath: ModuleReference,
): ModuleMetaData {
return config[modulePath];
}
7 changes: 6 additions & 1 deletion packages/react-noop-renderer/src/ReactNoopFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,12 @@ const ReactNoopFlightServer = ReactFlightServer({

function render(model: ReactModel): Destination {
let destination: Destination = [];
let request = ReactNoopFlightServer.createRequest(model, destination);
let bundlerConfig = undefined;
let request = ReactNoopFlightServer.createRequest(
model,
destination,
bundlerConfig,
);
ReactNoopFlightServer.startWork(request);
return destination;
}
Expand Down
12 changes: 11 additions & 1 deletion packages/react-server/src/ReactFlightServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
* @flow
*/

import type {Destination, Chunk} from './ReactFlightServerConfig';
import type {
Destination,
Chunk,
BundlerConfig,
// ModuleReference,
// ModuleMetaData,
} from './ReactFlightServerConfig';

import {
scheduleWork,
Expand All @@ -18,6 +24,7 @@ import {
close,
processModelChunk,
processErrorChunk,
// resolveModuleMetaData,
} from './ReactFlightServerConfig';

import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
Expand Down Expand Up @@ -49,6 +56,7 @@ type Segment = {

export type Request = {
destination: Destination,
bundlerConfig: BundlerConfig,
nextChunkId: number,
pendingChunks: number,
pingedSegments: Array<Segment>,
Expand All @@ -61,10 +69,12 @@ export type Request = {
export function createRequest(
model: ReactModel,
destination: Destination,
bundlerConfig: BundlerConfig,
): Request {
let pingedSegments = [];
let request = {
destination,
bundlerConfig,
nextChunkId: 0,
pendingChunks: 0,
pingedSegments: pingedSegments,
Expand Down
15 changes: 15 additions & 0 deletions packages/react-server/src/ReactFlightServerBundlerConfigCustom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

declare var $$$hostConfig: any;

export opaque type BundlerConfig = mixed; // eslint-disable-line no-undef
export opaque type ModuleReference = mixed; // eslint-disable-line no-undef
export opaque type ModuleMetaData = mixed; // eslint-disable-line no-undef
export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;
Loading

0 comments on commit 0d94205

Please sign in to comment.