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

[Fizz] New Server Rendering Infra #14144

Merged
merged 12 commits into from
Nov 30, 2018
Merged

Conversation

sebmarkbage
Copy link
Collaborator

@sebmarkbage sebmarkbage commented Nov 8, 2018

This adds a bunch of new stuff related to the build process for the new server renderer (Fizz).

It adds a new package react-stream. The name is temporary (but is nicely owned by @aickin).

This is equivalent to react-reconciler but for server rendering. I considered putting them in the same package but they really shouldn't share anything and splitting them up into folders just make both seem more complicated.

This is used to create a two new entry points.

react-dom/unstable-fizz which is a server renderer for DOM. Can run in Node for Node streams or browsers for WHATWG streams.

There is also a react-noop-rendering/server for tests.

The interesting new twist here is that there is not just a HostConfig (Node.js, Service Worker, other). There's also a FormatConfig (DOM, RN, possibly variations of DOM).

Currently I just copy pasted all the FiberHostConfig overrides to also account for FizzHostConfig and FizzFormatConfig.

The inlinedHostConfigs.js model starts breaking down though. Currently the dom configuration tests the DOM format config + Node host config. However, that means we wouldn't get coverage on DOM format config + Service Worker host config. Maybe that's fine as long as the Service Worker host config is covered by one of the other configurations?

@sizebot
Copy link

sizebot commented Nov 8, 2018

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

Details of bundled changes.

Comparing: f1bf281...b1182d1

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.production.min.js 0.0% -0.0% 97.8 KB 97.8 KB 31.84 KB 31.84 KB UMD_PROD
react-dom.profiling.min.js 0.0% -0.0% 100.69 KB 100.69 KB 32.52 KB 32.52 KB UMD_PROFILING
react-dom.production.min.js 0.0% 0.0% 97.79 KB 97.79 KB 31.38 KB 31.38 KB NODE_PROD
ReactDOM-prod.js 0.0% -0.0% 308.18 KB 308.18 KB 56.78 KB 56.78 KB FB_WWW_PROD
ReactDOM-profiling.js 0.0% -0.0% 314.96 KB 314.96 KB 58.17 KB 58.17 KB FB_WWW_PROFILING
react-dom-unstable-fire.production.min.js 0.0% -0.0% 97.81 KB 97.81 KB 31.85 KB 31.85 KB UMD_PROD
react-dom-unstable-fire.profiling.min.js 0.0% -0.0% 100.7 KB 100.7 KB 32.53 KB 32.53 KB UMD_PROFILING
react-dom-unstable-fire.profiling.min.js 0.0% 0.0% 100.8 KB 100.8 KB 31.98 KB 31.98 KB NODE_PROFILING
ReactFire-prod.js 0.0% -0.0% 296.77 KB 296.77 KB 54.35 KB 54.35 KB FB_WWW_PROD
ReactFire-profiling.js 0.0% -0.0% 303.48 KB 303.48 KB 55.8 KB 55.8 KB FB_WWW_PROFILING
react-dom-test-utils.development.js 0.0% -0.0% 44.87 KB 44.87 KB 12.3 KB 12.3 KB UMD_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% -0.0% 11.01 KB 11.01 KB 3.81 KB 3.81 KB UMD_PROD
react-dom-unstable-native-dependencies.development.js 0.0% 0.0% 60.29 KB 60.29 KB 15.79 KB 15.79 KB NODE_DEV
react-dom-unstable-native-dependencies.production.min.js 0.0% -0.0% 10.75 KB 10.75 KB 3.71 KB 3.7 KB NODE_PROD
react-dom-server.browser.development.js 0.0% -0.0% 123.82 KB 123.82 KB 33.07 KB 33.07 KB UMD_DEV
ReactDOMServer-dev.js 0.0% -0.0% 121.18 KB 121.18 KB 31.79 KB 31.79 KB FB_WWW_DEV
react-dom-unstable-fizz.browser.development.js n/a n/a 0 B 3.63 KB 0 B 1.44 KB UMD_DEV
react-dom-unstable-fizz.browser.production.min.js n/a n/a 0 B 1.21 KB 0 B 706 B UMD_PROD
react-dom-unstable-fizz.browser.development.js n/a n/a 0 B 3.45 KB 0 B 1.39 KB NODE_DEV
react-dom-unstable-fizz.browser.production.min.js n/a n/a 0 B 1.05 KB 0 B 637 B NODE_PROD
react-dom-unstable-fizz.node.development.js n/a n/a 0 B 3.7 KB 0 B 1.42 KB NODE_DEV
react-dom-unstable-fizz.node.production.min.js n/a n/a 0 B 1.1 KB 0 B 667 B NODE_PROD
ReactDOMFizzServer-dev.js n/a n/a 0 B 3.68 KB 0 B 1.4 KB FB_WWW_DEV
ReactDOMFizzServer-prod.js n/a n/a 0 B 2.16 KB 0 B 874 B FB_WWW_PROD

