@samitouri / QOS-React-2 / commits / c0cd1be908

[Flight] Move bundler configs to use Suspense instead of returning thenable (#18367)

* Move bundler configs to use suspense instead of returning thenable * Fix some Flow types

Sebastian Markbåge committed Mar 21, 2020 at 22:28 UTC c0cd1be908c9e2123fa41fb784780dde9babb002
10 files changed +39 -31
packages/react-client/src/ReactFlightClient.js
-1
@@ -17,7 +17,6 @@ import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
17 // import {
18 // resolveModuleReference,
19 // preloadModule,
20 -// loadModule,
20 // requireModule,
21 // } from './ReactFlightClientHostConfig';
22
packages/react-client/src/forks/ReactFlightClientHostConfig.custom.js
+2
@@ -26,6 +26,8 @@
26 declare var $$$hostConfig: any;
27
28 export opaque type ModuleMetaData = mixed; // eslint-disable-line no-undef
29 +export opaque type ModuleReference<T> = mixed; // eslint-disable-line no-undef
30 +export const resolveModuleReference = $$$hostConfig.resolveModuleReference;
31 export const preloadModule = $$$hostConfig.preloadModule;
32 export const requireModule = $$$hostConfig.requireModule;
33
packages/react-flight-dom-relay/src/ReactFlightDOMRelayClientHostConfig.js
-1
@@ -10,7 +10,6 @@
10 export {
11 resolveModuleReference,
12 preloadModule,
13 - loadModule,
13 requireModule,
14 } from 'ReactFlightDOMRelayClientIntegration';
15
packages/react-flight-dom-relay/src/__mocks__/ReactFlightDOMRelayClientIntegration.js
-3
@@ -18,9 +18,6 @@ const ReactFlightDOMRelayClientIntegration = {
18 return moduleData;
19 },
20 preloadModule(moduleReference) {},
21 - loadModule(moduleReference) {
22 - return null;
23 - },
21 requireModule(moduleReference) {
22 return getFakeModule();
23 },
packages/react-flight-dom-webpack/src/ReactFlightClientWebpackBundlerConfig.js
+20 -15
@@ -7,14 +7,14 @@
7 * @flow
8 */
9
10 -export type ModuleMetaData = {
10 +export opaque type ModuleMetaData = {
11 id: string,
12 chunks: Array<string>,
13 name: string,
14 };
15
16 // eslint-disable-next-line no-unused-vars
17 -export type ModuleReference<T> = ModuleMetaData;
17 +export opaque type ModuleReference<T> = ModuleMetaData;
18
19 export function resolveModuleReference<T>(
20 moduleData: ModuleMetaData,
@@ -23,7 +23,7 @@ export function resolveModuleReference<T>(
23 }
24
25 type Thenable = {
26 - then(resolve: () => mixed, reject: (mixed) => mixed): mixed,
26 + then(resolve: (any) => mixed, reject?: (Error) => mixed): Thenable,
27 ...
28 };
29
@@ -31,32 +31,37 @@ type Thenable = {
31 // If they're still pending they're a thenable. This map also exists
32 // in Webpack but unfortunately it's not exposed so we have to
33 // replicate it in user space. null means that it has already loaded.
34 -const chunkCache: Map<string, null | Thenable> = new Map();
34 +const chunkCache: Map<string, null | Thenable | Error> = new Map();
35
36 // Returning null means that all dependencies are fulfilled and we
37 // can synchronously require the module now. A thenable is returned
38 // that when resolved, means we can try again.
39 export function preloadModule<T>(moduleData: ModuleReference<T>): void {
40 - loadModule(moduleData);
41 -}
42 -
43 -export function loadModule<T>(moduleData: ModuleReference<T>): null | Thenable {
40 let chunks = moduleData.chunks;
45 - let anyRemainingThenable = null;
41 for (let i = 0; i < chunks.length; i++) {
42 let chunkId = chunks[i];
43 let entry = chunkCache.get(chunkId);
44 if (entry === undefined) {
50 - anyRemainingThenable = __webpack_chunk_load__(chunkId);
51 - chunkCache.set(chunkId, anyRemainingThenable);
52 - anyRemainingThenable.then(chunkCache.set.bind(chunkCache, chunkId, null));
53 - } else if (entry !== null) {
54 - anyRemainingThenable = entry;
45 + let thenable = __webpack_chunk_load__(chunkId);
46 + let resolve = chunkCache.set.bind(chunkCache, chunkId, null);
47 + let reject = chunkCache.set.bind(chunkCache, chunkId);
48 + thenable.then(resolve, reject);
49 + chunkCache.set(chunkId, thenable);
50 }
51 }
57 - return anyRemainingThenable;
52 }
53
54 export function requireModule<T>(moduleData: ModuleReference<T>): T {
55 + let chunks = moduleData.chunks;
56 + for (let i = 0; i < chunks.length; i++) {
57 + let chunkId = chunks[i];
58 + let entry = chunkCache.get(chunkId);
59 + if (entry !== null) {
60 + // We assume that preloadModule has been called before.
61 + // So we don't expect to see entry being undefined here, that's an error.
62 + // Let's throw either an error or the Promise.
63 + throw entry;
64 + }
65 + }
66 return __webpack_require__(moduleData.id)[moduleData.name];
67 }
packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
+1
@@ -18,6 +18,7 @@ export type ModuleReference = string;
18 export type ModuleMetaData = {
19 id: string,
20 chunks: Array<string>,
21 + name: string,
22 };
23
24 export function resolveModuleMetaData(
packages/react-noop-renderer/src/ReactNoopFlightClient.js
+9
@@ -27,6 +27,15 @@ const {
27 close,
28 } = ReactFlightClient({
29 supportsBinaryStreams: false,
30 + resolveModuleReference(name: string) {
31 + return name;
32 + },
33 + preloadModule(name: string) {},
34 + requireModule(name: string) {
35 + return function FakeModule() {
36 + return name;
37 + };
38 + },
39 });
40
41 function read<T>(source: Source): ReactModelRoot<T> {
packages/react-server/src/ReactFlightServerBundlerConfigCustom.js
+1 -1
@@ -11,5 +11,5 @@ declare var $$$hostConfig: any;
11
12 export opaque type BundlerConfig = mixed; // eslint-disable-line no-undef
13 export opaque type ModuleReference = mixed; // eslint-disable-line no-undef
14 -export opaque type ModuleMetaData = mixed; // eslint-disable-line no-undef
14 +export opaque type ModuleMetaData: any = mixed; // eslint-disable-line no-undef
15 export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;
scripts/flow/environment.js
+5 -1
@@ -67,5 +67,9 @@ declare module 'EventListener' {
67 };
68 }
69
70 -declare function __webpack_chunk_load__(id: string): {then(() => mixed): mixed};
70 +type Thenable = {
71 + then(resolve: (mixed) => mixed, reject?: (Error) => mixed): Thenable,
72 +};
73 +
74 +declare function __webpack_chunk_load__(id: string): Thenable;
75 declare function __webpack_require__(id: string): {default: any};
scripts/flow/react-relay-hooks.js
+1 -9
@@ -15,11 +15,6 @@ type JSONValue =
15 | {[key: string]: JSONValue}
16 | Array<JSONValue>;
17
18 -type Thenable = {
19 - then(resolve: () => mixed, reject: (error: Error) => mixed): mixed,
20 - ...
21 -};
22 -
18 declare module 'ReactFlightDOMRelayServerIntegration' {
19 declare export opaque type Destination;
20 declare export function emitModel(
@@ -43,7 +38,7 @@ declare module 'ReactFlightDOMRelayServerIntegration' {
38 }
39
40 declare module 'ReactFlightDOMRelayClientIntegration' {
46 - declare export opaque type ModuleReference;
41 + declare export opaque type ModuleReference<T>;
42 declare export opaque type ModuleMetaData;
43 declare export function resolveModuleReference<T>(
44 moduleData: ModuleMetaData,
@@ -51,9 +46,6 @@ declare module 'ReactFlightDOMRelayClientIntegration' {
46 declare export function preloadModule<T>(
47 moduleReference: ModuleReference<T>,
48 ): void;
54 - declare export function loadModule<T>(
55 - moduleReference: ModuleReference<T>,
56 - ): null | Thenable;
49 declare export function requireModule<T>(
50 moduleReference: ModuleReference<T>,
51 ): T;