Skip to content

Commit

Permalink
Move client only exports to react-dom/client
Browse files Browse the repository at this point in the history
This change updates the entrypoints for `react-dom` to only include exports which make sense in every runtime (Flight, Fizz, and Fiber). The main benefit to doing this is we stop including the entire client build when importing anything from `react-dom`. The server-rendering-stub was added as a manual way of doing this prior to the next major and now that stub simply reexports from `react-dom`. In a future major we will remove the stub altogether.

This change affects the OSS channels but does not update how the meta entrypoints are organized
  • Loading branch information
gnoff committed Feb 14, 2024
1 parent 901fe05 commit 91a323d
Show file tree
Hide file tree
Showing 64 changed files with 535 additions and 2,337 deletions.
42 changes: 42 additions & 0 deletions packages/react-dom-bindings/src/client/ReactDOMContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

import {disableCommentsAsDOMContainers} from 'shared/ReactFeatureFlags';

import {
ELEMENT_NODE,
COMMENT_NODE,
DOCUMENT_NODE,
DOCUMENT_FRAGMENT_NODE,
} from './HTMLNodeType';

export function isValidContainer(node: any): boolean {
return !!(
node &&
(node.nodeType === ELEMENT_NODE ||
node.nodeType === DOCUMENT_NODE ||
node.nodeType === DOCUMENT_FRAGMENT_NODE ||
(!disableCommentsAsDOMContainers &&
node.nodeType === COMMENT_NODE &&
(node: any).nodeValue === ' react-mount-point-unstable '))
);
}

// TODO: Remove this function which also includes comment nodes.
// We only use it in places that are currently more relaxed.
export function isValidContainerLegacy(node: any): boolean {
return !!(
node &&
(node.nodeType === ELEMENT_NODE ||
node.nodeType === DOCUMENT_NODE ||
node.nodeType === DOCUMENT_FRAGMENT_NODE ||
(node.nodeType === COMMENT_NODE &&
(node: any).nodeValue === ' react-mount-point-unstable '))
);
}
74 changes: 69 additions & 5 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* @flow
*/

import type {HostDispatcher} from 'react-dom/src/shared/ReactDOMTypes';
import type {EventPriority} from 'react-reconciler/src/ReactEventPriorities';
import type {DOMEventName} from '../events/DOMEventNames';
import type {Fiber, FiberRoot} from 'react-reconciler/src/ReactInternalTypes';
Expand All @@ -20,6 +19,7 @@ import type {ReactScopeInstance} from 'shared/ReactTypes';
import type {AncestorInfoDev} from './validateDOMNesting';
import type {FormStatus} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
import type {
HostDispatcher,
CrossOriginEnum,
PreloadImplOptions,
PreloadModuleImplOptions,
Expand All @@ -28,6 +28,10 @@ import type {
PreinitModuleScriptOptions,
} from 'react-dom/src/shared/ReactDOMTypes';

import {
isAlreadyRendering,
flushSync as flushSyncWithoutWarningIfAlreadyRendering,
} from 'react-reconciler/src/ReactFiberReconciler';
import {NotPending} from 'react-dom-bindings/src/shared/ReactDOMFormActions';
import {getCurrentRootHostContainer} from 'react-reconciler/src/ReactFiberHostContext';
import {DefaultEventPriority} from 'react-reconciler/src/ReactEventPriorities';
Expand Down Expand Up @@ -106,6 +110,9 @@ import {listenToAllSupportedEvents} from '../events/DOMPluginEventSystem';
import {validateLinkPropsForStyleResource} from '../shared/ReactDOMResourceValidation';
import escapeSelectorAttributeValueInsideDoubleQuotes from './escapeSelectorAttributeValueInsideDoubleQuotes';

import ReactDOMSharedInternals from 'shared/ReactDOMSharedInternals';
const ReactDOMCurrentDispatcher = ReactDOMSharedInternals.Dispatcher;

export type Type = string;
export type Props = {
autoFocus?: boolean,
Expand Down Expand Up @@ -2083,19 +2090,51 @@ function getDocumentFromRoot(root: HoistableRoot): Document {
return root.ownerDocument || root;
}

// We want this to be the default dispatcher on ReactDOMSharedInternals but we don't want to mutate
// internals in Module scope. Instead we export it and Internals will import it. There is already a cycle
// from Internals -> ReactDOM -> HostConfig -> Internals so this doesn't introduce a new one.
export const ReactDOMClientDispatcher: HostDispatcher = {
const ReactDOMClientDispatcher: HostDispatcher = {
prefetchDNS,
preconnect,
preload,
preloadModule,
preinitStyle,
preinitScript,
preinitModuleScript,
flushSync,
nextDispatcher: null,
};

// We register the HostDispatcher on ReactDOMSharedInternals
// For client builds we always put the dispatcher at the end of the list
// This is because the implementations on this dispatcher will always forward
// all calls to subsequent dispatchers whereas the server dispatcher may not.
// This is a tricky construction but hopefully balances intended semantics for
// resource APIS and flushSync behavior on both server and client runtimes without
// adding overhead. One litmust test is can you preload in renderToString on the client
// without that leaking into the Document.
if (ReactDOMCurrentDispatcher.current === null) {
ReactDOMCurrentDispatcher.current = ReactDOMClientDispatcher;
} else {
ReactDOMCurrentDispatcher.current.nextDispatcher = ReactDOMClientDispatcher;
}

function flushSync<R>(fn: void | (() => R)): void | R {
if (__DEV__) {
if (isAlreadyRendering()) {
console.error(
'flushSync was called from inside a lifecycle method. React cannot ' +
'flush when React is already rendering. Consider moving this call to ' +
'a scheduler task or micro task.',
);
}
}
if (ReactDOMClientDispatcher.nextDispatcher) {
return ReactDOMClientDispatcher.nextDispatcher.flushSync(() =>
flushSyncWithoutWarningIfAlreadyRendering(fn),
);
} else {
return flushSyncWithoutWarningIfAlreadyRendering(fn);
}
}

// We expect this to get inlined. It is a function mostly to communicate the special nature of
// how we resolve the HoistableRoot for ReactDOM.pre*() methods. Because we support calling
// these methods outside of render there is no way to know which Document or ShadowRoot is 'scoped'
Expand Down Expand Up @@ -2134,20 +2173,29 @@ function preconnectAs(
}

function prefetchDNS(href: string) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.prefetchDNS(href);
}
if (!enableFloat) {
return;
}
preconnectAs('dns-prefetch', href, null);
}

function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preconnect(href, crossOrigin);
}
if (!enableFloat) {
return;
}
preconnectAs('preconnect', href, crossOrigin);
}