react-noop-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-noop-renderer.development.js 0.0% -0.0% 28.16 KB 28.16 KB 6.15 KB 6.15 KB NODE_DEV
react-noop-renderer-server.development.js n/a n/a 0 B 1.83 KB 0 B 877 B NODE_DEV
react-noop-renderer-server.production.min.js n/a n/a 0 B 813 B 0 B 491 B NODE_PROD

react-stream

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-stream.development.js n/a n/a 0 B 4.53 KB 0 B 1.65 KB NODE_DEV
react-stream.production.min.js n/a n/a 0 B 1.2 KB 0 B 664 B NODE_PROD

Generated by 🚫 dangerJS

@@ -0,0 +1,81 @@
/**
Copy link
Collaborator Author

@sebmarkbage sebmarkbage Nov 8, 2018

Choose a reason for hiding this comment

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

@gaearon I named this ReactFizzRenderer but I don't think it makes sense since we use the term "renderer" to refer to the compiled output or the HostConfig. But Reconciler doesn't make sense since that's exactly what it doesn't do. It does everything but reconcile. Ideas?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Umm.. Writer? Streamer? You know like cool kids on YouTube.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Or just Server.

const ReactFizzRenderer = require('./src/ReactFizzRenderer');

// TODO: decide on the top-level export form.
// This is hacky but makes it work with both Rollup and Jest.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are we still doing this? I think we switched to

export * from './src/ReactFizzRenderer';

@gaearon

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, the other entries do that. Maybe I'm confused.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we do that for packages that are ready to be ESM. But here the actual output will be a function anyway so it doesn’t matter. I guess could work either way.

Copy link
Collaborator

Choose a reason for hiding this comment

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

My understanding based on absolutely nothing was that old packages do this because to switch to ESM would be a breaking change. But new packages don't have that restriction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'd love to fix this though. This is probably really bad for inlining/DCE.

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.

Seems legit

@@ -0,0 +1,12 @@
/**
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let’s add unstable to the entry point

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

To the file name or the method names?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I’d add to the file

@@ -29,6 +29,7 @@
"server.js",
"server.browser.js",
"server.node.js",
"fizz.js",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also fizz.node.js?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

hm. Why doesn't this break ReactDOMFizzServer-test.js in build tests? I'll need to look into that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Because npm entry point (see npm folder) directly points the bundle. The entry point above (which you redirect) only used by Jest. So technically this change isn’t even necessary right now. But would be less confusing.

Copy link
Collaborator

@gaearon gaearon Nov 8, 2018

Choose a reason for hiding this comment

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

For consistency you can make npm/fizz also do a re export of ./fizz.node. Like npm/server does.

@@ -0,0 +1,35 @@
{
"name": "react-stream",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Set private to true to not block the sync?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

You mean the release? We still want it in the sync so we can try it out at FB.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yes I mean the release

@@ -0,0 +1,81 @@
/**
Copy link
Collaborator

Choose a reason for hiding this comment

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

Or just Server.

@@ -0,0 +1,44 @@
/**
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@gaearon I put this in react-stream/src/ which is a bit weird because it's not part of the core algorithm. It's part of a possible host config. I'm not sure this makes sense to put it here but it's not really shared and we really shouldn't make shared a dumping ground.

However, I guess in the future we could have react-stream export preconfigured environments and all you fill in is the format config. E.g. react-stream/index.node.js, react-stream/index.browser.js.

So maybe that makes sense.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sure. We also never got these things quite right from first try so I wouldn’t expect to do it now.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe you can add a comment about this? I was just puzzled over this because I forgot.

@sebmarkbage sebmarkbage changed the title [WIP][Fizz] New Server Rendering Infra [Fizz] New Server Rendering Infra Nov 8, 2018
@sebmarkbage
Copy link
Collaborator Author

I also added a browser build. e65b22f

@Ephem
Copy link
Contributor

Ephem commented Nov 9, 2018

I'm moderately familiar with the current server renderer and after having gone through this I just have to add that I really like this approach for a new renderer! Makes so much sense to me.

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.
We need to separate the format (DOM, React Native, etc) from the host
running the server (Node, Browser, etc).
The Node DOM API is pipeToNodeStream which accepts a writable stream.
Simpler API this way but also avoids having to fork the wrapper config.

Fixes noop builds.
Also use forwarding to it from fizz.js in builds so that tests covers
this.
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.
This is for testing server rendering - on the client.
@sebmarkbage
Copy link
Collaborator Author

Since we landed the Fire infra we can land this too.

@sebmarkbage sebmarkbage merged commit 1d25aa5 into facebook:master Nov 30, 2018
jetoneza pushed a commit to jetoneza/react that referenced this pull request Jan 23, 2019
* [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
n8schloss pushed a commit to n8schloss/react that referenced this pull request Jan 31, 2019
* [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
let chunk = chunks[i];
writeChunk(destination, chunk);
}
} finally {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why doesn't it keep the chunks that failed to be written (due to an exception) in completedChunks to be retried later?

} finally {
completeWriting(destination);
}
close(destination);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is close(destination) not called in case of an exception?

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.

7 participants