-
Notifications
You must be signed in to change notification settings - Fork 47.5k
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
[Flight] Add support for Module References in transport protocol #20121
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 8e54638:
|
Details of bundled changes.Comparing: 343d7a4...8e54638 react
react-transport-dom-relay
react-is
react-transport-dom-webpack
react-client
react-server
React: size: 0.0%, gzip: 0.0% Size changes (experimental) |
Details of bundled changes.Comparing: 343d7a4...8e54638 react
react-transport-dom-relay
react-is
react-transport-dom-webpack
react-client
react-server
React: size: 0.0%, gzip: 0.0% Size changes (stable) |
// we don't know which Flight build this will end up being used | ||
// with. | ||
type.$$typeof === REACT_MODULE_REFERENCE || | ||
type._moduleId !== undefined || |
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.
I don't really get this. Why can't we use the brand check? Why can't different systems agree on the Symbol to use if they have to agree on the field name anyway?
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.
They don’t have to agree on either. For now it just has to match one or the other. The field check is just because I can’t require JSResourceReference in other environments but it should really be an instanceof check. We just have to add all possible checks here. If this was a true private field we couldn’t check the field neither. That might even mean that we have to relax it to accept all objects.
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.
Ugh. This didn't even work because we obscure underscore prefixed properties.
I don't really like this approach because as it's currently set up, this will yield a different value on the output than the input of serialization.
So input is This is actually fine if we stick to the automatic conversion of import statements because we can pretend to TypeScript that it's the real value, but not for the longer term asset reference or FB variant which is an explicit reference object. Another approach would be to send I think a better approach would be input In general, the reason it's hard to just use a Another approach would be to treat all references as |
I guess since there are two different approaches: 1) Explicit call to get a reference. 2) A reference is automatically created by the compiler. There really need to be two different wrapper objects that yield the different semantics. |
This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects.
We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced.
This emits module references where ever they occur. In blocks or even directly in elements.
I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh.
Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them.
Seems like our compiler is not happy with stripping this.
2aaf7a9
to
8e54638
Compare
Summary: Base sync before adding Flight files. This sync includes the following changes: - **[454c2211c](facebook/react@454c2211c )**: Refactor SchedulerHostConfigs ([#20025](facebook/react#20025)) //<Ricky>// - **[56e9feead](facebook/react@56e9feead )**: Remove Blocks ([#20138](facebook/react#20138)) //<Sebastian Markbåge>// - **[3fbd47b86](facebook/react@3fbd47b86 )**: Serialize pending server components by reference (lazy component) ([#20137](facebook/react#20137)) //<Sebastian Markbåge>// - **[930ce7c15](facebook/react@930ce7c15 )**: Allow values to be encoded by "reference" to a value rather than the value itself ([#20136](facebook/react#20136)) //<Sebastian Markbåge>// - **[39eb6d176](facebook/react@39eb6d176 )**: Rename ([#20134](facebook/react#20134)) //<Sebastian Markbåge>// - **[ffd842335](facebook/react@ffd842335 )**: [Flight] Add support for Module References in transport protocol ([#20121](facebook/react#20121)) //<Sebastian Markbåge>// - **[343d7a4a7](facebook/react@343d7a4a7 )**: Fast Refresh: Don't block DevTools commit hook ([#20129](facebook/react#20129)) //<Brian Vaughn>// - **[779a472b0](facebook/react@779a472b0 )**: Prevent inlining into recursive commit functions ([#20105](facebook/react#20105)) //<Andrew Clark>// - **[25b18d31c](facebook/react@25b18d31c )**: Traverse commit phase effects iteratively ([#20094](facebook/react#20094)) //<Andrew Clark>// Changelog: [General][Changed] - React Native sync for revisions 4e5d7fa...454c221 Reviewed By: rickhanlonii Differential Revision: D24698701 fbshipit-source-id: dfaf692b1051150355dece1657764a484b7ae603
…ebook#20121) * Refactor Flight to require a module reference to be brand checked This exposes a host environment (bundler) specific hook to check if an object is a module reference. This will be used so that they can be passed directly into Flight without needing additional wrapper objects. * Emit module references as a special type of value We already have JSON and errors as special types of "rows". This encodes module references as a special type of row value. This was always the intention because it allows those values to be emitted first in the stream so that as a large models stream down, we can start preloading as early as possible. We preload the module when they resolve but we lazily require them as they are referenced. * Emit module references where ever they occur This emits module references where ever they occur. In blocks or even directly in elements. * Don't special case the root row I originally did this so that a simple stream is also just plain JSON. However, since we might want to emit things like modules before the root module in the stream, this gets unnecessarily complicated. We could add this back as a special case if it's the first byte written but meh. * Update the protocol * Add test for using a module reference as a client component * Relax element type check Since Flight now accepts a module reference as returned by any bundler system, depending on the renderer running. We need to drastically relax the check to include all of them. We can add more as we discover them. * Move flow annotation Seems like our compiler is not happy with stripping this. * Some bookkeeping bug * Can't use the private field to check
This is the first in a series of refactors. It adds a first-class type of row value for modules. This was always the idea since they can be preloaded earlier if they're special cased in the stream.
It also accepts a "Module Reference" object anywhere to be serialized in the protocol. This includes the type position of JSX. This is now how client components are defined.
These objects need a non-JSON serializable brand check like symbol check or instanceof. However, React doesn't actually define what kind of object it is. The host environment, i.e. bundler, does. So for the Relay www integration we use JSResource. For the webpack one I temporarily use a react symbol but it should really be something else like an AssetReference object.
All these has to now be allowlisted in isValidElementTypes for every possible bundler environment.
Some follow ups: