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

[Flight] Basic Streaming Suspense Support #17285

Merged
merged 6 commits into from
Nov 6, 2019

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Nov 6, 2019

This adds basic Suspense support to Flight by streaming the response.

First it sends one line with the root JSON model. Within the model holes are replaced with "$" followed by a hex ID. E.g. "$12AB3".

Subsequent lines begin with "J" followed by a hex ID.

So an example response may look something like:

{"some":{"json":"$1"},data:["$1","$2"]}
J1:{"more":"data"}
J2:{"even":"more"}

The client suspends if you try to access an unresolved value. Once a new line comes in it unsuspends that part of the model.

Currently this suspending is implemented as a getter but it could also be a Proxy. However, more likely is that we'll hide this behind an explicit API that unwraps both components and its data in the future.

Errors

If the server errors while rendering one of the models that error is encoded with an "E" prefix:

{"bad":"$1","good":"$2"}
E1:{"message":"An error happened","stack": "\n..."}
J2:{"this":"worked"}

When this happens, the previously suspended part of the model now resolves and starts throwing an error on the client. This will then be caught by an error boundary on the client. Unrelated parts of the response can still continue rendering though.

If the connection dies, then all remaining pending promises resolve and start throwing an error which are caught by error boundaries. Previously resolved parts don't error though.

There's a prioritization scheme so errors are emitted at lower priority in the stream than models.

Future Additions

I added a comment describing the protocol. The protocol also includes space for a few other types of data.

  • URL: This can be used to emit URL rows at higher priority than models and can be used to preload other resources without waiting for or even parsing the JSON models yet.
  • Blob: Traditionally sending binary data is a PITA in existing protocol. We should just have this built-in. It's especially efficient with modern stream APIs. This is important in data heavy use cases like data viz.
  • HTML: Instead of encoding HTML inside JSON we can just send it as raw HTML for faster parsing and more efficient size. We can also encode that we generated this HTML (using React SSR with proper data structures) in the encoding. So we can by-pass dangerouslySetInnerHTML and just provide a React element that can be rendered directly.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Nov 6, 2019

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 387c233:

Sandbox Source
flamboyant-snow-w1vb7 Configuration

@sizebot
Copy link

sizebot commented Nov 6, 2019

Size changes (stable)

ReactDOM: size: 🔺+62.2%, gzip: 🔺+58.2%

Details of bundled changes.

Comparing: 62ef250...387c233

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom-unstable-flight-server.browser.production.min.js 🔺+136.3% 🔺+89.4% 1.12 KB 2.64 KB 679 B 1.26 KB NODE_PROD
react-dom-unstable-flight-client.development.js +80.3% +62.4% 4.83 KB 8.7 KB 1.59 KB 2.59 KB UMD_DEV
react-dom-unstable-flight-client.production.min.js 🔺+62.2% 🔺+58.2% 1.78 KB 2.88 KB 866 B 1.34 KB UMD_PROD
react-dom-unstable-flight-server.node.development.js +112.9% +76.9% 4.49 KB 9.57 KB 1.77 KB 3.14 KB NODE_DEV
react-dom.development.js 0.0% 0.0% 951.42 KB 951.42 KB 215 KB 215 KB UMD_DEV
react-dom-server.browser.production.min.js 0.0% 0.0% 19.85 KB 19.85 KB 7.38 KB 7.38 KB NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 3.87 KB 3.87 KB 1.54 KB 1.54 KB UMD_DEV
react-dom-unstable-flight-server.node.production.min.js 🔺+128.4% 🔺+80.8% 1.18 KB 2.71 KB 712 B 1.26 KB NODE_PROD
react-dom.production.min.js 0.0% 0.0% 116.16 KB 116.16 KB 37.43 KB 37.43 KB UMD_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.1% 1.2 KB 1.2 KB 703 B 704 B UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 119.73 KB 119.73 KB 38.49 KB 38.5 KB UMD_PROFILING
react-dom.development.js 0.0% 0.0% 945.53 KB 945.53 KB 213.41 KB 213.41 KB NODE_DEV
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.13 KB 60.13 KB 15.79 KB 15.79 KB UMD_DEV
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.2% 1.04 KB 1.04 KB 634 B 635 B NODE_PROD
react-dom-unstable-flight-server.browser.development.js +110.1% +71.0% 4.44 KB 9.32 KB 1.79 KB 3.06 KB UMD_DEV
react-dom-unstable-flight-server.browser.production.min.js 🔺+115.0% 🔺+78.6% 1.32 KB 2.83 KB 761 B 1.33 KB UMD_PROD
react-dom-unstable-flight-server.browser.development.js +115.4% +73.8% 4.23 KB 9.12 KB 1.73 KB 3.01 KB NODE_DEV
react-dom-server.node.development.js 0.0% 0.0% 137.39 KB 137.39 KB 36.09 KB 36.09 KB NODE_DEV
react-dom-unstable-flight-client.development.js +83.3% +64.9% 4.65 KB 8.53 KB 1.54 KB 2.55 KB NODE_DEV
react-dom-server.node.production.min.js 0.0% 0.0% 20.26 KB 20.26 KB 7.53 KB 7.53 KB NODE_PROD
react-dom-unstable-flight-client.production.min.js 🔺+68.0% 🔺+65.0% 1.61 KB 2.71 KB 792 B 1.28 KB NODE_PROD
react-dom-test-utils.production.min.js 0.0% 0.0% 11.17 KB 11.17 KB 4.14 KB 4.14 KB UMD_PROD
react-dom-test-utils.development.js 0.0% 0.0% 54.53 KB 54.53 KB 15.24 KB 15.24 KB NODE_DEV
react-dom-unstable-fizz.node.development.js -0.2% -0.4% 3.96 KB 3.95 KB 1.52 KB 1.52 KB NODE_DEV
react-dom-server.browser.production.min.js 0.0% -0.0% 19.93 KB 19.93 KB 7.39 KB 7.38 KB UMD_PROD

react-server

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-server-flight.development.js +96.8% +71.5% 5.24 KB 10.31 KB 1.92 KB 3.3 KB NODE_DEV
react-server-flight.production.min.js 🔺+105.7% 🔺+75.1% 1.39 KB 2.85 KB 751 B 1.28 KB NODE_PROD
react-server.development.js -0.3% -0.7% 4.83 KB 4.82 KB 1.77 KB 1.76 KB NODE_DEV
react-server.production.min.js 0.0% 🔺+0.2% 1.2 KB 1.2 KB 664 B 665 B NODE_PROD

react-flight

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-flight.development.js +91.4% +60.7% 4.25 KB 8.13 KB 1.66 KB 2.67 KB NODE_DEV
react-flight.production.min.js 🔺+77.0% 🔺+71.3% 1.41 KB 2.49 KB 701 B 1.17 KB NODE_PROD

Generated by 🚫 dangerJS against 387c233

@sizebot
Copy link

sizebot commented Nov 6, 2019

Size changes (experimental)

ReactDOM: size: 0.0%, gzip: -0.0%

Details of bundled changes.

Comparing: 62ef250...387c233

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js 0.0% 0.0% 123.54 KB 123.54 KB 38.79 KB 38.79 KB NODE_PROFILING
react-dom-server.browser.development.js 0.0% 0.0% 140.37 KB 140.37 KB 36.87 KB 36.87 KB UMD_DEV
react-dom-unstable-flight-server.browser.development.js +109.8% +71.0% 4.45 KB 9.34 KB 1.79 KB 3.07 KB UMD_DEV
react-dom-server.browser.production.min.js 0.0% -0.0% 20.39 KB 20.39 KB 7.48 KB 7.48 KB UMD_PROD
react-dom-unstable-flight-server.browser.production.min.js 🔺+114.0% 🔺+77.5% 1.33 KB 2.85 KB 770 B 1.33 KB UMD_PROD
react-dom-test-utils.development.js 0.0% 0.0% 56.27 KB 56.27 KB 15.58 KB 15.58 KB UMD_DEV
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 3.88 KB 3.88 KB 1.55 KB 1.55 KB UMD_DEV
react-dom-unstable-flight-client.development.js +80.1% +62.2% 4.84 KB 8.72 KB 1.6 KB 2.6 KB UMD_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 11.18 KB 11.18 KB 4.15 KB 4.15 KB UMD_PROD
react-dom-unstable-flight-client.production.min.js 🔺+61.7% 🔺+57.4% 1.79 KB 2.89 KB 875 B 1.34 KB UMD_PROD
ReactDOMServer-dev.js 0.0% 0.0% 139.64 KB 139.64 KB 35.41 KB 35.41 KB FB_WWW_DEV
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 3.71 KB 3.71 KB 1.5 KB 1.5 KB NODE_DEV
react-dom-unstable-flight-client.development.js +83.1% +64.4% 4.67 KB 8.54 KB 1.55 KB 2.55 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% 0.0% 10.95 KB 10.95 KB 4.09 KB 4.09 KB NODE_PROD
react-dom-unstable-fizz.browser.production.min.js 0.0% 🔺+0.2% 1.05 KB 1.05 KB 642 B 643 B NODE_PROD
react-dom-unstable-flight-client.production.min.js 🔺+67.5% 🔺+64.1% 1.63 KB 2.72 KB 802 B 1.29 KB NODE_PROD
react-dom.development.js 0.0% 0.0% 951.45 KB 951.45 KB 215.02 KB 215.02 KB UMD_DEV
react-dom.production.min.js 0.0% 0.0% 119.57 KB 119.57 KB 38.35 KB 38.35 KB UMD_PROD
react-dom.profiling.min.js 0.0% 0.0% 123.25 KB 123.25 KB 39.45 KB 39.45 KB UMD_PROFILING
ReactDOMFizzServer-dev.js -0.2% -0.7% 3.92 KB 3.91 KB 1.5 KB 1.49 KB FB_WWW_DEV
react-dom.development.js 0.0% 0.0% 945.55 KB 945.55 KB 213.43 KB 213.43 KB NODE_DEV
react-dom-server.node.development.js 0.0% -0.0% 137.41 KB 137.41 KB 36.09 KB 36.09 KB NODE_DEV
react-dom-unstable-flight-server.node.development.js +112.6% +76.4% 4.51 KB 9.58 KB 1.79 KB 3.15 KB NODE_DEV
react-dom-unstable-flight-server.node.production.min.js 🔺+127.1% 🔺+79.5% 1.2 KB 2.72 KB 722 B 1.27 KB NODE_PROD
ReactFlightDOMClient-dev.js +81.9% +63.7% 4.64 KB 8.45 KB 1.54 KB 2.51 KB FB_WWW_DEV
react-dom-unstable-flight-server.browser.development.js +115.1% +73.5% 4.25 KB 9.13 KB 1.74 KB 3.02 KB NODE_DEV
ReactFlightDOMClient-prod.js 🔺+95.2% 🔺+77.3% 3.26 KB 6.36 KB 1.04 KB 1.84 KB FB_WWW_PROD
react-dom-server.browser.production.min.js 0.0% 0.0% 20.31 KB 20.31 KB 7.46 KB 7.46 KB NODE_PROD
react-dom-unstable-flight-server.browser.production.min.js 🔺+134.8% 🔺+88.2% 1.13 KB 2.65 KB 688 B 1.26 KB NODE_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.14 KB 60.14 KB 15.8 KB 15.8 KB UMD_DEV
ReactDOM-dev.js 0.0% 0.0% 973.77 KB 973.77 KB 215.92 KB 215.92 KB FB_WWW_DEV
ReactFlightDOMServer-dev.js +115.0% +79.3% 4.44 KB 9.55 KB 1.75 KB 3.13 KB FB_WWW_DEV
react-dom-unstable-fizz.node.development.js -0.2% -0.4% 3.97 KB 3.96 KB 1.53 KB 1.53 KB NODE_DEV
ReactFlightDOMServer-prod.js 🔺+147.7% 🔺+88.2% 2.32 KB 5.73 KB 940 B 1.73 KB FB_WWW_PROD
ReactDOM-profiling.js 0.0% 0.0% 402.33 KB 402.33 KB 73.42 KB 73.42 KB FB_WWW_PROFILING
react-dom-unstable-native-dependencies.production.min.js 0.0% 0.0% 10.48 KB 10.48 KB 3.58 KB 3.58 KB NODE_PROD
react-dom-unstable-fizz.node.production.min.js 0.0% 🔺+0.1% 1.12 KB 1.12 KB 676 B 677 B NODE_PROD

