2018-05-19 11:29:11 +01:00
|
|
|
/**
|
2022-10-18 11:19:24 -04:00
|
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
2018-05-19 11:29:11 +01:00
|
|
|
*
|
|
|
|
|
* This source code is licensed under the MIT license found in the
|
|
|
|
|
* LICENSE file in the root directory of this source tree.
|
|
|
|
|
*/
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
module.exports = [
|
|
|
|
|
{
|
2024-11-05 15:05:04 -05:00
|
|
|
shortName: 'dom-browser',
|
2019-10-29 14:45:47 -07:00
|
|
|
entryPoints: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
2022-02-08 23:12:31 -05:00
|
|
|
'react-dom/unstable_testing',
|
2024-11-05 15:05:04 -05:00
|
|
|
'react-dom/src/server/react-dom-server.browser.js',
|
|
|
|
|
'react-dom/static.browser',
|
|
|
|
|
'react-dom/unstable_server-external-runtime',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.browser',
|
2024-11-05 15:05:04 -05:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.browser',
|
|
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
|
|
|
|
'react-dom/server.browser',
|
|
|
|
|
'react-dom/static.browser',
|
|
|
|
|
'react-dom/unstable_testing',
|
|
|
|
|
'react-dom/src/server/react-dom-server.browser',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerBrowser.js', // react-dom/server.browser
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticBrowser.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
|
|
|
|
'react-server-dom-webpack',
|
|
|
|
|
'react-server-dom-webpack/client',
|
|
|
|
|
'react-server-dom-webpack/client.browser',
|
|
|
|
|
'react-server-dom-webpack/server.browser',
|
|
|
|
|
'react-server-dom-webpack/static.browser',
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-webpack/client.browser
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackBrowser.js',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.browser',
|
2024-11-05 15:05:04 -05:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.browser',
|
|
|
|
|
'react-server-dom-webpack/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-webpack/src/server/react-flight-dom-server.browser
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2024-11-05 15:05:04 -05:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'dom-node',
|
|
|
|
|
entryPoints: [
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.node.js',
|
2024-04-08 12:27:20 -07:00
|
|
|
'react-dom/test-utils',
|
[ServerRenderer] Move fizz external runtime implementation to react-dom-bindings (#25617)
<!--
Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.
Before submitting a pull request, please make sure the following is
done:
1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn debug-test --watch TestName`, open
`chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
10. If you haven't already, complete the CLA.
Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->
Following
[comment](https://github.com/facebook/react/pull/25437#discussion_r1010944983)
in #25437 , the external runtime implementation should be moved from
`react-dom` to `react-dom-bindings`.
I did have a question here:
I set the entrypoint to `react-dom/unstable_server-external-runtime.js`,
since a.) I was following #25436 as an example and b.)
`react-dom-bindings` was missing a `README.md` and `npm/`. This also
involved adding the external runtime to `package.json`.
However, the external runtime isn't really a `react-dom` entrypoint. Is
this change alright, or should I change the bundling code instead?
## How did you test this change?
<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
If you leave this empty, your PR will very likely be closed.
-->
2022-11-03 11:15:29 -04:00
|
|
|
'react-dom/unstable_server-external-runtime',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.node.unbundled',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.node.unbundled',
|
2019-10-29 14:45:47 -07:00
|
|
|
],
|
2020-03-06 16:20:42 -08:00
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2022-09-28 19:05:50 -04:00
|
|
|
'react-dom-bindings',
|
2022-03-01 00:13:28 -05:00
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2022-06-18 22:34:31 -04:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom/static',
|
|
|
|
|
'react-dom/static.node',
|
2024-04-08 12:27:20 -07:00
|
|
|
'react-dom/test-utils',
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.node',
|
2021-06-14 21:37:44 -04:00
|
|
|
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
|
2022-06-18 22:34:31 -04:00
|
|
|
'react-dom/src/server/ReactDOMFizzStaticNode.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2020-12-08 08:08:57 -05:00
|
|
|
'react-server-dom-webpack',
|
2023-02-16 11:01:52 -05:00
|
|
|
'react-server-dom-webpack/client.node.unbundled',
|
2022-10-18 10:15:52 -04:00
|
|
|
'react-server-dom-webpack/server',
|
2023-02-16 11:01:52 -05:00
|
|
|
'react-server-dom-webpack/server.node.unbundled',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-webpack/static',
|
|
|
|
|
'react-server-dom-webpack/static.node.unbundled',
|
2025-06-06 17:14:15 -04:00
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.node
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-webpack/client.node
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerNode.js',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.node.unbundled',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.node.unbundled',
|
|
|
|
|
'react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-webpack/src/server/react-flight-dom-server.node
|
2022-03-01 00:13:28 -05:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
2022-09-15 15:31:31 -07:00
|
|
|
'shared/ReactDOMSharedInternals',
|
2023-12-15 21:38:01 -05:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNode.js',
|
2020-03-06 16:20:42 -08:00
|
|
|
],
|
2018-05-19 11:29:11 +01:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: true,
|
2018-11-30 11:38:22 -08:00
|
|
|
},
|
2023-09-27 10:03:57 -07:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-node-webpack',
|
|
|
|
|
entryPoints: [
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.node',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom/static',
|
|
|
|
|
'react-dom/static.node',
|
|
|
|
|
'react-dom/src/server/react-dom-server.node',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticNode.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-webpack',
|
|
|
|
|
'react-server-dom-webpack/client.node',
|
|
|
|
|
'react-server-dom-webpack/server',
|
|
|
|
|
'react-server-dom-webpack/server.node',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-webpack/static',
|
|
|
|
|
'react-server-dom-webpack/static.node',
|
2025-06-06 17:14:15 -04:00
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.node
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-webpack/client.node
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.node',
|
|
|
|
|
'react-server-dom-webpack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-webpack/src/server/react-flight-dom-server.node
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-webpack/node-register',
|
|
|
|
|
'react-server-dom-webpack/src/ReactFlightWebpackNodeRegister.js',
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
2023-12-15 21:38:01 -05:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNode.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'dom-node-turbopack',
|
|
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.node',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom/static',
|
|
|
|
|
'react-dom/static.node',
|
|
|
|
|
'react-dom/src/server/react-dom-server.node',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticNode.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-turbopack',
|
|
|
|
|
'react-server-dom-turbopack/client.node',
|
|
|
|
|
'react-server-dom-turbopack/server',
|
|
|
|
|
'react-server-dom-turbopack/server.node',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-turbopack/static',
|
|
|
|
|
'react-server-dom-turbopack/static.node',
|
2025-06-06 17:14:15 -04:00
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-turbopack/client.node
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightDOMClientNode.js', // react-server-dom-turbopack/client.node
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.node',
|
|
|
|
|
'react-server-dom-turbopack/src/server/ReactFlightDOMServerNode.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.node
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-turbopack/node-register',
|
|
|
|
|
'react-server-dom-turbopack/src/ReactFlightTurbopackNodeRegister.js',
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
2023-12-15 21:38:01 -05:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNode.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-node-parcel',
|
|
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.node',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.node',
|
|
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
|
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom/static',
|
|
|
|
|
'react-dom/static.node',
|
|
|
|
|
'react-dom/src/server/react-dom-server.node',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticNode.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
|
|
|
|
'react-server-dom-parcel',
|
|
|
|
|
'react-server-dom-parcel/client.node',
|
|
|
|
|
'react-server-dom-parcel/server',
|
|
|
|
|
'react-server-dom-parcel/server.node',
|
|
|
|
|
'react-server-dom-parcel/static',
|
|
|
|
|
'react-server-dom-parcel/static.node',
|
2025-06-06 17:14:15 -04:00
|
|
|
'react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-parcel/client.node
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/client/ReactFlightDOMClientNode.js', // react-server-dom-parcel/client.node
|
2024-12-12 14:39:25 -05:00
|
|
|
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.node',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.node',
|
|
|
|
|
'react-server-dom-parcel/src/server/ReactFlightDOMServerNode.js', // react-server-dom-parcel/src/server/react-flight-dom-server.node
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNode.js',
|
|
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2022-11-17 13:15:56 -08:00
|
|
|
{
|
2023-02-06 15:54:14 -05:00
|
|
|
shortName: 'dom-bun',
|
2024-11-05 15:05:04 -05:00
|
|
|
entryPoints: ['react-dom/src/server/react-dom-server.bun.js'],
|
2022-11-17 13:15:56 -08:00
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
2022-11-17 13:15:56 -08:00
|
|
|
'react-dom/server.bun',
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.bun',
|
2022-11-17 13:15:56 -08:00
|
|
|
'react-dom/src/server/ReactDOMFizzServerBun.js',
|
|
|
|
|
'react-dom-bindings',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2022-11-17 13:15:56 -08:00
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2022-11-17 13:15:56 -08:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2023-08-17 15:17:46 -07:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-browser-esm',
|
|
|
|
|
entryPoints: ['react-server-dom-esm/client.browser'],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-08-17 15:17:46 -07:00
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-08-17 15:17:46 -07:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom-bindings',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-08-17 15:17:46 -07:00
|
|
|
'react-server-dom-esm',
|
|
|
|
|
'react-server-dom-esm/client',
|
|
|
|
|
'react-server-dom-esm/client.browser',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-esm/client.browser
|
2023-08-17 15:17:46 -07:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2023-08-17 15:17:46 -07:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2023-09-27 10:03:57 -07:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-browser-turbopack',
|
|
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom-bindings',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-turbopack',
|
|
|
|
|
'react-server-dom-turbopack/client',
|
|
|
|
|
'react-server-dom-turbopack/client.browser',
|
|
|
|
|
'react-server-dom-turbopack/server.browser',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-turbopack/static.browser',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-turbopack/client.browser
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackBrowser.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',
|
|
|
|
|
'react-server-dom-turbopack/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.browser
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-browser-parcel',
|
|
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.browser',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.browser',
|
|
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
|
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
|
|
|
|
'react-server-dom-parcel',
|
|
|
|
|
'react-server-dom-parcel/client',
|
|
|
|
|
'react-server-dom-parcel/client.browser',
|
|
|
|
|
'react-server-dom-parcel/server.browser',
|
|
|
|
|
'react-server-dom-parcel/static.browser',
|
|
|
|
|
'react-server-dom-parcel/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-parcel/client.browser
|
2024-12-12 14:39:25 -05:00
|
|
|
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.browser',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.browser',
|
|
|
|
|
'react-server-dom-parcel/src/server/ReactFlightDOMServerBrowser.js', // react-server-dom-parcel/src/server/react-flight-dom-server.browser
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2023-02-07 15:10:01 -05:00
|
|
|
{
|
2023-02-16 11:01:52 -05:00
|
|
|
shortName: 'dom-edge-webpack',
|
2023-02-07 15:10:01 -05:00
|
|
|
entryPoints: [
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.edge.js',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-dom/static.edge',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.edge',
|
2023-02-07 15:10:01 -05:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-dom/server.edge',
|
|
|
|
|
'react-dom/static.edge',
|
|
|
|
|
'react-dom/unstable_testing',
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.edge',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticEdge.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-server-dom-webpack',
|
2023-02-16 11:01:52 -05:00
|
|
|
'react-server-dom-webpack/client.edge',
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-server-dom-webpack/server.edge',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-webpack/static.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-webpack/client.edge
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',
|
|
|
|
|
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',
|
2025-06-05 14:29:02 -04:00
|
|
|
'react-server-dom-webpack/src/client/react-flight-dom-client.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-webpack/src/server/react-flight-dom-server.edge',
|
|
|
|
|
'react-server-dom-webpack/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-webpack/src/server/react-flight-dom-server.edge
|
2023-02-07 15:10:01 -05:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2023-02-16 11:01:52 -05:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
2023-09-27 10:03:57 -07:00
|
|
|
shortName: 'dom-edge-turbopack',
|
2023-02-16 11:01:52 -05:00
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',
|
2023-02-16 11:01:52 -05:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-02-16 11:01:52 -05:00
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-dom/server.edge',
|
|
|
|
|
'react-dom/static.edge',
|
|
|
|
|
'react-dom/unstable_testing',
|
|
|
|
|
'react-dom/src/server/react-dom-server.edge',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticEdge.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-09-27 10:03:57 -07:00
|
|
|
'react-server-dom-turbopack',
|
|
|
|
|
'react-server-dom-turbopack/client.edge',
|
|
|
|
|
'react-server-dom-turbopack/server.edge',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-turbopack/static.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-turbopack/client.edge
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopack.js',
|
|
|
|
|
'react-server-dom-turbopack/src/client/ReactFlightClientConfigBundlerTurbopackServer.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',
|
|
|
|
|
'react-server-dom-turbopack/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-turbopack/src/server/react-flight-dom-server.edge
|
2023-02-16 11:01:52 -05:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2020-03-06 16:20:42 -08:00
|
|
|
],
|
2018-11-30 11:38:22 -08:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: true,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-edge-parcel',
|
|
|
|
|
entryPoints: [
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.edge',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.edge',
|
|
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
|
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
|
|
|
|
'react-dom/profiling',
|
|
|
|
|
'react-dom/server.edge',
|
|
|
|
|
'react-dom/static.edge',
|
|
|
|
|
'react-dom/unstable_testing',
|
|
|
|
|
'react-dom/src/server/react-dom-server.edge',
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticEdge.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
|
|
|
|
'react-server-dom-parcel',
|
|
|
|
|
'react-server-dom-parcel/client.edge',
|
|
|
|
|
'react-server-dom-parcel/server.edge',
|
|
|
|
|
'react-server-dom-parcel/static.edge',
|
|
|
|
|
'react-server-dom-parcel/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-parcel/client.edge
|
2024-12-12 14:39:25 -05:00
|
|
|
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
|
2025-06-06 11:07:40 -04:00
|
|
|
'react-server-dom-parcel/src/client/react-flight-dom-client.edge',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
'react-server-dom-parcel/src/server/react-flight-dom-server.edge',
|
|
|
|
|
'react-server-dom-parcel/src/server/ReactFlightDOMServerEdge.js', // react-server-dom-parcel/src/server/react-flight-dom-server.edge
|
|
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
Implement react-server-dom-parcel (#31725)
This adds a new `react-server-dom-parcel-package`, which is an RSC
integration for the Parcel bundler. It is mostly copied from the
existing webpack/turbopack integrations, with some changes to utilize
Parcel runtime APIs for loading and executing bundles/modules.
See https://github.com/parcel-bundler/parcel/pull/10043 for the Parcel
side of this, which includes the plugin needed to generate client and
server references. https://github.com/parcel-bundler/rsc-examples also
includes examples of various ways to use RSCs with Parcel.
Differences from other integrations:
* Client and server modules are all part of the same graph, and we use
Parcel's
[environments](https://parceljs.org/plugin-system/transformer/#the-environment)
to distinguish them. The server is the Parcel build entry point, and it
imports and renders server components in route handlers. When a `"use
client"` directive is seen, the environment changes and Parcel creates a
new client bundle for the page, combining all client modules together.
CSS from both client and server components are also combined
automatically.
* There is no separate manifest file that needs to be passed around by
the user. A [Runtime](https://parceljs.org/plugin-system/runtime/)
plugin injects client and server references as needed into the relevant
bundles, and registers server action ids using `react-server-dom-parcel`
automatically.
* A special `<Resources>` component is also generated by Parcel to
render the `<script>` and `<link rel="stylesheet">` elements needed for
a page, using the relevant info from the bundle graph.
Note: I've already published a 0.0.x version of this package to npm for
testing purposes but happy to add whoever needs access to it as well.
### Questions
* How to test this in the React repo. I'll have integration tests in
Parcel, but setting up all the different mocks and environments to
simulate that here seems challenging. I could try to copy how
Webpack/Turbopack do it but it's a bit different.
* Where to put TypeScript types. Right now I have some ambient types in
my [example
repo](https://github.com/parcel-bundler/rsc-examples/blob/main/types.d.ts)
but it would be nice for users not to copy and paste these. Can I
include them in the package or do they need to maintained separately in
definitelytyped? I would really prefer not to have to maintain code in
three different repos ideally.
---------
Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2024-12-11 22:58:51 -05:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2023-06-03 15:58:24 -04:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-node-esm',
|
|
|
|
|
entryPoints: [
|
|
|
|
|
'react-server-dom-esm/client.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-esm/src/server/react-flight-dom-server.node',
|
2023-06-03 15:58:24 -04:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-06-03 15:58:24 -04:00
|
|
|
'react-dom-bindings',
|
|
|
|
|
'react-dom/client',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/profiling',
|
2023-06-03 15:58:24 -04:00
|
|
|
'react-dom/server',
|
|
|
|
|
'react-dom/server.node',
|
|
|
|
|
'react-dom/static',
|
|
|
|
|
'react-dom/static.node',
|
2023-08-22 15:21:36 -04:00
|
|
|
'react-dom/src/server/react-dom-server.node',
|
2023-06-03 15:58:24 -04:00
|
|
|
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
|
|
|
|
|
'react-dom/src/server/ReactDOMFizzStaticNode.js',
|
2024-06-27 18:09:40 +02:00
|
|
|
'react-dom-bindings/src/server/ReactDOMFlightServerHostDispatcher.js',
|
|
|
|
|
'react-dom-bindings/src/server/ReactFlightServerConfigDOM.js',
|
|
|
|
|
'react-dom-bindings/src/shared/ReactFlightClientConfigDOM.js',
|
2023-06-03 15:58:24 -04:00
|
|
|
'react-server-dom-esm',
|
|
|
|
|
'react-server-dom-esm/client.node',
|
|
|
|
|
'react-server-dom-esm/server',
|
|
|
|
|
'react-server-dom-esm/server.node',
|
2024-08-15 14:28:28 -07:00
|
|
|
'react-server-dom-esm/static',
|
|
|
|
|
'react-server-dom-esm/static.node',
|
2024-08-14 18:10:40 -07:00
|
|
|
'react-server-dom-esm/src/client/ReactFlightDOMClientNode.js', // react-server-dom-esm/client.node
|
|
|
|
|
'react-server-dom-esm/src/server/react-flight-dom-server.node',
|
|
|
|
|
'react-server-dom-esm/src/server/ReactFlightDOMServerNode.js', // react-server-dom-esm/src/server/react-flight-dom-server.node
|
2023-06-03 15:58:24 -04:00
|
|
|
'react-devtools',
|
|
|
|
|
'react-devtools-core',
|
|
|
|
|
'react-devtools-shell',
|
|
|
|
|
'react-devtools-shared',
|
|
|
|
|
'shared/ReactDOMSharedInternals',
|
2023-12-15 21:38:01 -05:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNode.js',
|
2023-06-03 15:58:24 -04:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2021-06-14 15:54:30 -04:00
|
|
|
{
|
|
|
|
|
shortName: 'dom-legacy',
|
2021-06-14 19:23:19 -04:00
|
|
|
entryPoints: [
|
2022-02-09 11:37:17 -08:00
|
|
|
'react-dom/src/server/ReactDOMLegacyServerBrowser.js', // react-dom/server.browser
|
|
|
|
|
'react-dom/src/server/ReactDOMLegacyServerNode.js', // react-dom/server.node
|
2021-06-14 19:23:19 -04:00
|
|
|
],
|
2021-06-14 15:54:30 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2022-09-28 19:05:50 -04:00
|
|
|
'react-dom-bindings',
|
2023-09-27 09:53:31 -07:00
|
|
|
'react-dom/src/server/ReactDOMLegacyServerImpl.js', // not an entrypoint, but only usable in *Browser and *Node files
|
2021-06-14 15:54:30 -04:00
|
|
|
'react-dom/src/server/ReactDOMLegacyServerBrowser.js', // react-dom/server.browser
|
|
|
|
|
'react-dom/src/server/ReactDOMLegacyServerNode.js', // react-dom/server.node
|
2024-06-28 15:25:10 +02:00
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2024-06-28 15:25:10 +02:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'markup',
|
|
|
|
|
entryPoints: [
|
2024-08-14 19:22:44 +02:00
|
|
|
'react-markup/src/ReactMarkupClient.js', // react-markup
|
|
|
|
|
'react-markup/src/ReactMarkupServer.js', // react-markup/react-markup.react-server
|
2024-06-28 15:25:10 +02:00
|
|
|
],
|
|
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
|
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
|
|
|
|
'react-dom-bindings',
|
2024-08-14 19:22:44 +02:00
|
|
|
'react-markup',
|
2022-09-15 15:31:31 -07:00
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2021-06-14 15:54:30 -04:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
},
|
2018-05-19 11:29:11 +01:00
|
|
|
{
|
2023-05-17 20:33:25 -04:00
|
|
|
shortName: 'dom-fb',
|
2024-04-24 08:50:32 -07:00
|
|
|
entryPoints: [
|
|
|
|
|
'react-dom/src/ReactDOMFB.js',
|
|
|
|
|
'react-dom/src/ReactDOMTestingFB.js',
|
|
|
|
|
'react-server-dom-fb/src/ReactDOMServerFB.js',
|
|
|
|
|
],
|
2023-05-17 20:33:25 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-dom',
|
2024-04-24 08:50:32 -07:00
|
|
|
'react-dom/src/ReactDOMFB.js',
|
|
|
|
|
'react-dom/src/ReactDOMTestingFB.js',
|
|
|
|
|
'react-dom/src/ReactDOMReactServer.js',
|
2023-05-17 20:33:25 -04:00
|
|
|
'react-dom-bindings',
|
2024-04-18 16:41:04 -04:00
|
|
|
'react-server-dom-fb',
|
2023-05-17 20:33:25 -04:00
|
|
|
'shared/ReactDOMSharedInternals',
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
2023-05-17 20:33:25 -04:00
|
|
|
],
|
|
|
|
|
isFlowTyped: true,
|
|
|
|
|
isServerSupported: true,
|
|
|
|
|
isFlightSupported: false,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'native',
|
|
|
|
|
entryPoints: ['react-native-renderer'],
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-native-renderer',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
|
|
|
|
],
|
2018-05-19 11:29:11 +01:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: false,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'fabric',
|
|
|
|
|
entryPoints: ['react-native-renderer/fabric'],
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-native-renderer',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
|
|
|
|
],
|
2018-05-19 11:29:11 +01:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: false,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
shortName: 'test',
|
|
|
|
|
entryPoints: ['react-test-renderer'],
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-test-renderer',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
|
|
|
|
],
|
2018-05-19 11:29:11 +01:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: false,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
2020-03-07 11:23:30 -08:00
|
|
|
{
|
2023-05-17 20:33:25 -04:00
|
|
|
shortName: 'art',
|
|
|
|
|
entryPoints: ['react-art'],
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-art',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
|
|
|
|
],
|
2023-05-17 20:33:25 -04:00
|
|
|
isFlowTyped: false, // TODO: type it.
|
|
|
|
|
isServerSupported: false,
|
2020-11-02 21:49:48 -05:00
|
|
|
},
|
2018-05-19 11:29:11 +01:00
|
|
|
{
|
|
|
|
|
shortName: 'custom',
|
2018-11-30 11:38:22 -08:00
|
|
|
entryPoints: [
|
|
|
|
|
'react-reconciler',
|
2020-03-07 11:23:30 -08:00
|
|
|
'react-client/flight',
|
2019-10-29 14:45:47 -07:00
|
|
|
'react-server',
|
|
|
|
|
'react-server/flight',
|
2018-11-30 11:38:22 -08:00
|
|
|
],
|
[Flight] Track Awaits on I/O as Debug Info (#33388)
This lets us track what data each Server Component depended on. This
will be used by Performance Track and React DevTools.
We use Node.js `async_hooks`. This has a number of downside. It is
Node.js specific so this feature is not available in other runtimes
until something equivalent becomes available. It's [discouraged by
Node.js docs](https://nodejs.org/api/async_hooks.html#async-hooks). It's
also slow which makes this approach only really viable in development
mode. At least with stack traces. However, it's really the only solution
that gives us the data that we need.
The [Diagnostic
Channel](https://nodejs.org/api/diagnostics_channel.html) API is not
sufficient. Not only is many Node.js built-in APIs missing but all
libraries like databases are also missing. Were as `async_hooks` covers
pretty much anything async in the Node.js ecosystem.
However, even if coverage was wider it's not actually showing the
information we want. It's not enough to show the low level I/O that is
happening because that doesn't provide the context. We need the stack
trace in user space code where it was initiated and where it was
awaited. It's also not each low level socket operation that we want to
surface but some higher level concept which can span a sequence of I/O
operations but as far as user space is concerned.
Therefore this solution is anchored on stack traces and ignore listing
to determine what the interesting span is. It is somewhat
Promise-centric (and in particular async/await) because it allows us to
model an abstract span instead of just random I/O. Async/await points
are also especially useful because this allows Async Stacks to show the
full sequence which is not supported by random callbacks. However, if no
Promises are involved we still to our best to show the stack causing
plain I/O callbacks.
Additionally, we don't want to track all possible I/O. For example,
side-effects like logging that doesn't affect the rendering performance
doesn't need to be included. We only want to include things that
actually block the rendering output. We also need to track which data
blocks each component so that we can track which data caused a
particular subtree to suspend.
We can do this using `async_hooks` because we can track the graph of
what resolved what and then spawned what.
To track what suspended what, something has to resolve. Therefore it
needs to run to completion before we can show what it was suspended on.
So something that never resolves, won't be tracked for example.
We use the `async_hooks` in `ReactFlightServerConfigDebugNode` to build
up an `ReactFlightAsyncSequence` graph that collects the stack traces
for basically all I/O and Promises allocated in the whole app. This is
pretty heavy, especially the stack traces, but it's because we don't
know which ones we'll need until they resolve. We don't materialize the
stacks until we need them though.
Once they end up pinging the Flight runtime, we collect which current
executing task that pinged the runtime and then log the sequence that
led up until that runtime into the RSC protocol. Currently we only
include things that weren't already resolved before we started rendering
this task/component, so that we don't log the entire history each time.
Each operation is split into two parts. First a `ReactIOInfo` which
represents an I/O operation and its start/end time. Basically the start
point where it was start. This is basically represents where you called
`new Promise()` or when entering an `async function` which has an
implied Promise. It can be started in a different component than where
it's awaited and it can be awaited in multiple places. Therefore this is
global information and not associated with a specific Component.
The second part is `ReactAsyncInfo`. This represents where this I/O was
`await`:ed or `.then()` called. This is associated with a point in the
tree (usually the Promise that's a direct child of a Component). Since
you can have multiple different I/O awaited in a sequence technically it
forms a dependency graph but to simplify the model these awaits as
flattened into the `ReactDebugInfo` list. Basically it contains each
await in a sequence that affected this part from unblocking.
This means that the same `ReactAsyncInfo` can appear in mutliple
components if they all await the same `ReactIOInfo` but the same Promise
only appears once.
Promises that are only resolved by other Promises or immediately are not
considered here. Only if they're resolved by an I/O operation. We pick
the Promise basically on the border between user space code and ignored
listed code (`node_modules`) to pick the most specific span but abstract
enough to not give too much detail irrelevant to the current audience.
Similarly, the deepest `await` in user space is marked as the relevant
`await` point.
This feature is only available in the `node` builds of React. Not if you
use the `edge` builds inside of Node.js.
---------
Co-authored-by: Sebastian "Sebbie" Silbermann <silbermann.sebastian@gmail.com>
2025-06-03 14:14:40 -04:00
|
|
|
paths: [
|
|
|
|
|
'react-client/flight',
|
|
|
|
|
'react-server/flight',
|
|
|
|
|
'react-server/src/ReactFlightServerConfigDebugNoop.js',
|
|
|
|
|
],
|
2018-05-19 11:29:11 +01:00
|
|
|
isFlowTyped: true,
|
2019-10-29 14:45:47 -07:00
|
|
|
isServerSupported: true,
|
2018-05-19 11:29:11 +01:00
|
|
|
},
|
|
|
|
|
];
|