From 8206b4b864645881974d219ffb0233128748ba94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Wed, 18 Mar 2020 12:18:34 -0700 Subject: [PATCH] Wire up bundler configs (#18334) This allows different flight server and clients to have different configs depending on bundler to serialize and resolve modules. --- .eslintrc.js | 7 +++ .../react-client/src/ReactFlightClient.js | 7 +++ .../ReactFlightClientHostConfigNoStream.js | 30 +++++++++++ .../ReactFlightClientHostConfig.custom.js | 5 ++ ...ReactFlightClientHostConfig.dom-browser.js | 1 + .../ReactFlightClientHostConfig.dom-relay.js | 1 + .../forks/ReactFlightClientHostConfig.dom.js | 1 + .../ReactFlightDOMRelayClientHostConfig.js | 25 ++------- .../src/ReactFlightDOMRelayServer.js | 2 +- .../ReactFlightDOMRelayServerHostConfig.js | 29 ++++++++-- .../ReactFlightDOMRelayClientIntegration.js | 25 +++++++++ .../ReactFlightDOMRelayServerIntegration.js | 3 ++ .../ReactFlightClientWebpackBundlerConfig.js | 53 +++++++++++++++++++ .../src/ReactFlightDOMServerBrowser.js | 8 ++- .../src/ReactFlightDOMServerNode.js | 9 +++- .../ReactFlightServerWebpackBundlerConfig.js | 28 ++++++++++ .../src/ReactNoopFlightServer.js | 7 ++- .../react-server/src/ReactFlightServer.js | 12 ++++- .../ReactFlightServerBundlerConfigCustom.js | 15 ++++++ .../forks/ReactFlightServerConfig.custom.js | 1 + .../ReactFlightServerConfig.dom-browser.js | 1 + .../src/forks/ReactFlightServerConfig.dom.js | 1 + scripts/flow/environment.js | 3 ++ scripts/flow/react-relay-hooks.js | 19 +++++++ scripts/jest/setupHostConfigs.js | 3 ++ scripts/rollup/bundles.js | 2 +- 26 files changed, 266 insertions(+), 32 deletions(-) create mode 100644 packages/react-client/src/ReactFlightClientHostConfigNoStream.js create mode 100644 packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayClientIntegration.js create mode 100644 packages/react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js create mode 100644 packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js create mode 100644 packages/react-server/src/ReactFlightServerBundlerConfigCustom.js diff --git a/.eslintrc.js b/.eslintrc.js index 112b17120f065..9f459489f0aea 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -157,6 +157,13 @@ module.exports = { nativeFabricUIManager: true, }, }, + { + files: ['packages/react-flight-dom-webpack/**/*.js'], + globals: { + '__webpack_chunk_load__': true, + '__webpack_require__': true, + }, + }, ], globals: { diff --git a/packages/react-client/src/ReactFlightClient.js b/packages/react-client/src/ReactFlightClient.js index ef236394e0ade..fd2af77004c9b 100644 --- a/packages/react-client/src/ReactFlightClient.js +++ b/packages/react-client/src/ReactFlightClient.js @@ -9,6 +9,13 @@ import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; +// import type {ModuleMetaData} from './ReactFlightClientHostConfig'; + +// import { +// preloadModule, +// requireModule, +// } from './ReactFlightClientHostConfig'; + export type ReactModelRoot = {| model: T, |}; diff --git a/packages/react-client/src/ReactFlightClientHostConfigNoStream.js b/packages/react-client/src/ReactFlightClientHostConfigNoStream.js new file mode 100644 index 0000000000000..17f29a9f26c50 --- /dev/null +++ b/packages/react-client/src/ReactFlightClientHostConfigNoStream.js @@ -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'); +} diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js index ea0037f25ff84..5c3930f69d371 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js @@ -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 preloadModule = $$$hostConfig.preloadModule; +export const requireModule = $$$hostConfig.requireModule; + export opaque type Source = mixed; // eslint-disable-line no-undef export opaque type StringDecoder = mixed; // eslint-disable-line no-undef diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-browser.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-browser.js index eb1e6199b425d..80d967d3ecdba 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-browser.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-browser.js @@ -8,3 +8,4 @@ */ export * from 'react-client/src/ReactFlightClientHostConfigBrowser'; +export * from 'react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig'; diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-relay.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-relay.js index 7428b890f2e33..d055870a6afaa 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-relay.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom-relay.js @@ -8,3 +8,4 @@ */ export * from 'react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig'; +export * from '../ReactFlightClientHostConfigNoStream'; diff --git a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom.js b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom.js index eb1e6199b425d..80d967d3ecdba 100644 --- a/packages/react-client/src/forks/ReactFlightClientHostConfig.dom.js +++ b/packages/react-client/src/forks/ReactFlightClientHostConfig.dom.js @@ -8,3 +8,4 @@ */ export * from 'react-client/src/ReactFlightClientHostConfigBrowser'; +export * from 'react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig'; diff --git a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js index 17f29a9f26c50..7f86dcfb19cad 100644 --- a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js +++ b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js @@ -7,24 +7,9 @@ * @flow */ -export type StringDecoder = void; +export { + preloadModule, + requireModule, +} 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'; diff --git a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServer.js b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServer.js index 9c589a9f61daa..95b52750498a7 100644 --- a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServer.js +++ b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServer.js @@ -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); } diff --git a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js index bd6166ca95d99..4b5fd5b33f3eb 100644 --- a/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js +++ b/packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js @@ -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 diff --git a/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayClientIntegration.js b/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayClientIntegration.js new file mode 100644 index 0000000000000..0df7d51104ff2 --- /dev/null +++ b/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayClientIntegration.js @@ -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 = { + preloadModule(jsResource) { + return null; + }, + requireModule(jsResource) { + return getFakeModule(); + }, +}; + +module.exports = ReactFlightDOMRelayClientIntegration; diff --git a/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayServerIntegration.js b/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayServerIntegration.js index 212586b30b16e..89304a070de4e 100644 --- a/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayServerIntegration.js +++ b/packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayServerIntegration.js @@ -23,6 +23,9 @@ const ReactFlightDOMRelayServerIntegration = { }); }, close(destination) {}, + resolveResourceMetaData(resource) { + return resource; + }, }; module.exports = ReactFlightDOMRelayServerIntegration; diff --git a/packages/react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js b/packages/react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js new file mode 100644 index 0000000000000..f3866e851256a --- /dev/null +++ b/packages/react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js @@ -0,0 +1,53 @@ +/** + * 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, +}; + +type Thenable = { + then(resolve: () => mixed, reject: (mixed) => mixed): mixed, + ... +}; + +// The chunk cache contains all the chunks we've preloaded so far. +// If they're still pending they're a thenable. This map also exists +// in Webpack but unfortunately it's not exposed so we have to +// replicate it in user space. null means that it has already loaded. +const chunkCache: Map = new Map(); + +// Returning null means that all dependencies are fulfilled and we +// can synchronously require the module now. A thenable is returned +// that when resolved, means we can try again. +export function preloadModule(moduleData: ModuleMetaData): null | Thenable { + let moduleEntry = require.cache[moduleData.id]; + if (moduleEntry) { + // Fast exit if this module has already been loaded. + return null; + } + let chunks = moduleData.chunks; + let anyRemainingThenable = null; + for (let i = 0; i < chunks.length; i++) { + let chunkId = chunks[i]; + let entry = chunkCache.get(chunkId); + if (entry === undefined) { + anyRemainingThenable = __webpack_chunk_load__(chunkId); + chunkCache.set(chunkId, anyRemainingThenable); + anyRemainingThenable.then(chunkCache.set.bind(chunkCache, chunkId, null)); + } else if (entry !== null) { + anyRemainingThenable = entry; + } + } + return anyRemainingThenable; +} + +export function requireModule(moduleData: ModuleMetaData): T { + return __webpack_require__(moduleData.id).default; +} diff --git a/packages/react-flight-dom-webpack/src/ReactFlightDOMServerBrowser.js b/packages/react-flight-dom-webpack/src/ReactFlightDOMServerBrowser.js index 0d9468bbe6260..bbbf5f18ea867 100644 --- a/packages/react-flight-dom-webpack/src/ReactFlightDOMServerBrowser.js +++ b/packages/react-flight-dom-webpack/src/ReactFlightDOMServerBrowser.js @@ -8,6 +8,7 @@ */ import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig'; import { createRequest, @@ -15,11 +16,14 @@ import { 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) { diff --git a/packages/react-flight-dom-webpack/src/ReactFlightDOMServerNode.js b/packages/react-flight-dom-webpack/src/ReactFlightDOMServerNode.js index 8bc5e20d4ed55..413e42de9c1e8 100644 --- a/packages/react-flight-dom-webpack/src/ReactFlightDOMServerNode.js +++ b/packages/react-flight-dom-webpack/src/ReactFlightDOMServerNode.js @@ -8,6 +8,7 @@ */ import type {ReactModel} from 'react-server/src/ReactFlightServer'; +import type {BundlerConfig} from './ReactFlightServerWebpackBundlerConfig'; import type {Writable} from 'stream'; import { @@ -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); } diff --git a/packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js b/packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js new file mode 100644 index 0000000000000..f2e3f8afc22e7 --- /dev/null +++ b/packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js @@ -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, +}; + +export function resolveModuleMetaData( + config: BundlerConfig, + modulePath: ModuleReference, +): ModuleMetaData { + return config[modulePath]; +} diff --git a/packages/react-noop-renderer/src/ReactNoopFlightServer.js b/packages/react-noop-renderer/src/ReactNoopFlightServer.js index 8acf4307b9ff7..e33a664e07852 100644 --- a/packages/react-noop-renderer/src/ReactNoopFlightServer.js +++ b/packages/react-noop-renderer/src/ReactNoopFlightServer.js @@ -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; } diff --git a/packages/react-server/src/ReactFlightServer.js b/packages/react-server/src/ReactFlightServer.js index 4d1ad11a3c8cf..e3df453485a00 100644 --- a/packages/react-server/src/ReactFlightServer.js +++ b/packages/react-server/src/ReactFlightServer.js @@ -7,7 +7,13 @@ * @flow */ -import type {Destination, Chunk} from './ReactFlightServerConfig'; +import type { + Destination, + Chunk, + BundlerConfig, + // ModuleReference, + // ModuleMetaData, +} from './ReactFlightServerConfig'; import { scheduleWork, @@ -18,6 +24,7 @@ import { close, processModelChunk, processErrorChunk, + // resolveModuleMetaData, } from './ReactFlightServerConfig'; import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols'; @@ -49,6 +56,7 @@ type Segment = { export type Request = { destination: Destination, + bundlerConfig: BundlerConfig, nextChunkId: number, pendingChunks: number, pingedSegments: Array, @@ -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, diff --git a/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js b/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js new file mode 100644 index 0000000000000..eebaf480d14a2 --- /dev/null +++ b/packages/react-server/src/ReactFlightServerBundlerConfigCustom.js @@ -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; diff --git a/packages/react-server/src/forks/ReactFlightServerConfig.custom.js b/packages/react-server/src/forks/ReactFlightServerConfig.custom.js index 2ade60a042904..bae5a6920d56a 100644 --- a/packages/react-server/src/forks/ReactFlightServerConfig.custom.js +++ b/packages/react-server/src/forks/ReactFlightServerConfig.custom.js @@ -8,3 +8,4 @@ */ export * from '../ReactFlightServerConfigStream'; +export * from '../ReactFlightServerBundlerConfigCustom'; diff --git a/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser.js b/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser.js index 2ade60a042904..dec9a2894548b 100644 --- a/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser.js +++ b/packages/react-server/src/forks/ReactFlightServerConfig.dom-browser.js @@ -8,3 +8,4 @@ */ export * from '../ReactFlightServerConfigStream'; +export * from 'react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig'; diff --git a/packages/react-server/src/forks/ReactFlightServerConfig.dom.js b/packages/react-server/src/forks/ReactFlightServerConfig.dom.js index 2ade60a042904..dec9a2894548b 100644 --- a/packages/react-server/src/forks/ReactFlightServerConfig.dom.js +++ b/packages/react-server/src/forks/ReactFlightServerConfig.dom.js @@ -8,3 +8,4 @@ */ export * from '../ReactFlightServerConfigStream'; +export * from 'react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig'; diff --git a/scripts/flow/environment.js b/scripts/flow/environment.js index c6be784d35fd4..14f22c362302b 100644 --- a/scripts/flow/environment.js +++ b/scripts/flow/environment.js @@ -66,3 +66,6 @@ declare module 'EventListener' { ... }; } + +declare function __webpack_chunk_load__(id: string): {then(() => mixed): mixed}; +declare function __webpack_require__(id: string): {default: any}; diff --git a/scripts/flow/react-relay-hooks.js b/scripts/flow/react-relay-hooks.js index 0b42a2572340b..b7a2806fa36fc 100644 --- a/scripts/flow/react-relay-hooks.js +++ b/scripts/flow/react-relay-hooks.js @@ -15,6 +15,11 @@ type JSONValue = | {[key: string]: JSONValue} | Array; +type Thenable = { + then(resolve: () => mixed, reject: (error: Error) => mixed): mixed, + ... +}; + declare module 'ReactFlightDOMRelayServerIntegration' { declare export opaque type Destination; declare export function emitModel( @@ -29,4 +34,18 @@ declare module 'ReactFlightDOMRelayServerIntegration' { stack: string, ): void; declare export function close(destination: Destination): void; + + declare export opaque type ModuleReference; + declare export opaque type ModuleMetaData; + declare export function resolveResourceMetaData( + resource: ModuleReference, + ): ModuleMetaData; +} + +declare module 'ReactFlightDOMRelayClientIntegration' { + declare export opaque type ModuleMetaData; + declare export function preloadModule( + moduleData: ModuleMetaData, + ): null | Thenable; + declare export function requireModule(moduleData: ModuleMetaData): T; } diff --git a/scripts/jest/setupHostConfigs.js b/scripts/jest/setupHostConfigs.js index 8bde2bd51b6e4..593c215b05604 100644 --- a/scripts/jest/setupHostConfigs.js +++ b/scripts/jest/setupHostConfigs.js @@ -34,6 +34,9 @@ jest.mock('react-server/flight', () => { return config => { jest.mock(shimServerStreamConfigPath, () => config); jest.mock(shimServerFormatConfigPath, () => config); + jest.mock('react-server/src/ReactFlightServerBundlerConfigCustom', () => ({ + resolveModuleMetaData: config.resolveModuleMetaData, + })); jest.mock(shimFlightServerConfigPath, () => require.requireActual( 'react-server/src/forks/ReactFlightServerConfig.custom' diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index d8c2e55b21ed0..205f1acfbc41b 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -258,7 +258,7 @@ const bundles = [ moduleType: RENDERER, entry: 'react-flight-dom-relay', global: 'ReactFlightDOMRelayClient', - externals: ['react'], + externals: ['react', 'ReactFlightDOMRelayClientIntegration'], }, /******* React ART *******/