Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React Server Components #10043

Merged
merged 41 commits into from
Dec 22, 2024
Merged

React Server Components #10043

merged 41 commits into from
Dec 22, 2024

Conversation

devongovett
Copy link
Member

@devongovett devongovett commented Dec 9, 2024

This adds initial support for React Server Components to Parcel. This involves handling the "use client" and "use server" directives using Parcel's existing multi-environment support. With RSC, the server becomes the entry point of the app instead of an HTML file. Each root page component is imported by the server and becomes a code splitting point. When we see a "use client" directive, the bundler creates a parallel bundle containing the client code needed for that page.

Since Parcel is not a framework, you have full control over how RSC is implemented in your app, including how and when server components load (e.g. via fetch, SSR, etc.), how routing works, how server actions are sent, what they return, etc. This enables things like integrating RSCs into existing client driven apps as well as the typical server driven setups and static site generation.

In terms of implementation, the JS transformer is responsible for handling the "use client" and "use server" directives and setting the appropriate environments. A new @parcel/runtime-rsc plugin generates the client and server references needed by React, using the react-server-dom-parcel package which will be in the React repo (see facebook/react#31725). This enables server components to render client components, and client components to call server actions. It also generates code to inject the necessary <script> and <style> elements for each page, so that client components and stylesheets are efficiently bundled and loaded.

The HMR runtime has been updated to also work on the server. When server files are updated, both the server and client handle this, and the page reloads. The client can also intercept an event when this happens to avoid a full page reload and preserve state.

Other changes are to better support multi-environment setups like RSC with shared assets. With RSC, the server bundle needs to be able to import client modules since SSR uses client React. This is done by importing using the with {env: 'react-client'} import attribute. See the individual commits for more details on other changes.

See this repo for some example apps and detailed descriptions of how they work: /~https://github.com/parcel-bundler/rsc-examples

sebmarkbage added a commit to facebook/react that referenced this pull request Dec 12, 2024
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 parcel-bundler/parcel#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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant