{"action":"created","issue":{"url":"https://api.github.com/repos/facebook/react/issues/6420","repository_url":"https://api.github.com/repos/facebook/react","labels_url":"https://api.github.com/repos/facebook/react/issues/6420/labels{/name}","comments_url":"https://api.github.com/repos/facebook/react/issues/6420/comments","events_url":"https://api.github.com/repos/facebook/react/issues/6420/events","html_url":"https://github.com/facebook/react/issues/6420","id":146167538,"number":6420,"title":"Proposal: ReactDOMServer render to Stream","user":{"login":"aickin","id":44199,"avatar_url":"https://avatars.githubusercontent.com/u/44199?v=3","gravatar_id":"","url":"https://api.github.com/users/aickin","html_url":"https://github.com/aickin","followers_url":"https://api.github.com/users/aickin/followers","following_url":"https://api.github.com/users/aickin/following{/other_user}","gists_url":"https://api.github.com/users/aickin/gists{/gist_id}","starred_url":"https://api.github.com/users/aickin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aickin/subscriptions","organizations_url":"https://api.github.com/users/aickin/orgs","repos_url":"https://api.github.com/users/aickin/repos","events_url":"https://api.github.com/users/aickin/events{/privacy}","received_events_url":"https://api.github.com/users/aickin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":21,"created_at":"2016-04-06T02:25:29Z","updated_at":"2016-11-14T12:24:15Z","closed_at":null,"body":"tl;dr: I'd like to know how much enthusiasm there is on the core React team for accepting a PR with the ability to render markup to a stream. I don't need a guarantee, of course, but I'd like to get an sense if it's something the React team might do before spending a ton of time working on it.\n### Background\n\nCurrently, server rendering is accomplished by `ReactDOMServer.renderToString` or `ReactDOMServer.renderToStaticMarkup`, which are synchronous functions that return a string. \n\nThe server render methods can be somewhat slow. Large (~500K) web pages can easily take over 100 or 200ms to render, depending on the server. Also, since node is single threaded and single-core performance has not been improving rapidly, this is not just a problem that Moore's Law will eventually solve. The slowness in turn causes two problems in production websites with large (or somewhat large) HTML pages:\n1. First, because the methods return a string, they completely render the entire component before you can return even the first byte to the browser, meaning that the browser is waiting idle while the render method is called.\n2. Second, because the methods are synchronous and node is single threaded, the server is unresponsive during rendering, which means that a large page render can easily starve out renders of smaller pages (which may only take a few ms). An asynchronous render method would let large page renders yield CPU to small pages, improving average response time.\n### Proposed Solution\n\nThe proposal is to add two methods to ReactDOMServer, both of which return a node Readable Stream.\n\n``` javascript\nStream renderToStream(ReactElement element)\nStream renderToStaticMarkupStream(ReactElement element)\n```\n\nIn terms of behavior, these methods would return a Readable Stream that outputs the same markup as `renderToString` and `renderToStaticMarkup`, respectively.\n\nThese methods could solve both problems above. A stream can begin emitting content immediately to send to the browser, keeping TTFB constant as components get larger. Streams are also inherently asynchronous, which allows large pages to not starve out smaller ones.\n\nA few months back I forked react into a library called [react-dom-stream](https://github.com/aickin/react-dom-stream) to do this exact thing, and it's been fairly well received (1,100+ stars on GitHub, though modest actual downloads on npm). There's also [a wishlist bug thread](https://github.com/facebook/react/issues/3009) on this repo about it. However, maintaining a fork is a less than desirable position, and I wonder if I can get it integrated in to the core code base.\n\nMy implementation in `react-dom-stream` is not ideal; I ended up copying basically every implementation of `mountComponent` and making the copied versions asynchronous. The benefit of this approach was that it didn't affect `renderToString` performance, but the obvious drawback was that any code changes or bug fixes would have to be performed in both forks of the code, which is not ideal.\n\nRecently, I figured out a way to share code in a better way between `renderToString` and `renderToStream`, but the result was that `renderToString` slowed down relatively significantly (+30%, plus or minus). I'm trying to figure out how if I can tune it more carefully, but it's not looking great yet.\n### Questions\n\nSo I think the questions I'd like to ask to the team are:\n1. Assuming it were perfectly implemented with no performance degradation of the current code, is this even something you are willing to accept a PR for this feature?\n2. If you were to accept this, how important to you is it that the string and stream versions of the code follow the same code path?\n3. Are you willing to accept any degradation in performance of the string version of server rendering in order to get stream rendering that has constant TTFB and keep a single code path?\n\nThanks for your time, and thanks for all the great work you do on react!\n\n(Tagging @spicyj, @gaearon, and @sebmarkbage, as I was instructed to do on the react IRC channel.)\n"},"comment":{"url":"https://api.github.com/repos/facebook/react/issues/comments/260322106","html_url":"https://github.com/facebook/react/issues/6420#issuecomment-260322106","issue_url":"https://api.github.com/repos/facebook/react/issues/6420","id":260322106,"user":{"login":"gaearon","id":810438,"avatar_url":"https://avatars.githubusercontent.com/u/810438?v=3","gravatar_id":"","url":"https://api.github.com/users/gaearon","html_url":"https://github.com/gaearon","followers_url":"https://api.github.com/users/gaearon/followers","following_url":"https://api.github.com/users/gaearon/following{/other_user}","gists_url":"https://api.github.com/users/gaearon/gists{/gist_id}","starred_url":"https://api.github.com/users/gaearon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gaearon/subscriptions","organizations_url":"https://api.github.com/users/gaearon/orgs","repos_url":"https://api.github.com/users/gaearon/repos","events_url":"https://api.github.com/users/gaearon/events{/privacy}","received_events_url":"https://api.github.com/users/gaearon/received_events","type":"User","site_admin":false},"created_at":"2016-11-14T12:24:15Z","updated_at":"2016-11-14T12:24:15Z","body":"We are currently working on Fiber which is a [complete reimplementation of React core](https://www.youtube.com/watch?v=aV1271hd9ew).\r\nThis means it doesn't seem to make sense to spend effort in trying to shoehorn streaming into the existing reconciler, as it will be replaced.\r\n\r\nFiber should make it easier to create a separate streaming server renderer that would be focused on performance. This won't be our initial focus but as Fiber becomes more stable I'm sure there will be a lot more space for such community contributions."}}
{"actor":{"display_login":"gaearon"}}