From d93b58a5e38cf06998da628932029291cc605c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Markb=C3=A5ge?= Date: Fri, 20 Nov 2020 11:47:13 -0500 Subject: [PATCH] Add flight specific entry point for react package (#20304) This configures the Flight fixture to use the "react-server" environment. This allows the package.json exports field to specify a different resolution in this environment. I use this in the "react" package to resolve to a new bundle that excludes the Hooks that aren't relevant in this environment like useState and useEffect. This allows us to error early if these names are imported. If we actually published ESM, it would we a static error. Now it's a runtime error. You can test this by importing useState in Container.js which is used by the client and server. --- fixtures/flight/package.json | 2 +- packages/react/npm/unstable-index.server.js | 7 ++++ packages/react/package.json | 15 ++++++++ .../unstable-index.server.experimental.js | 37 +++++++++++++++++++ packages/react/unstable-index.server.js | 12 ++++++ scripts/rollup/bundles.js | 9 +++++ scripts/rollup/forks.js | 6 +-- 7 files changed, 84 insertions(+), 4 deletions(-) create mode 100644 packages/react/npm/unstable-index.server.js create mode 100644 packages/react/unstable-index.server.experimental.js create mode 100644 packages/react/unstable-index.server.js diff --git a/fixtures/flight/package.json b/fixtures/flight/package.json index e8e30736f3fb2..3470e72e753aa 100644 --- a/fixtures/flight/package.json +++ b/fixtures/flight/package.json @@ -67,7 +67,7 @@ "prebuild": "cp -r ../../build/node_modules/* ./node_modules/", "start": "concurrently \"npm run start:server\" \"npm run start:client\"", "start:client": "node scripts/start.js", - "start:server": "NODE_ENV=development node --experimental-loader ./loader/index.js server", + "start:server": "NODE_ENV=development node --experimental-loader ./loader/index.js --conditions=react-server server", "start:prod": "node scripts/build.js && NODE_ENV=production node server", "build": "node scripts/build.js", "test": "node scripts/test.js --env=jsdom" diff --git a/packages/react/npm/unstable-index.server.js b/packages/react/npm/unstable-index.server.js new file mode 100644 index 0000000000000..431f257867779 --- /dev/null +++ b/packages/react/npm/unstable-index.server.js @@ -0,0 +1,7 @@ +'use strict'; + +if (process.env.NODE_ENV === 'production') { + module.exports = require('./cjs/react-unstable-index.server.production.min.js'); +} else { + module.exports = require('./cjs/react-unstable-index.server.development.js'); +} diff --git a/packages/react/package.json b/packages/react/package.json index 4ed34b868d917..993a45af3bc5f 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -17,9 +17,24 @@ "umd/", "jsx-runtime.js", "jsx-dev-runtime.js", + "unstable-index.server.js", "unstable-cache.js" ], "main": "index.js", + "exports": { + ".": { + "react-server": "./unstable-index.server.js", + "default": "./index.js" + }, + "./index": { + "react-server": "./unstable-index.server.js", + "default": "./index.js" + }, + "./build-info.json": "./build-info.json", + "./jsx-runtime": "./jsx-runtime.js", + "./jsx-dev-runtime": "./jsx-dev-runtime.js", + "./": "./" + }, "repository": { "type": "git", "url": "https://github.com/facebook/react.git", diff --git a/packages/react/unstable-index.server.experimental.js b/packages/react/unstable-index.server.experimental.js new file mode 100644 index 0000000000000..479094f46de6f --- /dev/null +++ b/packages/react/unstable-index.server.experimental.js @@ -0,0 +1,37 @@ +/** + * 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 { + Children, + createRef, + forwardRef, + lazy, + memo, + useCallback, + useContext, + useDebugValue, + useMemo, + useMutableSource as unstable_useMutableSource, + createMutableSource as unstable_createMutableSource, + Fragment, + Profiler, + StrictMode, + Suspense, + createElement, + cloneElement, + isValidElement, + version, + __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED, + // exposeConcurrentModeAPIs + useDeferredValue as unstable_useDeferredValue, + SuspenseList as unstable_SuspenseList, + unstable_useOpaqueIdentifier, + // enableDebugTracing + unstable_DebugTracingMode, +} from './src/React'; diff --git a/packages/react/unstable-index.server.js b/packages/react/unstable-index.server.js new file mode 100644 index 0000000000000..e2ae4ad2f62d6 --- /dev/null +++ b/packages/react/unstable-index.server.js @@ -0,0 +1,12 @@ +/** + * 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 + */ + +throw new Error( + 'This entry point is not yet supported outside of experimental channels', +); diff --git a/scripts/rollup/bundles.js b/scripts/rollup/bundles.js index 15bbc68d364da..f39d197eb0363 100644 --- a/scripts/rollup/bundles.js +++ b/scripts/rollup/bundles.js @@ -90,6 +90,15 @@ const bundles = [ externals: [], }, + /******* Isomorphic Server Only *******/ + { + bundleTypes: [NODE_DEV, NODE_PROD], + moduleType: ISOMORPHIC, + entry: 'react/unstable-index.server', + global: 'React', + externals: [], + }, + /******* React JSX Runtime *******/ { bundleTypes: [ diff --git a/scripts/rollup/forks.js b/scripts/rollup/forks.js index 03437e1f31034..4651b3fa86af9 100644 --- a/scripts/rollup/forks.js +++ b/scripts/rollup/forks.js @@ -43,7 +43,7 @@ const forks = Object.freeze({ // happens. Other bundles just require('object-assign') anyway. return null; } - if (entry === 'react') { + if (entry === 'react' || entry === 'react/unstable-index.server') { // Use the forked version that uses ES modules instead of CommonJS. return 'shared/forks/object-assign.inline-umd.js'; } @@ -64,8 +64,8 @@ const forks = Object.freeze({ // Without this fork, importing `shared/ReactSharedInternals` inside // the `react` package itself would not work due to a cyclical dependency. 'shared/ReactSharedInternals': (bundleType, entry, dependencies) => { - if (entry === 'react') { - return 'react/src/ReactSharedInternals'; + if (entry === 'react' || entry === 'react/unstable-index.server') { + return 'react/src/ReactSharedInternals.js'; } if (!entry.startsWith('react/') && dependencies.indexOf('react') === -1) { // React internals are unavailable if we can't reference the package.