Skip to content

Commit

Permalink
Restrict React DOM imports from Server Components (facebook#27382)
Browse files Browse the repository at this point in the history
Adds a separate entry point for the react-dom package when it's accessed
from a Server Component environment, using the "react-server" export
condition.

When you're inside a Server Component module, you won't be able to
import client-only APIs like useState. This applies to almost all React
DOM exports, except for Float ones like preload.
  • Loading branch information
acdlite authored and AndyPengc12 committed Apr 15, 2024
1 parent fbd362a commit b0c1f95
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 2 deletions.
7 changes: 7 additions & 0 deletions packages/react-dom/npm/react-dom.shared-subset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-dom.shared-subset.production.min.js');
} else {
module.exports = require('./cjs/react-dom.shared-subset.development.js');
}
5 changes: 4 additions & 1 deletion packages/react-dom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
"umd/"
],
"exports": {
".": "./index.js",
".": {
"react-server": "./react-dom.shared-subset.js",
"default": "./index.js"
},
"./client": "./client.js",
"./server": {
"workerd": "./server.edge.js",
Expand Down
19 changes: 19 additions & 0 deletions packages/react-dom/src/ReactDOMSharedSubset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* 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
*/

// This is the subset of APIs that can be accessed from Server Component modules
export {default as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED} from './ReactDOMSharedInternals';
export {
prefetchDNS,
preconnect,
preload,
preloadModule,
preinit,
preinitModule,
} from './shared/ReactDOMFloat';
12 changes: 12 additions & 0 deletions scripts/rollup/bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,18 @@ const bundles = [
externals: ['react'],
},

/******* React DOM Shared Subset *******/
{
bundleTypes: [NODE_DEV, NODE_PROD],
moduleType: RENDERER,
entry: 'react-dom/src/ReactDOMSharedSubset.js',
name: 'react-dom.shared-subset',
global: 'ReactDOM',
minifyWithProdErrorCodes: false,
wrapWithModuleBoundaries: false,
externals: ['react'],
},

/******* Test Utils *******/
{
moduleType: RENDERER_UTILS,
Expand Down
6 changes: 5 additions & 1 deletion scripts/rollup/forks.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ const forks = Object.freeze({
entry,
dependencies
) => {
if (entry === 'react-dom' || entry === 'react-dom/server-rendering-stub') {
if (
entry === 'react-dom' ||
entry === 'react-dom/server-rendering-stub' ||
entry === 'react-dom/src/ReactDOMSharedSubset.js'
) {
return './packages/react-dom/src/ReactDOMSharedInternals.js';
}
if (
Expand Down
9 changes: 9 additions & 0 deletions scripts/shared/inlinedHostConfigs.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = [
shortName: 'dom-node',
entryPoints: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom/unstable_testing',
'react-dom/src/server/react-dom-server.node.js',
'react-dom/static.node',
Expand All @@ -21,6 +22,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-dom/client',
'react-dom/server',
Expand Down Expand Up @@ -73,6 +75,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-dom/client',
'react-dom/server.browser',
Expand Down Expand Up @@ -101,6 +104,7 @@ module.exports = [
entryPoints: ['react-server-dom-esm/client.browser'],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom/client',
'react-dom/server',
'react-dom/server.node',
Expand Down Expand Up @@ -128,6 +132,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-dom/client',
'react-dom/server.edge',
Expand Down Expand Up @@ -158,6 +163,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-dom/client',
'react-dom/server',
Expand Down Expand Up @@ -192,6 +198,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-dom/client',
'react-dom/server',
Expand Down Expand Up @@ -224,6 +231,7 @@ module.exports = [
],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-server-dom-webpack',
'react-dom/src/server/ReactDOMLegacyServerImpl.js', // not an entrypoint, but only usable in *Brower and *Node files
Expand All @@ -241,6 +249,7 @@ module.exports = [
entryPoints: ['react-server-dom-fb/src/ReactDOMServerFB.js'],
paths: [
'react-dom',
'react-dom/src/ReactDOMSharedSubset.js',
'react-dom-bindings',
'react-server-dom-fb',
'shared/ReactDOMSharedInternals',
Expand Down

0 comments on commit b0c1f95

Please sign in to comment.