react-server

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-server-flight.development.js +96.6% +71.3% 5.25 KB 10.32 KB 1.93 KB 3.31 KB NODE_DEV
react-server-flight.production.min.js 🔺+104.7% 🔺+74.3% 1.4 KB 2.86 KB 759 B 1.29 KB NODE_PROD
react-server.development.js -0.3% -0.7% 4.85 KB 4.83 KB 1.78 KB 1.77 KB NODE_DEV
react-server.production.min.js 0.0% 🔺+0.1% 1.22 KB 1.22 KB 672 B 673 B NODE_PROD

react-flight

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-flight.development.js +91.1% +60.1% 4.26 KB 8.14 KB 1.67 KB 2.68 KB NODE_DEV
react-flight.production.min.js 🔺+76.3% 🔺+70.5% 1.42 KB 2.5 KB 709 B 1.18 KB NODE_PROD

Generated by 🚫 dangerJS against 387c233

Copy link
Collaborator

@gaearon gaearon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Want to add tests?

x.then(ping, ping);
return;
} else {
// This errored, we need to serialize this error to the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to the...?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thing

@sebmarkbage sebmarkbage merged commit dee0304 into facebook:master Nov 6, 2019
@gaearon
Copy link
Collaborator

gaearon commented Nov 6, 2019

If connection dies, how do I implement a Retry button?

@sebmarkbage
Copy link
Collaborator Author

Error boundary and do the request from the root again.

@gaearon
Copy link
Collaborator

gaearon commented Nov 6, 2019

Let me rephrase the tests question. Do you want me to write tests? 😄

@gaearon
Copy link
Collaborator

gaearon commented Nov 6, 2019

I can also just make an app..

@sebmarkbage
Copy link
Collaborator Author

If you want to write tests that would be great. Like the suspending and error cases.

@gaearon
Copy link
Collaborator

gaearon commented Nov 6, 2019

Cool, I'll do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants