Server render fork for react-dom (#25436)

Publish an aliasable entry for `react-dom` top level package exports for use in server environments. This is a stub containing only the exports that we expect to retain in the top level once 19 is released
This commit is contained in:
Josh Story
2022-10-10 11:06:22 -07:00
committed by GitHub
parent 68bfd5620e
commit 1c5a3fe385
10 changed files with 169 additions and 2 deletions
+7
View File
@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-dom-server-rendering-stub.production.min.js');
} else {
module.exports = require('./cjs/react-dom-server-rendering-stub.development.js');
}
+2
View File
@@ -35,6 +35,7 @@
"static.js",
"static.browser.js",
"static.node.js",
"server-rendering-stub.js",
"test-utils.js",
"unstable_testing.js",
"cjs/",
@@ -59,6 +60,7 @@
},
"./static.browser": "./static.browser.js",
"./static.node": "./static.node.js",
"./server-rendering-stub": "./server-rendering-stub.js",
"./profiling": "./profiling.js",
"./test-utils": "./test-utils.js",
"./unstable_testing": "./unstable_testing.js",
@@ -0,0 +1,22 @@
/**
* 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 all exports so that they're available in tests.
// We can't use export * from in Flow for some reason.
import ReactVersion from 'shared/ReactVersion';
export {ReactVersion as version};
export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/ReactDOMSharedInternals';
export {
createPortal,
flushSync,
} from './src/server/ReactDOMServerRenderingStub';
export {preinit, preload} from 'react-dom-bindings/src/shared/ReactDOMFloat';
+21
View File
@@ -0,0 +1,21 @@
/**
* 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 all exports so that they're available in tests.
// We can't use export * from in Flow for some reason.
import ReactVersion from 'shared/ReactVersion';
export {ReactVersion as version};
export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './src/ReactDOMSharedInternals';
export {
createPortal,
flushSync,
} from './src/server/ReactDOMServerRenderingStub';
@@ -0,0 +1,74 @@
/**
* 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.
*
* @emails react-core
*/
'use strict';
let React;
let ReactDOM;
let ReactDOMFizzServer;
describe('react-dom-server-rendering-stub', () => {
beforeEach(() => {
jest.mock('react-dom', () => require('react-dom/server-rendering-stub'));
React = require('react');
ReactDOM = require('react-dom');
ReactDOMFizzServer = require('react-dom/server');
});
it('exports a version', () => {
expect(ReactDOM.version).toBeTruthy();
});
it('exports that are expected to be client only in the future are not exported', () => {
expect(ReactDOM.createRoot).toBe(undefined);
expect(ReactDOM.hydrateRoot).toBe(undefined);
expect(ReactDOM.findDOMNode).toBe(undefined);
expect(ReactDOM.hydrate).toBe(undefined);
expect(ReactDOM.render).toBe(undefined);
expect(ReactDOM.unmountComponentAtNode).toBe(undefined);
expect(ReactDOM.unstable_batchedUpdates).toBe(undefined);
expect(ReactDOM.unstable_createEventHandle).toBe(undefined);
expect(ReactDOM.unstable_flushControlled).toBe(undefined);
expect(ReactDOM.unstable_isNewReconciler).toBe(undefined);
expect(ReactDOM.unstable_renderSubtreeIntoContainer).toBe(undefined);
expect(ReactDOM.unstable_runWithPriority).toBe(undefined);
});
// @gate enableFloat
it('provides preload and preinit exports', async () => {
function App() {
ReactDOM.preload('foo', {as: 'style'});
ReactDOM.preinit('bar', {as: 'style'});
return <div>foo</div>;
}
const html = ReactDOMFizzServer.renderToString(<App />);
expect(html).toEqual(
'<link href="foo" rel="preload" as="style"/><link rel="stylesheet" href="bar" data-rprec="default"/><div>foo</div>',
);
});
it('provides a stub for createPortal', async () => {
expect(() => {
ReactDOM.createPortal();
}).toThrow(
'createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.',
);
});
it('provides a stub for flushSync', async () => {
let x = false;
expect(() => {
ReactDOM.flushSync(() => (x = true));
}).toThrow(
'flushSync was called on the server. This is likely caused by a function being called during render or in module scope that was intended to be called from an effect or event handler. Update your to not call flushSync no the server.',
);
expect(x).toBe(false);
});
});
@@ -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.
*
* @flow
*/
export function createPortal() {
throw new Error(
'createPortal was called on the server. Portals are not currently' +
' supported on the server. Update your program to conditionally call' +
' createPortal on the client only.',
);
}
export function flushSync() {
throw new Error(
'flushSync was called on the server. This is likely caused by a' +
' function being called during render or in module scope that was' +
' intended to be called from an effect or event handler. Update your' +
' to not call flushSync no the server.',
);
}
+3 -1
View File
@@ -432,5 +432,7 @@
"444": "getResource encountered a resource type it did not expect: \"%s\". this is a bug in React.",
"445": "\"currentResources\" was expected to exist. This is a bug in React.",
"446": "\"resourceRoot\" was expected to exist. This is a bug in React.",
"447": "While attempting to insert a Resource, React expected the Document to contain a head element but it was not found."
"447": "While attempting to insert a Resource, React expected the Document to contain a head element but it was not found.",
"448": "createPortal was called on the server. Portals are not currently supported on the server. Update your program to conditionally call createPortal on the client only.",
"449": "flushSync was called on the server. This is likely caused by a function being called during render or in module scope that was intended to be called from an effect or event handler. Update your to not call flushSync no the server."
}
+12
View File
@@ -351,6 +351,18 @@ const bundles = [
externals: ['react', 'util', 'stream', 'react-dom'],
},
/******* React DOM Server Render Stub *******/
{
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
moduleType: RENDERER,
entry: 'react-dom/server-rendering-stub',
name: 'react-dom-server-rendering-stub',
global: 'ReactDOMServerRenderingStub',
minifyWithProdErrorCodes: true,
wrapWithModuleBoundaries: false,
externals: ['react'],
},
/******* React Server DOM Webpack Writer *******/
{
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
+1 -1
View File
@@ -74,7 +74,7 @@ const forks = Object.freeze({
entry,
dependencies
) => {
if (entry === 'react-dom') {
if (entry === 'react-dom' || entry === 'react-dom/server-rendering-stub') {
return './packages/react-dom/src/ReactDOMSharedInternals.js';
}
if (
+2
View File
@@ -14,6 +14,7 @@ module.exports = [
'react-dom/unstable_testing',
'react-dom/src/server/ReactDOMFizzServerNode.js',
'react-dom/static.node',
'react-dom/server-rendering-stub',
'react-server-dom-webpack/writer.node.server',
'react-server-dom-webpack',
],
@@ -49,6 +50,7 @@ module.exports = [
'react-dom/unstable_testing',
'react-dom/src/server/ReactDOMFizzServerBrowser.js',
'react-dom/static.browser',
'react-dom/server-rendering-stub',
'react-server-dom-webpack/writer.browser.server',
'react-server-dom-webpack',
],