Add server-runtime to create Server Blocks (#18392)
This is equivalent to the jsx-runtime in that this is what the compiled output on the server is supposed to target. It's really just the same code for all the different Flights, but they have different types in their arguments so each one gets their own entry point. We might use this to add runtime warnings per entry point. Unlike the client-side React.block call this doesn't provide the factory function that curries the load function. The compiler is expected to wrap this call in the currying factory.
Sebastian Markbåge committed
Mar 25, 2020 at 19:03 UTC
ce6fe50b0195449a65e1edc26724eaad9fa08e51
22 files changed
+181
-25
packages/react-client/src/__tests__/ReactFlight-test.js
+8
-4
@@ -16,6 +16,7 @@ let act;
16
let React;
17
let ReactNoop;
18
let ReactNoopFlightServer;
19
+let ReactNoopFlightServerRuntime;
20
let ReactNoopFlightClient;
21
22
describe('ReactFlight', () => {
@@ -25,19 +26,22 @@ describe('ReactFlight', () => {
26
React = require('react');
27
ReactNoop = require('react-noop-renderer');
28
ReactNoopFlightServer = require('react-noop-renderer/flight-server');
29
+ ReactNoopFlightServerRuntime = require('react-noop-renderer/flight-server-runtime');
30
ReactNoopFlightClient = require('react-noop-renderer/flight-client');
31
act = ReactNoop.act;
32
});
33
34
function block(render, load) {
35
+ if (load === undefined) {
36
+ return () => {
37
+ return ReactNoopFlightServerRuntime.serverBlockNoData(render);
38
+ };
39
+ }
40
return function(...args) {
34
- if (load === undefined) {
35
- return [Symbol.for('react.server.block'), render];
36
- }
41
let curriedLoad = () => {
42
return load(...args);
43
};
40
- return [Symbol.for('react.server.block'), render, curriedLoad];
44
+ return ReactNoopFlightServerRuntime.serverBlock(render, curriedLoad);
45
};
46
}
47
packages/react-flight-dom-relay/server-runtime.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export * from 'react-server/src/ReactFlightServerRuntime';
packages/react-flight-dom-relay/src/ReactFlightDOMRelayServerHostConfig.js
+2
-2
@@ -31,9 +31,9 @@ export type {
31
32
export type BundlerConfig = void;
33
34
-export function resolveModuleMetaData(
34
+export function resolveModuleMetaData<T>(
35
config: BundlerConfig,
36
- resource: ModuleReference,
36
+ resource: ModuleReference<T>,
37
): ModuleMetaData {
38
return resolveModuleMetaDataImpl(resource);
39
}
packages/react-flight-dom-relay/src/__tests__/ReactFlightDOMRelay-test.internal.js
+6
-4
@@ -11,6 +11,7 @@ let act;
11
let React;
12
let ReactDOM;
13
let ReactDOMFlightRelayServer;
14
+let ReactDOMFlightRelayServerRuntime;
15
let ReactDOMFlightRelayClient;
16
17
describe('ReactFlightDOMRelay', () => {
@@ -21,6 +22,7 @@ describe('ReactFlightDOMRelay', () => {
22
React = require('react');
23
ReactDOM = require('react-dom');
24
ReactDOMFlightRelayServer = require('react-flight-dom-relay/server');
25
+ ReactDOMFlightRelayServerRuntime = require('react-flight-dom-relay/server-runtime');
26
ReactDOMFlightRelayClient = require('react-flight-dom-relay');
27
});
28
@@ -45,14 +47,14 @@ describe('ReactFlightDOMRelay', () => {
47
}
48
49
function block(render, load) {
50
+ if (load === undefined) {
51
+ return ReactDOMFlightRelayServerRuntime.serverBlock(render);
52
+ }
53
return function(...args) {
49
- if (load === undefined) {
50
- return [Symbol.for('react.server.block'), render];
51
- }
54
let curriedLoad = () => {
55
return load(...args);
56
};
55
- return [Symbol.for('react.server.block'), render, curriedLoad];
57
+ return ReactDOMFlightRelayServerRuntime.serverBlock(render, curriedLoad);
58
};
59
}
60
packages/react-flight-dom-webpack/npm/server-runtime.js
new
+7
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+if (process.env.NODE_ENV === 'production') {
4
+ module.exports = require('./cjs/react-flight-dom-webpack-server-runtime.production.min.js');
5
+} else {
6
+ module.exports = require('./cjs/react-flight-dom-webpack-server-runtime.development.js');
7
+}
packages/react-flight-dom-webpack/package.json
+1
@@ -16,6 +16,7 @@
16
"server.js",
17
"server.browser.js",
18
"server.node.js",
19
+ "server-runtime.js",
20
"cjs/",
21
"umd/"
22
],
packages/react-flight-dom-webpack/server-runtime.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export * from 'react-server/src/ReactFlightServerRuntime';
packages/react-flight-dom-webpack/src/ReactFlightServerWebpackBundlerConfig.js
+4
-3
@@ -13,7 +13,8 @@ type WebpackMap = {
13
14
export type BundlerConfig = WebpackMap;
15
16
-export type ModuleReference = string;
16
+// eslint-disable-next-line no-unused-vars
17
+export type ModuleReference<T> = string;
18
19
export type ModuleMetaData = {
20
id: string,
@@ -21,9 +22,9 @@ export type ModuleMetaData = {
22
name: string,
23
};
24
24
-export function resolveModuleMetaData(
25
+export function resolveModuleMetaData<T>(
26
config: BundlerConfig,
26
- modulePath: ModuleReference,
27
+ modulePath: ModuleReference<T>,
28
): ModuleMetaData {
29
return config[modulePath];
30
}
packages/react-flight-dom-webpack/src/__tests__/ReactFlightDOM-test.js
+11
-4
@@ -29,6 +29,7 @@ let Stream;
29
let React;
30
let ReactDOM;
31
let ReactFlightDOMServer;
32
+let ReactFlightDOMServerRuntime;
33
let ReactFlightDOMClient;
34
35
describe('ReactFlightDOM', () => {
@@ -41,6 +42,7 @@ describe('ReactFlightDOM', () => {
42
React = require('react');
43
ReactDOM = require('react-dom');
44
ReactFlightDOMServer = require('react-flight-dom-webpack/server');
45
+ ReactFlightDOMServerRuntime = require('react-flight-dom-webpack/server-runtime');
46
ReactFlightDOMClient = require('react-flight-dom-webpack');
47
});
48
@@ -72,14 +74,19 @@ describe('ReactFlightDOM', () => {
74
chunks: [],
75
name: 'd',
76
};
77
+ if (load === undefined) {
78
+ return () => {
79
+ return ReactFlightDOMServerRuntime.serverBlockNoData('path/' + idx);
80
+ };
81
+ }
82
return function(...args) {
76
- if (load === undefined) {
77
- return [Symbol.for('react.server.block'), render];
78
- }
83
let curriedLoad = () => {
84
return load(...args);
85
};
82
- return [Symbol.for('react.server.block'), 'path/' + idx, curriedLoad];
86
+ return ReactFlightDOMServerRuntime.serverBlock(
87
+ 'path/' + idx,
88
+ curriedLoad,
89
+ );
90
};
91
}
92
packages/react-noop-renderer/flight-server-runtime.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export * from 'react-server/flight-server-runtime';
packages/react-noop-renderer/npm/flight-server-runtime.js
new
+3
@@ -0,0 +1,3 @@
1
+'use strict';
2
+
3
+module.exports = require('react-server/flight-server-runtime');
packages/react-noop-renderer/package.json
+1
@@ -30,6 +30,7 @@
30
"flight-client.js",
31
"flight-modules.js",
32
"flight-server.js",
33
+ "flight-server-runtime.js",
34
"cjs/"
35
]
36
}
packages/react-server/flight-server-runtime.js
new
+10
@@ -0,0 +1,10 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+export * from './src/ReactFlightServerRuntime';
packages/react-server/npm/flight-server-runtime.js
new
+7
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+if (process.env.NODE_ENV === 'production') {
4
+ module.exports = require('./cjs/react-server-flight-server-runtime.production.min.js');
5
+} else {
6
+ module.exports = require('./cjs/react-server-flight-server-runtime.development.js');
7
+}
packages/react-server/package.json
+1
@@ -14,6 +14,7 @@
14
"README.md",
15
"index.js",
16
"flight.js",
17
+ "flight-server-runtime.js",
18
"cjs/"
19
],
20
"main": "index.js",
packages/react-server/src/ReactFlightServer.js
+1
-1
@@ -176,7 +176,7 @@ export function resolveModelToJSON(
176
switch (key) {
177
case '1': {
178
// Module reference
179
- let moduleReference: ModuleReference = (value: any);
179
+ let moduleReference: ModuleReference<any> = (value: any);
180
try {
181
let moduleMetaData: ModuleMetaData = resolveModuleMetaData(
182
request.bundlerConfig,
packages/react-server/src/ReactFlightServerBundlerConfigCustom.js
+1
-1
@@ -10,6 +10,6 @@
10
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
13
+export opaque type ModuleReference<T> = mixed; // eslint-disable-line no-undef
14
export opaque type ModuleMetaData: any = mixed; // eslint-disable-line no-undef
15
export const resolveModuleMetaData = $$$hostConfig.resolveModuleMetaData;
packages/react-server/src/ReactFlightServerRuntime.js
new
+52
@@ -0,0 +1,52 @@
1
+/**
2
+ * Copyright (c) Facebook, Inc. and its affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ * @flow
8
+ */
9
+
10
+import type {BlockRenderFunction} from 'react/src/ReactBlock';
11
+
12
+import type {ModuleReference} from './ReactFlightServerConfig';
13
+
14
+import {REACT_SERVER_BLOCK_TYPE} from 'shared/ReactSymbols';
15
+
16
+export type ServerBlockComponent<Props, Data> =
17
+ | [
18
+ Symbol | number,
19
+ ModuleReference<BlockRenderFunction<Props, Data>>,
20
+ () => Data,
21
+ ]
22
+ | [Symbol | number, ModuleReference<BlockRenderFunction<Props, void>>];
23
+
24
+opaque type ServerBlock<Props>: React$AbstractComponent<
25
+ Props,
26
+ null,
27
+> = React$AbstractComponent<Props, null>;
28
+
29
+export function serverBlock<Props, Data>(
30
+ moduleReference: ModuleReference<BlockRenderFunction<Props, Data>>,
31
+ loadData: () => Data,
32
+): ServerBlock<Props> {
33
+ let blockComponent: ServerBlockComponent<Props, Data> = [
34
+ REACT_SERVER_BLOCK_TYPE,
35
+ moduleReference,
36
+ loadData,
37
+ ];
38
+
39
+ // $FlowFixMe: Upstream BlockComponent to Flow as a valid Node.
40
+ return blockComponent;
41
+}
42
+
43
+export function serverBlockNoData<Props>(
44
+ moduleReference: ModuleReference<BlockRenderFunction<Props, void>>,
45
+): ServerBlock<Props> {
46
+ let blockComponent: ServerBlockComponent<Props, void> = [
47
+ REACT_SERVER_BLOCK_TYPE,
48
+ moduleReference,
49
+ ];
50
+ // $FlowFixMe: Upstream BlockComponent to Flow as a valid Node.
51
+ return blockComponent;
52
+}
packages/react/src/ReactBlock.js
+2
-2
@@ -106,7 +106,7 @@ export function block<Args: Iterable<any>, Props, Data>(
106
_render: render,
107
};
108
109
- // $FlowFixMe
109
+ // $FlowFixMe: Upstream BlockComponent to Flow as a valid Node.
110
return blockComponent;
111
};
112
}
@@ -132,7 +132,7 @@ export function block<Args: Iterable<any>, Props, Data>(
132
_init: lazyInitializer,
133
};
134
135
- // $FlowFixMe
135
+ // $FlowFixMe: Upstream BlockComponent to Flow as a valid Node.
136
return lazyType;
137
};
138
}
scripts/flow/react-relay-hooks.js
+3
-3
@@ -30,10 +30,10 @@ declare module 'ReactFlightDOMRelayServerIntegration' {
30
): void;
31
declare export function close(destination: Destination): void;
32
33
- declare export opaque type ModuleReference;
33
+ declare export opaque type ModuleReference<T>;
34
declare export type ModuleMetaData = JSONValue;
35
- declare export function resolveModuleMetaData(
36
- resourceReference: ModuleReference,
35
+ declare export function resolveModuleMetaData<T>(
36
+ resourceReference: ModuleReference<T>,
37
): ModuleMetaData;
38
}
39
scripts/rollup/bundles.js
+21
@@ -229,6 +229,13 @@ const bundles = [
229
global: 'ReactFlightDOMServer',
230
externals: ['react', 'react-dom/server'],
231
},
232
+ {
233
+ bundleTypes: [NODE_DEV, NODE_PROD],
234
+ moduleType: RENDERER,
235
+ entry: 'react-flight-dom-webpack/server-runtime',
236
+ global: 'ReactFlightDOMServerRuntime',
237
+ externals: ['react'],
238
+ },
239
240
/******* React DOM Flight Client Webpack *******/
241
{
@@ -251,6 +258,13 @@ const bundles = [
258
'ReactFlightDOMRelayServerIntegration',
259
],
260
},
261
+ {
262
+ bundleTypes: [FB_WWW_DEV, FB_WWW_PROD],
263
+ moduleType: RENDERER,
264
+ entry: 'react-flight-dom-relay/server-runtime',
265
+ global: 'ReactFlightDOMRelayServerRuntime',
266
+ externals: ['react', 'ReactFlightDOMRelayServerIntegration'],
267
+ },
268
269
/******* React DOM Flight Client Relay *******/
270
{
@@ -453,6 +467,13 @@ const bundles = [
467
global: 'ReactFlightServer',
468
externals: ['react'],
469
},
470
+ {
471
+ bundleTypes: [NODE_DEV, NODE_PROD],
472
+ moduleType: RENDERER,
473
+ entry: 'react-server/flight-server-runtime',
474
+ global: 'ReactFlightServerRuntime',
475
+ externals: ['react'],
476
+ },
477
478
/******* React Flight Client *******/
479
{
scripts/shared/inlinedHostConfigs.js
+10
-1
@@ -14,6 +14,7 @@ module.exports = [
14
'react-dom/testing',
15
'react-dom/unstable-fizz.node',
16
'react-flight-dom-webpack/server.node',
17
+ 'react-flight-dom-webpack/server-runtime',
18
'react-flight-dom-webpack',
19
],
20
paths: [
@@ -24,6 +25,7 @@ module.exports = [
25
'react-flight-dom-webpack',
26
'react-flight-dom-webpack/server',
27
'react-flight-dom-webpack/server.node',
28
+ 'react-flight-dom-webpack/server-runtime',
29
'react-flight-dom-webpack/src/ReactFlightDOMServerNode.js', // react-flight-dom-webpack/server.browser
30
'react-interactions',
31
],
@@ -37,6 +39,7 @@ module.exports = [
39
'react-dom/testing',
40
'react-dom/unstable-fizz.browser',
41
'react-flight-dom-webpack/server.browser',
42
+ 'react-flight-dom-webpack/server-runtime',
43
'react-flight-dom-webpack',
44
],
45
paths: [
@@ -46,6 +49,7 @@ module.exports = [
49
'react-dom/src/server/ReactDOMFizzServerBrowser.js', // react-dom/unstable-fizz.browser
50
'react-flight-dom-webpack',
51
'react-flight-dom-webpack/server.browser',
52
+ 'react-flight-dom-webpack/server-runtime',
53
'react-flight-dom-webpack/src/ReactFlightDOMServerBrowser.js', // react-flight-dom-webpack/server.browser
54
],
55
isFlowTyped: true,
@@ -81,7 +85,11 @@ module.exports = [
85
},
86
{
87
shortName: 'dom-relay',
84
- entryPoints: ['react-flight-dom-relay', 'react-flight-dom-relay/server'],
88
+ entryPoints: [
89
+ 'react-flight-dom-relay',
90
+ 'react-flight-dom-relay/server',
91
+ 'react-flight-dom-relay/server-runtime',
92
+ ],
93
paths: ['react-dom', 'react-flight-dom-relay'],
94
isFlowTyped: true,
95
isServerSupported: true,
@@ -93,6 +101,7 @@ module.exports = [
101
'react-client/flight',
102
'react-server',
103
'react-server/flight',
104
+ 'react-server/flight-server-runtime',
105
],
106
paths: [],
107
isFlowTyped: true,