forked from facebook/react
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Fizz] New Server Rendering Infra (facebook#14144)
* [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
- Loading branch information
1 parent
d3559d3
commit 5f38fa8
Showing
48 changed files
with
1,214 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<!DOCTYPE html> | ||
<html style="width: 100%; height: 100%; overflow: hidden"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Fizz Example</title> | ||
</head> | ||
<body> | ||
<h1>Fizz Example</h1> | ||
<div id="container"> | ||
<p> | ||
To install React, follow the instructions on | ||
<a href="https://github.com/facebook/react/">GitHub</a>. | ||
</p> | ||
<p> | ||
If you can see this, React is <strong>not</strong> working right. | ||
If you checked out the source from GitHub make sure to run <code>npm run build</code>. | ||
</p> | ||
</div> | ||
<script src="../../build/dist/react.development.js"></script> | ||
<script src="../../build/dist/react-dom-unstable-fizz.browser.development.js"></script> | ||
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script> | ||
<script type="text/babel"> | ||
let stream = ReactDOMFizzServer.renderToReadableStream(<body>Success</body>); | ||
let response = new Response(stream, { | ||
headers: {'Content-Type': 'text/html'}, | ||
}); | ||
display(response); | ||
|
||
async function display(responseToDisplay) { | ||
let blob = await responseToDisplay.blob(); | ||
let url = URL.createObjectURL(blob); | ||
let iframe = document.createElement('iframe'); | ||
iframe.src = url; | ||
let container = document.getElementById('container'); | ||
container.innerHTML = ''; | ||
container.appendChild(iframe); | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
'use strict'; | ||
|
||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./cjs/react-dom-unstable-fizz.browser.production.min.js'); | ||
} else { | ||
module.exports = require('./cjs/react-dom-unstable-fizz.browser.development.js'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
'use strict'; | ||
|
||
module.exports = require('./unstable-fizz.node'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
'use strict'; | ||
|
||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./cjs/react-dom-unstable-fizz.node.production.min.js'); | ||
} else { | ||
module.exports = require('./cjs/react-dom-unstable-fizz.node.development.js'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
45 changes: 45 additions & 0 deletions
45
packages/react-dom/src/__tests__/ReactDOMFizzServerBrowser-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @emails react-core | ||
*/ | ||
|
||
'use strict'; | ||
|
||
// Polyfills for test environment | ||
global.ReadableStream = require('@mattiasbuelens/web-streams-polyfill/ponyfill/es6').ReadableStream; | ||
global.TextEncoder = require('util').TextEncoder; | ||
|
||
let React; | ||
let ReactDOMFizzServer; | ||
|
||
describe('ReactDOMFizzServer', () => { | ||
beforeEach(() => { | ||
jest.resetModules(); | ||
React = require('react'); | ||
ReactDOMFizzServer = require('react-dom/unstable-fizz.browser'); | ||
}); | ||
|
||
async function readResult(stream) { | ||
let reader = stream.getReader(); | ||
let result = ''; | ||
while (true) { | ||
let {done, value} = await reader.read(); | ||
if (done) { | ||
return result; | ||
} | ||
result += Buffer.from(value).toString('utf8'); | ||
} | ||
} | ||
|
||
it('should call renderToReadableStream', async () => { | ||
let stream = ReactDOMFizzServer.renderToReadableStream( | ||
<div>hello world</div>, | ||
); | ||
let result = await readResult(stream); | ||
expect(result).toBe('<div>hello world</div>'); | ||
}); | ||
}); |
39 changes: 39 additions & 0 deletions
39
packages/react-dom/src/__tests__/ReactDOMFizzServerNode-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @emails react-core | ||
* @jest-environment node | ||
*/ | ||
|
||
'use strict'; | ||
|
||
let Stream; | ||
let React; | ||
let ReactDOMFizzServer; | ||
|
||
describe('ReactDOMFizzServer', () => { | ||
beforeEach(() => { | ||
jest.resetModules(); | ||
React = require('react'); | ||
ReactDOMFizzServer = require('react-dom/unstable-fizz'); | ||
Stream = require('stream'); | ||
}); | ||
|
||
function getTestWritable() { | ||
let writable = new Stream.PassThrough(); | ||
writable.setEncoding('utf8'); | ||
writable.result = ''; | ||
writable.on('data', chunk => (writable.result += chunk)); | ||
return writable; | ||
} | ||
|
||
it('should call pipeToNodeWritable', () => { | ||
let writable = getTestWritable(); | ||
ReactDOMFizzServer.pipeToNodeWritable(<div>hello world</div>, writable); | ||
jest.runAllTimers(); | ||
expect(writable.result).toBe('<div>hello world</div>'); | ||
}); | ||
}); |
34 changes: 34 additions & 0 deletions
34
packages/react-dom/src/server/ReactDOMFizzServerBrowser.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import type {ReactNodeList} from 'shared/ReactTypes'; | ||
|
||
import { | ||
createRequest, | ||
startWork, | ||
startFlowing, | ||
} from 'react-stream/inline.dom-browser'; | ||
|
||
function renderToReadableStream(children: ReactNodeList): ReadableStream { | ||
let request; | ||
return new ReadableStream({ | ||
start(controller) { | ||
request = createRequest(children, controller); | ||
startWork(request); | ||
}, | ||
pull(controller) { | ||
startFlowing(request, controller.desiredSize); | ||
}, | ||
cancel(reason) {}, | ||
}); | ||
} | ||
|
||
export default { | ||
renderToReadableStream, | ||
}; |
19 changes: 19 additions & 0 deletions
19
packages/react-dom/src/server/ReactDOMFizzServerFormatConfig.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import {convertStringToBuffer} from 'react-stream/src/ReactFizzHostConfig'; | ||
|
||
export function formatChunk(type: string, props: Object): Uint8Array { | ||
let str = '<' + type + '>'; | ||
if (typeof props.children === 'string') { | ||
str += props.children; | ||
} | ||
str += '</' + type + '>'; | ||
return convertStringToBuffer(str); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
import type {ReactNodeList} from 'shared/ReactTypes'; | ||
import type {Writable} from 'stream'; | ||
|
||
import {createRequest, startWork, startFlowing} from 'react-stream/inline.dom'; | ||
|
||
function createDrainHandler(destination, request) { | ||
return () => startFlowing(request, 0); | ||
} | ||
|
||
function pipeToNodeWritable( | ||
children: ReactNodeList, | ||
destination: Writable, | ||
): void { | ||
let request = createRequest(children, destination); | ||
destination.on('drain', createDrainHandler(destination, request)); | ||
startWork(request); | ||
} | ||
|
||
export default { | ||
pipeToNodeWritable, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const ReactDOMFizzServerBrowser = require('./src/server/ReactDOMFizzServerBrowser'); | ||
|
||
// TODO: decide on the top-level export form. | ||
// This is hacky but makes it work with both Rollup and Jest | ||
module.exports = ReactDOMFizzServerBrowser.default || ReactDOMFizzServerBrowser; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
module.exports = require('./unstable-fizz.node'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const ReactDOMFizzServerNode = require('./src/server/ReactDOMFizzServerNode'); | ||
|
||
// TODO: decide on the top-level export form. | ||
// This is hacky but makes it work with both Rollup and Jest | ||
module.exports = ReactDOMFizzServerNode.default || ReactDOMFizzServerNode; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
'use strict'; | ||
|
||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./cjs/react-noop-renderer-server.production.min.js'); | ||
} else { | ||
module.exports = require('./cjs/react-noop-renderer-server.development.js'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
*/ | ||
|
||
'use strict'; | ||
|
||
const ReactNoopServer = require('./src/ReactNoopServer'); | ||
|
||
// TODO: decide on the top-level export form. | ||
// This is hacky but makes it work with both Rollup and Jest. | ||
module.exports = ReactNoopServer.default || ReactNoopServer; |
Oops, something went wrong.