-
Notifications
You must be signed in to change notification settings - Fork 47.6k
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
Setup react-server-dom-parcel package #28138
Conversation
That's ok. It's really up to you where you want the versioning seams. If the This is the ideal end state though. You shouldn't even need a plugin to use RSC. Just a bundler and a runtime and you're ready to go like other JS module features. If the runtime is more stable than the manifest, then maybe a plugin versioned with the If even the runtime isn't stable, it's also fine to just keep it in canary releases. It's stable from a consumer's perspective but you need to pin it. |
@@ -140,3 +145,35 @@ export function preinitScriptForSSR( | |||
}); | |||
} | |||
} | |||
|
|||
export function preloadForSSR( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this unused?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at the moment, yes. I need to add more metadata to the manifest so I can determine if a chunk is an ES module or not. Right now I'm just assuming it is.
I suspect the CSS loading part is not quite right with how it wires up with Fizz. Maybe @gnoff can take a closer look. It's a good example why there's no "just let me provide a callback to do loading" because the protocol isn't fixed and if you're forced to use a limited protocol you might end up with a bad implementation. So changing the Config protocol is exactly the kind of solution we want to see if it's not sufficient. One of the reasons it looks like this, is because Webpack loads CSS using the same JS chunk protocol (it's actually more like hacked on top of the JS chunk loading). Having other bundlers help inform what variety of structures need to be supported. Next.js bundles CSS for these cases into the parent page to avoid CSS rule thrashing and improve loading. Note that the intended behavior for CSS loaded through Server Component is that they use the Suspensey CSS mechanism If you load a component that depends on both CSS and JS, it should ideally not block rendering the components inside the JS on the CSS loading. The JS should load first and render, while the CSS is still streaming in and then suspend on the CSS. Instead of waiting to do the CPU work on the client until the CSS has loaded. The assumption here is that even if you import CSS through the module system, you don't actually do anything that depends on reading that CSS back until the commit phase. So you should be able to initialize the JS module and resolve the client component before the CSS loads. To this, the CSS needs to be extracted into a That's an optimization you wouldn't get without framework support maybe though. |
One way to look at suspensey CSS loading is like SSR. It needs to be injected into the In Webpack terms this would be part of the "entry point" which the consumer is responsible for loading - not the bundler. |
Yeah, in Parcel, by default, the CSS for both the server and client components for each page will get bundled together. In the initial HTML there will be a |
How does it load new CSS for a different "page" if there's no client component on it and only server components with new CSS? For CSS in the client component I think conceptually it's like injecting the style in the RSC stream as a sibling to the client component element. This is a bit more technically correct because if there's a Suspense boundary around it, it can suspend on that CSS deeper. In theory there could be some internal plumbing in React to do that automatically. That was kind of the initial plan for client components and React.lazy, however, doing it that way would inject the same style many different times in the page - it would still be deduped by React but leading to higher overhead. It still doesn't help with server component only CSS dependencies. So currently the model is that whatever slot suspends for server components only CSS, is also the one that's used for client components as part of that "page". |
This uses the preinit mechanism which is not blocking. It's more like a preloading semantics but doing more work eagerly. This does add it to the Rendering |
Yeah it doesn't work if there are no client components at the moment. But even if there are client components it isn't ideal because the link element we inject will never be removed from the DOM when you navigate to a different page, and it blocks rendering as you pointed out. I like the idea of injecting a link element into the RSC stream. That way it would be removed by react when that server component gets unmounted. Then we wouldn't need to inject link elements at runtime or into the initial HTML via |
Note that React doesn’t actually immediately remove link tags that are using the “precedence” mode which is also how you opt in to suspensey css. Same thing with style tags and precedence. That’s because it should be possible to have both at once (eg for animations, prerendering, keeping things rendered while in offscreen mode), it helps avoid css thrash of recomputing all rules to existing elements when changing pages already loaded and it avoids thrashing when returning to a page. It also simplifies hydration. This strategy is fairly opinionated and ofc best with small rules or atomic CSS. However React then has the option to eventually run a GC to clean up if there’s too many rules and at a time where the rules would be recomputed anyway such as when new styles are loaded. |
What is "precedence" mode? I saw some references to it in the code but I couldn't find much info about it. Edit: found #25243. Not sure if that's the latest info about it. |
OK I think it'll look like this: import {Resources} from '@parcel/rsc';
export default function App() {
return (
<html>
<head>
<Resources />
</head>
{/* ... */}
</html>
);
} The |
Question: is there any downside to doing the same thing for scripts as we will do for CSS? If we inject a |
The difference is that the CSS isn't needed by React to render a tree. Where as JS is needed before we commit. React wouldn't necessarily inject the script while rendering it. Also, the RSC protocol needs to be able to refer to JS objects that are resolved through those. However, for things that are completely outside of the Client Reference system and React rendering this technique can be use. E.g. for loading Google Analytics or something global like that which isn't needed to do the render but just wires up later and async after commit. |
This pull request has been automatically marked as stale. If this pull request is still relevant, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize reviewing it yet. Your contribution is very much appreciated. |
Closing this pull request after a prolonged period of inactivity. If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you! |
This sets up a new
react-server-dom-parcel
package, which will be 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.Some other differences:
This is only a first pass. Some parts may still change as I make progress on the Parcel side of this, but I wanted to open a PR in case there is any feedback. I'm happy for it to be merged or not, but will probably send more followup changes as I make more progress.