function preload(href: string, as: string, options?: ?PreloadImplOptions) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preload(href, as, options);
}
if (!enableFloat) {
return;
}
Expand Down Expand Up @@ -2228,6 +2276,9 @@ function preload(href: string, as: string, options?: ?PreloadImplOptions) {
}

function preloadModule(href: string, options?: ?PreloadModuleImplOptions) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preloadModule(href, options);
}
if (!enableFloat) {
return;
}
Expand Down Expand Up @@ -2291,6 +2342,13 @@ function preinitStyle(
precedence: ?string,
options?: ?PreinitStyleOptions,
) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preinitStyle(
href,
precedence,
options,
);
}
if (!enableFloat) {
return;
}
Expand Down Expand Up @@ -2367,6 +2425,9 @@ function preinitStyle(
}

function preinitScript(src: string, options?: ?PreinitScriptOptions) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preinitScript(src, options);
}
if (!enableFloat) {
return;
}
Expand Down Expand Up @@ -2425,6 +2486,9 @@ function preinitModuleScript(
src: string,
options?: ?PreinitModuleScriptOptions,
) {
if (ReactDOMClientDispatcher.nextDispatcher) {
ReactDOMClientDispatcher.nextDispatcher.preinitModuleScript(src, options);
}
if (!enableFloat) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,18 @@ export const ReactDOMFlightServerDispatcher: HostDispatcher = {
preinitStyle,
preinitScript,
preinitModuleScript,
flushSync,
nextDispatcher: null,
};

function flushSync<R>(fn: void | (() => R)): void | R {
if (ReactDOMFlightServerDispatcher.nextDispatcher) {
return ReactDOMFlightServerDispatcher.nextDispatcher.flushSync(fn);
} else if (fn) {
return fn();
}
}

function prefetchDNS(href: string) {
if (enableFloat) {
if (typeof href === 'string' && href) {
Expand All @@ -48,6 +58,8 @@ function prefetchDNS(href: string) {
}
hints.add(key);
emitHint(request, 'D', href);
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.prefetchDNS(href);
}
}
}
Expand All @@ -71,6 +83,11 @@ function preconnect(href: string, crossOrigin?: ?CrossOriginEnum) {
} else {
emitHint(request, 'C', href);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preconnect(
href,
crossOrigin,
);
}
}
}
Expand Down Expand Up @@ -104,6 +121,12 @@ function preload(href: string, as: string, options?: ?PreloadImplOptions) {
} else {
emitHint(request, 'L', [href, as]);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preload(
href,
as,
options,
);
}
}
}
Expand All @@ -128,6 +151,11 @@ function preloadModule(href: string, options?: ?PreloadModuleImplOptions) {
} else {
return emitHint(request, 'm', href);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preloadModule(
href,
options,
);
}
}
}
Expand Down Expand Up @@ -162,6 +190,12 @@ function preinitStyle(
} else {
return emitHint(request, 'S', href);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preinitStyle(
href,
precedence,
options,
);
}
}
}
Expand All @@ -186,6 +220,11 @@ function preinitScript(href: string, options?: ?PreinitScriptOptions) {
} else {
return emitHint(request, 'X', href);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preinitScript(
href,
options,
);
}
}
}
Expand Down Expand Up @@ -213,6 +252,11 @@ function preinitModuleScript(
} else {
return emitHint(request, 'M', href);
}
} else if (ReactDOMFlightServerDispatcher.nextDispatcher) {
ReactDOMFlightServerDispatcher.nextDispatcher.preinitModuleScript(
href,
options,
);
}
}
}
Expand Down
Loading

0 comments on commit 91a323d

Please sign in to comment.