Files
react/scripts/shared/inlinedHostConfigs.js

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

643 lines
26 KiB
JavaScript
Raw Normal View History

Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
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',
entryPoints: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/client',
'react-dom/profiling',
'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',
'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',
'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: [
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.node.js',
'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',
'react-server-dom-webpack/src/client/react-flight-dom-client.node.unbundled',
'react-server-dom-webpack/src/server/react-flight-dom-server.node.unbundled',
],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
Move createRoot/hydrateRoot to react-dom/client (#23385) * Move createRoot/hydrateRoot to /client We want these APIs ideally to be imported separately from things you might use in arbitrary components (like flushSync). Those other methods are "isomorphic" to how the ReactDOM tree is rendered. Similar to hooks. E.g. importing flushSync into a component that only uses it on the client should ideally not also pull in the entry client implementation on the server. This also creates a nicer parity with /server where the roots are in a separate entry point. Unfortunately, I can't quite do this yet because we have some legacy APIs that we plan on removing (like findDOMNode) and we also haven't implemented flushSync using a flag like startTransition does yet. Another problem is that we currently encourage these APIs to be aliased by /profiling (or unstable_testing). In the future you don't have to alias them because you can just change your roots to just import those APIs and they'll still work with the isomorphic forms. Although we might also just use export conditions for them. For that all to work, I went with a different strategy for now where the real API is in / but it comes with a warning if you use it. If you instead import /client it disables the warning in a wrapper. That means that if you alias / then import /client that will inturn import the alias and it'll just work. In a future breaking changes (likely when we switch to ESM) we can just remove createRoot/hydrateRoot from / and move away from the aliasing strategy. * Update tests to import from react-dom/client * Fix fixtures * Update warnings * Add test for the warning * Update devtools * Change order of react-dom, react-dom/client alias I think the order matters here. The first one takes precedence. * Require react-dom through client so it can be aliased Co-authored-by: Andrew Clark <git@andrewclark.io>
2022-03-01 00:13:28 -05:00
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/profiling',
'react-dom/server',
'react-dom/server.node',
'react-dom/static',
'react-dom/static.node',
'react-dom/test-utils',
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.node',
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
'react-dom/src/server/ReactDOMFizzStaticNode.js',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-webpack',
'react-server-dom-webpack/client.node.unbundled',
'react-server-dom-webpack/server',
'react-server-dom-webpack/server.node.unbundled',
'react-server-dom-webpack/static',
'react-server-dom-webpack/static.node.unbundled',
'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
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerNode.js',
'react-server-dom-webpack/src/client/react-flight-dom-client.node.unbundled',
'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
Move createRoot/hydrateRoot to react-dom/client (#23385) * Move createRoot/hydrateRoot to /client We want these APIs ideally to be imported separately from things you might use in arbitrary components (like flushSync). Those other methods are "isomorphic" to how the ReactDOM tree is rendered. Similar to hooks. E.g. importing flushSync into a component that only uses it on the client should ideally not also pull in the entry client implementation on the server. This also creates a nicer parity with /server where the roots are in a separate entry point. Unfortunately, I can't quite do this yet because we have some legacy APIs that we plan on removing (like findDOMNode) and we also haven't implemented flushSync using a flag like startTransition does yet. Another problem is that we currently encourage these APIs to be aliased by /profiling (or unstable_testing). In the future you don't have to alias them because you can just change your roots to just import those APIs and they'll still work with the isomorphic forms. Although we might also just use export conditions for them. For that all to work, I went with a different strategy for now where the real API is in / but it comes with a warning if you use it. If you instead import /client it disables the warning in a wrapper. That means that if you alias / then import /client that will inturn import the alias and it'll just work. In a future breaking changes (likely when we switch to ESM) we can just remove createRoot/hydrateRoot from / and move away from the aliasing strategy. * Update tests to import from react-dom/client * Fix fixtures * Update warnings * Add test for the warning * Update devtools * Change order of react-dom, react-dom/client alias I think the order matters here. The first one takes precedence. * Require react-dom through client so it can be aliased Co-authored-by: Andrew Clark <git@andrewclark.io>
2022-03-01 00:13:28 -05:00
'react-devtools',
'react-devtools-core',
'react-devtools-shell',
'react-devtools-shared',
'shared/ReactDOMSharedInternals',
'react-server/src/ReactFlightServerConfigDebugNode.js',
],
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
isFlowTyped: true,
isServerSupported: true,
[Fizz] New Server Rendering Infra (#14144) * [Fizz] Add Flow/Jest/Rollup build infra Add a new package for react-stream which allows for custom server renderer outputs. I picked the name because it's a reasonable name but also because the npm name is currently owned by a friend of the project. The react-dom build has its own inlined server renderer under the name `react-dom/fizz`. There is also a noop renderer to be used for testing. At some point we might add a public one to test-renderer but for now I don't want to have to think about public API design for the tests. * Add FormatConfig too We need to separate the format (DOM, React Native, etc) from the host running the server (Node, Browser, etc). * Basic wiring between Node, Noop and DOM configs The Node DOM API is pipeToNodeStream which accepts a writable stream. * Merge host and format config in dynamic react-stream entry point Simpler API this way but also avoids having to fork the wrapper config. Fixes noop builds. * Add setImmediate/Buffer globals to lint config Used by the server renderer * Properly include fizz.node.js Also use forwarding to it from fizz.js in builds so that tests covers this. * Make react-stream private since we're not ready to publish or even name it yet * Rename Renderer -> Streamer * Prefix react-dom/fizz with react-dom/unstable-fizz * Add Fizz Browser host config This lets Fizz render to WHATWG streams. E.g. for rendering in a Service Worker. I added react-dom/unstable-fizz.browser as the entry point for this. Since we now have two configurations of DOM. I had to add another inlinedHostConfigs configuration called `dom-browser`. The reconciler treats this configuration the same as `dom`. For stream it checks against the ReactFizzHostConfigBrowser instead of the Node one. * Add Fizz Browser Fixture This is for testing server rendering - on the client. * Lower version number to detach it from react-reconciler version
2018-11-30 11:38:22 -08:00
},
{
shortName: 'dom-node-webpack',
entryPoints: [
'react-server-dom-webpack/src/client/react-flight-dom-client.node',
'react-server-dom-webpack/src/server/react-flight-dom-server.node',
],
paths: [
'react-dom',
'react-dom-bindings',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'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',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-webpack',
'react-server-dom-webpack/client.node',
'react-server-dom-webpack/server',
'react-server-dom-webpack/server.node',
'react-server-dom-webpack/static',
'react-server-dom-webpack/static.node',
'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
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpack.js',
'react-server-dom-webpack/src/client/ReactFlightClientConfigBundlerWebpackServer.js',
'react-server-dom-webpack/src/client/react-flight-dom-client.node',
'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
'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',
'react-server/src/ReactFlightServerConfigDebugNode.js',
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-node-turbopack',
entryPoints: [
'react-server-dom-turbopack/src/client/react-flight-dom-client.node',
'react-server-dom-turbopack/src/server/react-flight-dom-server.node',
],
paths: [
'react-dom',
'react-dom-bindings',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'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',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-turbopack',
'react-server-dom-turbopack/client.node',
'react-server-dom-turbopack/server',
'react-server-dom-turbopack/server.node',
'react-server-dom-turbopack/static',
'react-server-dom-turbopack/static.node',
'react-server-dom-turbopack/src/client/ReactFlightDOMClientEdge.js', // react-server-dom-turbopack/client.node
'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',
'react-server-dom-turbopack/src/client/react-flight-dom-client.node',
'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
'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',
'react-server/src/ReactFlightServerConfigDebugNode.js',
],
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: [
'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',
'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
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
'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,
},
{
shortName: 'dom-bun',
2024-11-05 15:05:04 -05:00
entryPoints: ['react-dom/src/server/react-dom-server.bun.js'],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/client',
'react-dom/profiling',
'react-dom/server.bun',
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.bun',
'react-dom/src/server/ReactDOMFizzServerBun.js',
'react-dom-bindings',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'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',
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-browser-esm',
entryPoints: ['react-server-dom-esm/client.browser'],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/profiling',
'react-dom/server',
'react-dom/server.node',
'react-dom-bindings',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-esm',
'react-server-dom-esm/client',
'react-server-dom-esm/client.browser',
'react-server-dom-esm/src/client/ReactFlightDOMClientBrowser.js', // react-server-dom-esm/client.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',
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-browser-turbopack',
entryPoints: [
'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',
'react-server-dom-turbopack/src/server/react-flight-dom-server.browser',
],
paths: [
'react-dom',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'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-turbopack',
'react-server-dom-turbopack/client',
'react-server-dom-turbopack/client.browser',
'react-server-dom-turbopack/server.browser',
'react-server-dom-turbopack/static.browser',
'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',
'react-server-dom-turbopack/src/client/react-flight-dom-client.browser',
'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
'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',
],
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: [
'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
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
'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,
},
{
shortName: 'dom-edge-webpack',
entryPoints: [
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.edge.js',
'react-dom/static.edge',
'react-server-dom-webpack/src/client/react-flight-dom-client.edge',
'react-server-dom-webpack/src/server/react-flight-dom-server.edge',
],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/profiling',
'react-dom/server.edge',
'react-dom/static.edge',
'react-dom/unstable_testing',
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.edge',
'react-dom/src/server/ReactDOMFizzServerEdge.js', // react-dom/server.edge
'react-dom/src/server/ReactDOMFizzStaticEdge.js',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-webpack',
'react-server-dom-webpack/client.edge',
'react-server-dom-webpack/server.edge',
'react-server-dom-webpack/static.edge',
'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',
'react-server-dom-webpack/src/client/react-flight-dom-client.edge',
'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
'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',
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'dom-edge-turbopack',
entryPoints: [
'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',
'react-server-dom-turbopack/src/server/react-flight-dom-server.edge',
],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'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',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
'react-server-dom-turbopack',
'react-server-dom-turbopack/client.edge',
'react-server-dom-turbopack/server.edge',
'react-server-dom-turbopack/static.edge',
'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',
'react-server-dom-turbopack/src/client/react-flight-dom-client.edge',
'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
'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',
],
[Fizz] New Server Rendering Infra (#14144) * [Fizz] Add Flow/Jest/Rollup build infra Add a new package for react-stream which allows for custom server renderer outputs. I picked the name because it's a reasonable name but also because the npm name is currently owned by a friend of the project. The react-dom build has its own inlined server renderer under the name `react-dom/fizz`. There is also a noop renderer to be used for testing. At some point we might add a public one to test-renderer but for now I don't want to have to think about public API design for the tests. * Add FormatConfig too We need to separate the format (DOM, React Native, etc) from the host running the server (Node, Browser, etc). * Basic wiring between Node, Noop and DOM configs The Node DOM API is pipeToNodeStream which accepts a writable stream. * Merge host and format config in dynamic react-stream entry point Simpler API this way but also avoids having to fork the wrapper config. Fixes noop builds. * Add setImmediate/Buffer globals to lint config Used by the server renderer * Properly include fizz.node.js Also use forwarding to it from fizz.js in builds so that tests covers this. * Make react-stream private since we're not ready to publish or even name it yet * Rename Renderer -> Streamer * Prefix react-dom/fizz with react-dom/unstable-fizz * Add Fizz Browser host config This lets Fizz render to WHATWG streams. E.g. for rendering in a Service Worker. I added react-dom/unstable-fizz.browser as the entry point for this. Since we now have two configurations of DOM. I had to add another inlinedHostConfigs configuration called `dom-browser`. The reconciler treats this configuration the same as `dom`. For stream it checks against the ReactFizzHostConfigBrowser instead of the Node one. * Add Fizz Browser Fixture This is for testing server rendering - on the client. * Lower version number to detach it from react-reconciler version
2018-11-30 11:38:22 -08:00
isFlowTyped: true,
isServerSupported: true,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
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: [
'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
'react-server-dom-parcel/src/client/ReactFlightClientConfigBundlerParcel.js',
'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,
},
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
{
shortName: 'dom-node-esm',
entryPoints: [
'react-server-dom-esm/client.node',
'react-server-dom-esm/src/server/react-flight-dom-server.node',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
'react-dom-bindings',
'react-dom/client',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/profiling',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
'react-dom/server',
'react-dom/server.node',
'react-dom/static',
'react-dom/static.node',
[Fizz] Split ResponseState/Resources into RenderState/ResumableState (#27268) This exposes a `resume()` API to go with the `prerender()` (only in experimental). It doesn't work yet since we don't yet emit the postponed state so not yet tested. The main thing this does is rename ResponseState->RenderState and Resources->ResumableState. We separated out resources into a separate concept preemptively since it seemed like separate enough but probably doesn't warrant being a separate concept. The result is that we have a per RenderState in the Config which is really just temporary state and things that must be flushed completely in the prerender. Most things should be ResumableState. Most options are specified in the `prerender()` and transferred into the `resume()` but certain options that are unique per request can't be. Notably `nonce` is special. This means that bootstrap scripts and external runtime can't use `nonce` in this mode. They need to have a CSP configured to deal with external scripts, but not inline. We need to be able to restore state of things that we've already emitted in the prerender. We could have separate snapshot/restore methods that does this work when it happens but that means we have to explicitly do that work. This design is trying to keep to the principle that we just work with resumable data structures instead so that we're designing for it with every feature. It also makes restoring faster since it's just straight into the data structure. This is not yet a serializable format. That can be done in a follow up. We also need to vet that each step makes sense. Notably stylesToHoist is a bit unclear how it'll work.
2023-08-22 15:21:36 -04:00
'react-dom/src/server/react-dom-server.node',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
'react-dom/src/server/ReactDOMFizzServerNode.js', // react-dom/server.node
'react-dom/src/server/ReactDOMFizzStaticNode.js',
Add new package with renderToMarkup export (#30105) Name of the package is tbd (straw: `react-html`). It's a new package separate from `react-dom` though and can be used as a standalone package - e.g. also from a React Native app. ```js import {renderToMarkup} from '...'; const html = await renderToMarkup(<Component />); ``` The idea is that this is a helper for rendering HTML that is not intended to be hydrated. It's primarily intended to support a subset of HTML that can be used as embedding and not served as HTML documents from HTTP. For example as e-mails or in RSS/Atom feeds or other distributions. It's a successor to `renderToStaticMarkup`. A few differences: - This doesn't support "Client Components". It can only use the Server Components subset. No useEffect, no useState etc. since it will never be hydrated. Use of those are errors. - You also can't pass Client References so you can't use components marked with `"use client"`. - Unlike `renderToStaticMarkup` this does support async so you can suspend and use data from these components. - Unlike `renderToReadableStream` this does not support streaming or Suspense boundaries and any error rejects the promise. Since there's no feasible way to "client render" or patch up the document. - Form Actions are not supported since in an embedded environment there's no place to post back to across versions. You can render plain forms with fixed URLs though. - You can't use any resource preloading like `preload()` from `react-dom`. ## Implementation This first version in this PR only supports Server Components since that's the thing that doesn't have an existing API. Might add a Client Components version later that errors. We don't want to maintain a completely separate implementation for this use case so this uses the `dom-legacy` build dimension to wire up a build that encapsulates a Flight Server -> Flight Client -> Fizz stream to render Server Components that then get SSR:ed. There's no problem to use a Flight Client in a Server Component environment since it's already supported for Server-to-Server. Both of these use a bundler config that just errors for Client References though since we don't need any bundling integration and this is just a standalone package. Running Fizz in a Server Component environment is a problem though because it depends on "react" and it needs the client version. Therefore, for this build we embed the client version of "react" shared internals into the build. It doesn't need anything to be able to use those APIs since you can't call the client APIs anyway. One unfortunate thing though is that since Flight currently needs to go to binary and back, we need TextEncoder/TextDecoder to be available but this shouldn't really be necessary. Also since we use the legacy stream config, large strings that use byteLengthOfChunk errors atm. This needs to be fixed before shipping. I'm not sure what would be the best layering though that isn't unnecessarily burdensome to maintain. Maybe some kind of pass-through protocol that would also be useful in general - e.g. when Fizz and Flight are in the same process. --------- Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
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',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
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',
'react-server-dom-esm/static',
'react-server-dom-esm/static.node',
'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
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
'react-devtools',
'react-devtools-core',
'react-devtools-shell',
'react-devtools-shared',
'shared/ReactDOMSharedInternals',
'react-server/src/ReactFlightServerConfigDebugNode.js',
[Flight] Add bundler-less version of RSC using plain ESM (#26889) This isn't really meant to be actually used, there are many issues with this approach, but it shows the capabilities as a proof-of-concept. It's a new reference implementation package `react-server-dom-esm` as well as a fixture in `fixtures/flight-esm` (fork of `fixtures/flight`). This works pretty much the same as pieces we already have in the Webpack implementation but instead of loading modules using Webpack on the client it uses native browser ESM. To really show it off, I don't use any JSX in the fixture and so it also doesn't use Babel or any compilation of the files. This works because we don't actually bundle the server in the reference implementation in the first place. We instead use [Node.js Loaders](https://nodejs.org/api/esm.html#loaders) to intercept files that contain `"use client"` and `"use server"` and replace them. There's a simple check for those exact bytes, and no parsing, so this is very fast. Since the client isn't actually bundled, there's no module map needed. We can just send the file path to the file we want to load in the RSC payload for client references. Since the existing reference implementation for Node.js already used ESM to load modules on the server, that all works the same, including Server Actions. No bundling. There is one case that isn't implemented here. Importing a `"use server"` file from a Client Component. We don't have that implemented in the Webpack reference implementation neither - only in Next.js atm. In Webpack it would be implemented as a Webpack loader. There are a few ways this can be implemented without a bundler: - We can intercept the request from the browser importing this file in the HTTP server, and do a quick scan for `"use server"` in the file and replace it just like we do with loaders in Node.js. This is effectively how Vite works and likely how anyone using this technique would have to support JSX anyway. - We can use native browser "loaders" once that's eventually available in the same way as in Node.js. - We can generate import maps for each file and replace it with a pointer to a placeholder file. This requires scanning these ahead of time which defeats the purposes. Another case that's not implemented is the inline `"use server"` closure in a Server Component. That would require the existing loader to be a bit smarter but would still only "compile" files that contains those bytes in the fast path check. This would also happen in the loader that already exists so wouldn't do anything substantially different than what we currently have here.
2023-06-03 15:58:24 -04:00
],
isFlowTyped: true,
isServerSupported: true,
},
[Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276) * Wire up DOM legacy build * Hack to filter extra comments for testing purposes * Use string concat in renderToString I think this might be faster. We could probably use a combination of this technique in the stream too to lower the overhead. * Error if we can't complete the root synchronously Maybe this should always error but in the async forms we can just delay the stream until it resolves so it does have some useful semantics. In the synchronous form it's never useful though. I'm mostly adding the error because we're testing this behavior for renderToString specifically. * Gate memory leak tests of internals These tests don't translate as is to the new implementation and have been ported to the Fizz tests separately. * Enable Fizz legacy mode in stable * Add wrapper around the ServerFormatConfig for legacy mode This ensures that we can inject custom overrides without negatively affecting the new implementation. This adds another field for static mark up for example. * Wrap pushTextInstance to avoid emitting comments for text in static markup * Don't emit static mark up for completed suspense boundaries Completed and client rendered boundaries are only marked for the client to take over. Pending boundaries are still supported in case you stream non-hydratable mark up. * Wire up generateStaticMarkup to static API entry points * Mark as renderer for stable This shouldn't affect the FB one ideally but it's done with the same build so let's hope this works.
2021-06-14 15:54:30 -04:00
{
shortName: 'dom-legacy',
entryPoints: [
Remove deprecated wildcard folder mapping (#23256) * Remove deprecated folder mapping Node v16 deprecated the use of trailing "/" to define subpath folder mappings in the "exports" field of package.json. The recommendation is to explicitly list all our exports. We already do that for all our public modules. I believe the only reason we have a wildcard pattern is because our package.json files are also used at build time (by Rollup) to resolve internal source modules that don't appear in the final npm artifact. Changing trailing "/" to "/*" fixes the warnings. See https://nodejs.org/api/packages.html#subpath-patterns for more info. Since the wildcard pattern only exists so our build script has access to internal at build time, I've scoped the wildcard to "/src/*". Because our public modules are located outside the "src" directory, this means deep imports of our modules will no longer work: only packages that are listed in the "exports" field. The only two affected packages are react-dom and react. We need to be sure that all our public modules are still reachable. I audited the exports by comparing the entries to the "files" field in package.json, which represents a complete list of the files that are included in the final release artifact. At some point, we should add an e2e packaging test to prevent regressions; for now, we should have decent coverage because in CI we run our Jest test suite against the release artifacts. * Remove umd from exports Our expectation is that if you're using the UMD builds, you're not loading them through a normal module system like require or import. Instead you're probably copying the files directly or loading them from a CDN like unpkg.
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
],
[Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276) * Wire up DOM legacy build * Hack to filter extra comments for testing purposes * Use string concat in renderToString I think this might be faster. We could probably use a combination of this technique in the stream too to lower the overhead. * Error if we can't complete the root synchronously Maybe this should always error but in the async forms we can just delay the stream until it resolves so it does have some useful semantics. In the synchronous form it's never useful though. I'm mostly adding the error because we're testing this behavior for renderToString specifically. * Gate memory leak tests of internals These tests don't translate as is to the new implementation and have been ported to the Fizz tests separately. * Enable Fizz legacy mode in stable * Add wrapper around the ServerFormatConfig for legacy mode This ensures that we can inject custom overrides without negatively affecting the new implementation. This adds another field for static mark up for example. * Wrap pushTextInstance to avoid emitting comments for text in static markup * Don't emit static mark up for completed suspense boundaries Completed and client rendered boundaries are only marked for the client to take over. Pending boundaries are still supported in case you stream non-hydratable mark up. * Wire up generateStaticMarkup to static API entry points * Mark as renderer for stable This shouldn't affect the FB one ideally but it's done with the same build so let's hope this works.
2021-06-14 15:54:30 -04:00
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-dom/src/server/ReactDOMLegacyServerImpl.js', // not an entrypoint, but only usable in *Browser and *Node files
[Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276) * Wire up DOM legacy build * Hack to filter extra comments for testing purposes * Use string concat in renderToString I think this might be faster. We could probably use a combination of this technique in the stream too to lower the overhead. * Error if we can't complete the root synchronously Maybe this should always error but in the async forms we can just delay the stream until it resolves so it does have some useful semantics. In the synchronous form it's never useful though. I'm mostly adding the error because we're testing this behavior for renderToString specifically. * Gate memory leak tests of internals These tests don't translate as is to the new implementation and have been ported to the Fizz tests separately. * Enable Fizz legacy mode in stable * Add wrapper around the ServerFormatConfig for legacy mode This ensures that we can inject custom overrides without negatively affecting the new implementation. This adds another field for static mark up for example. * Wrap pushTextInstance to avoid emitting comments for text in static markup * Don't emit static mark up for completed suspense boundaries Completed and client rendered boundaries are only marked for the client to take over. Pending boundaries are still supported in case you stream non-hydratable mark up. * Wire up generateStaticMarkup to static API entry points * Mark as renderer for stable This shouldn't affect the FB one ideally but it's done with the same build so let's hope this works.
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
Add renderToMarkup for Client Components (#30121) Follow up to #30105. This supports `renderToMarkup` in a non-RSC environment (not the `react-server` condition). This is just a Fizz renderer but it errors at runtime when you use state, effects or event handlers that would require hydration - like the RSC version would. (Except RSC can give early errors too.) To do this I have to move the `react-html` builds to a new `markup` dimension out of the `dom-legacy` dimension so that we can configure this differently from `renderToString`/`renderToStaticMarkup`. Eventually that dimension can go away though if deprecated. That also helps us avoid dynamic configuration and we can just compile in the right configuration so the split helps anyway. One consideration is that if a compiler strips out useEffects or inlines initial state from useState, then it would not get called an the error wouldn't happen. Therefore to preserve semantics, a compiler would need to inject some call that can check the current renderer and whether it should throw. There is an argument that it could be useful to not error for these because it's possible to write components that works with SSR but are just optionally hydrated. However, there's also an argument that doing that silently is too easy to lead to mistakes and it's better to error - especially for the e-mail use case where you can't take it back but you can replay a queue that had failures. There are other ways to conditionally branch components intentionally. Besides if you want it to be silent you can still use renderToString (or better yet renderToReadableStream). The primary mechanism is the RSC environment and the client-environment is really the secondary one that's only there to support legacy environments. So this also ensures parity with the primary environment.
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',
Add renderToMarkup for Client Components (#30121) Follow up to #30105. This supports `renderToMarkup` in a non-RSC environment (not the `react-server` condition). This is just a Fizz renderer but it errors at runtime when you use state, effects or event handlers that would require hydration - like the RSC version would. (Except RSC can give early errors too.) To do this I have to move the `react-html` builds to a new `markup` dimension out of the `dom-legacy` dimension so that we can configure this differently from `renderToString`/`renderToStaticMarkup`. Eventually that dimension can go away though if deprecated. That also helps us avoid dynamic configuration and we can just compile in the right configuration so the split helps anyway. One consideration is that if a compiler strips out useEffects or inlines initial state from useState, then it would not get called an the error wouldn't happen. Therefore to preserve semantics, a compiler would need to inject some call that can check the current renderer and whether it should throw. There is an argument that it could be useful to not error for these because it's possible to write components that works with SSR but are just optionally hydrated. However, there's also an argument that doing that silently is too easy to lead to mistakes and it's better to error - especially for the e-mail use case where you can't take it back but you can replay a queue that had failures. There are other ways to conditionally branch components intentionally. Besides if you want it to be silent you can still use renderToString (or better yet renderToReadableStream). The primary mechanism is the RSC environment and the client-environment is really the secondary one that's only there to support legacy environments. So this also ensures parity with the primary environment.
2024-06-28 15:25:10 +02:00
],
isFlowTyped: true,
isServerSupported: true,
},
{
shortName: 'markup',
entryPoints: [
'react-markup/src/ReactMarkupClient.js', // react-markup
'react-markup/src/ReactMarkupServer.js', // react-markup/react-markup.react-server
Add renderToMarkup for Client Components (#30121) Follow up to #30105. This supports `renderToMarkup` in a non-RSC environment (not the `react-server` condition). This is just a Fizz renderer but it errors at runtime when you use state, effects or event handlers that would require hydration - like the RSC version would. (Except RSC can give early errors too.) To do this I have to move the `react-html` builds to a new `markup` dimension out of the `dom-legacy` dimension so that we can configure this differently from `renderToString`/`renderToStaticMarkup`. Eventually that dimension can go away though if deprecated. That also helps us avoid dynamic configuration and we can just compile in the right configuration so the split helps anyway. One consideration is that if a compiler strips out useEffects or inlines initial state from useState, then it would not get called an the error wouldn't happen. Therefore to preserve semantics, a compiler would need to inject some call that can check the current renderer and whether it should throw. There is an argument that it could be useful to not error for these because it's possible to write components that works with SSR but are just optionally hydrated. However, there's also an argument that doing that silently is too easy to lead to mistakes and it's better to error - especially for the e-mail use case where you can't take it back but you can replay a queue that had failures. There are other ways to conditionally branch components intentionally. Besides if you want it to be silent you can still use renderToString (or better yet renderToReadableStream). The primary mechanism is the RSC environment and the client-environment is really the secondary one that's only there to support legacy environments. So this also ensures parity with the primary environment.
2024-06-28 15:25:10 +02:00
],
paths: [
'react-dom',
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-markup',
'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',
[Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276) * Wire up DOM legacy build * Hack to filter extra comments for testing purposes * Use string concat in renderToString I think this might be faster. We could probably use a combination of this technique in the stream too to lower the overhead. * Error if we can't complete the root synchronously Maybe this should always error but in the async forms we can just delay the stream until it resolves so it does have some useful semantics. In the synchronous form it's never useful though. I'm mostly adding the error because we're testing this behavior for renderToString specifically. * Gate memory leak tests of internals These tests don't translate as is to the new implementation and have been ported to the Fizz tests separately. * Enable Fizz legacy mode in stable * Add wrapper around the ServerFormatConfig for legacy mode This ensures that we can inject custom overrides without negatively affecting the new implementation. This adds another field for static mark up for example. * Wrap pushTextInstance to avoid emitting comments for text in static markup * Don't emit static mark up for completed suspense boundaries Completed and client rendered boundaries are only marked for the client to take over. Pending boundaries are still supported in case you stream non-hydratable mark up. * Wire up generateStaticMarkup to static API entry points * Mark as renderer for stable This shouldn't affect the FB one ideally but it's done with the same build so let's hope this works.
2021-06-14 15:54:30 -04:00
],
isFlowTyped: true,
isServerSupported: true,
},
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
{
shortName: 'dom-fb',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
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',
],
paths: [
'react-dom',
[react-dom] move all client code to `react-dom/client` (#28271) This PR reorganizes the `react-dom` entrypoint to only pull in code that is environment agnostic. Previously if you required anything from this entrypoint in any environment the entire client reconciler was loaded. In a prior release we added a server rendering stub which you could alias in server environments to omit this unecessary code. After landing this change this entrypoint should not load any environment specific code. While a few APIs are truly client (browser) only such as createRoot and hydrateRoot many of the APIs you import from this package are only useful in the browser but could concievably be imported in shared code (components running in Fizz or shared components as part of an RSC app). To avoid making these require opting into the client bundle we are keeping them in the `react-dom` entrypoint and changing their implementation so that in environments where they are not particularly useful they do something benign and expected. #### Removed APIs The following APIs are being removed in the next major. Largely they have all been deprecated already and are part of legacy rendering modes where concurrent features of React are not available * `render` * `hydrate` * `findDOMNode` * `unmountComponentAtNode` * `unstable_createEventHandle` * `unstable_renderSubtreeIntoContainer` * `unstable_runWithPrioirty` #### moved Client APIs These APIs were available on both `react-dom` (with a warning) and `react-dom/client`. After this change they are only available on `react-dom/client` * `createRoot` * `hydrateRoot` #### retained APIs These APIs still exist on the `react-dom` entrypoint but have normalized behavior depending on which renderers are currently in scope * `flushSync`: will execute the function (if provided) inside the flushSync implemention of FlightServer, Fizz, and Fiber DOM renderers. * `unstable_batchedUpdates`: This is a noop in concurrent mode because it is now the only supported behavior because there is no legacy rendering mode * `createPortal`: This just produces an object. It can be called from anywhere but since you will probably not have a handle on a DOM node to pass to it it will likely warn in environments other than the browser * preloading APIS such as `preload`: These methods will execute the preload across all renderers currently in scope. Since we resolve the Request object on the server using AsyncLocalStorage or the current function stack in practice only one renderer should act upon the preload. In addition to these changes the server rendering stub now just rexports everything from `react-dom`. In a future minor we will add a warning when using the stub and in the next major we will remove the stub altogether
2024-04-24 08:50:32 -07:00
'react-dom/src/ReactDOMFB.js',
'react-dom/src/ReactDOMTestingFB.js',
'react-dom/src/ReactDOMReactServer.js',
'react-dom-bindings',
'react-server-dom-fb',
'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',
],
isFlowTyped: true,
isServerSupported: true,
isFlightSupported: false,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
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',
],
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
isFlowTyped: true,
isServerSupported: false,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
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',
],
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
isFlowTyped: true,
isServerSupported: false,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
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',
],
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
isFlowTyped: true,
isServerSupported: false,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01: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',
],
isFlowTyped: false, // TODO: type it.
isServerSupported: false,
},
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
{
shortName: 'custom',
[Fizz] New Server Rendering Infra (#14144) * [Fizz] Add Flow/Jest/Rollup build infra Add a new package for react-stream which allows for custom server renderer outputs. I picked the name because it's a reasonable name but also because the npm name is currently owned by a friend of the project. The react-dom build has its own inlined server renderer under the name `react-dom/fizz`. There is also a noop renderer to be used for testing. At some point we might add a public one to test-renderer but for now I don't want to have to think about public API design for the tests. * Add FormatConfig too We need to separate the format (DOM, React Native, etc) from the host running the server (Node, Browser, etc). * Basic wiring between Node, Noop and DOM configs The Node DOM API is pipeToNodeStream which accepts a writable stream. * Merge host and format config in dynamic react-stream entry point Simpler API this way but also avoids having to fork the wrapper config. Fixes noop builds. * Add setImmediate/Buffer globals to lint config Used by the server renderer * Properly include fizz.node.js Also use forwarding to it from fizz.js in builds so that tests covers this. * Make react-stream private since we're not ready to publish or even name it yet * Rename Renderer -> Streamer * Prefix react-dom/fizz with react-dom/unstable-fizz * Add Fizz Browser host config This lets Fizz render to WHATWG streams. E.g. for rendering in a Service Worker. I added react-dom/unstable-fizz.browser as the entry point for this. Since we now have two configurations of DOM. I had to add another inlinedHostConfigs configuration called `dom-browser`. The reconciler treats this configuration the same as `dom`. For stream it checks against the ReactFizzHostConfigBrowser instead of the Node one. * Add Fizz Browser Fixture This is for testing server rendering - on the client. * Lower version number to detach it from react-reconciler version
2018-11-30 11:38:22 -08:00
entryPoints: [
'react-reconciler',
'react-client/flight',
'react-server',
'react-server/flight',
[Fizz] New Server Rendering Infra (#14144) * [Fizz] Add Flow/Jest/Rollup build infra Add a new package for react-stream which allows for custom server renderer outputs. I picked the name because it's a reasonable name but also because the npm name is currently owned by a friend of the project. The react-dom build has its own inlined server renderer under the name `react-dom/fizz`. There is also a noop renderer to be used for testing. At some point we might add a public one to test-renderer but for now I don't want to have to think about public API design for the tests. * Add FormatConfig too We need to separate the format (DOM, React Native, etc) from the host running the server (Node, Browser, etc). * Basic wiring between Node, Noop and DOM configs The Node DOM API is pipeToNodeStream which accepts a writable stream. * Merge host and format config in dynamic react-stream entry point Simpler API this way but also avoids having to fork the wrapper config. Fixes noop builds. * Add setImmediate/Buffer globals to lint config Used by the server renderer * Properly include fizz.node.js Also use forwarding to it from fizz.js in builds so that tests covers this. * Make react-stream private since we're not ready to publish or even name it yet * Rename Renderer -> Streamer * Prefix react-dom/fizz with react-dom/unstable-fizz * Add Fizz Browser host config This lets Fizz render to WHATWG streams. E.g. for rendering in a Service Worker. I added react-dom/unstable-fizz.browser as the entry point for this. Since we now have two configurations of DOM. I had to add another inlinedHostConfigs configuration called `dom-browser`. The reconciler treats this configuration the same as `dom`. For stream it checks against the ReactFizzHostConfigBrowser instead of the Node one. * Add Fizz Browser Fixture This is for testing server rendering - on the client. * Lower version number to detach it from react-reconciler version
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',
],
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
isFlowTyped: true,
isServerSupported: true,
Resolve host configs at build time (#12792) * Extract base Jest config This makes it easier to change the source config without affecting the build test config. * Statically import the host config This changes react-reconciler to import HostConfig instead of getting it through a function argument. Rather than start with packages like ReactDOM that want to inline it, I started with React Noop and ensured that *custom* renderers using react-reconciler package still work. To do this, I'm making HostConfig module in the reconciler look at a global variable by default (which, in case of the react-reconciler npm package, ends up being the host config argument in the top-level scope). This is still very broken. * Add scaffolding for importing an inlined renderer * Fix the build * ES exports for renderer methods * ES modules for host configs * Remove closures from the reconciler * Check each renderer's config with Flow * Fix uncovered Flow issue We know nextHydratableInstance doesn't get mutated inside this function, but Flow doesn't so it thinks it may be null. Help Flow. * Prettier * Get rid of enable*Reconciler flags They are not as useful anymore because for almost all cases (except third party renderers) we *know* whether it supports mutation or persistence. This refactoring means react-reconciler and react-reconciler/persistent third-party packages now ship the same thing. Not ideal, but this seems worth how simpler the code becomes. We can later look into addressing it by having a single toggle instead. * Prettier again * Fix Flow config creation issue * Fix imprecise Flow typing * Revert accidental changes
2018-05-19 11:29:11 +01:00
},
];