[Fizz] New Server Rendering Infra (#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
This commit is contained in:
parent
f1bf281605
commit
1d25aa5787
|
@ -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>
|
|
@ -84,7 +84,8 @@
|
|||
"targz": "^1.0.1",
|
||||
"through2": "^2.0.0",
|
||||
"tmp": "~0.0.28",
|
||||
"typescript": "~1.8.10"
|
||||
"typescript": "~1.8.10",
|
||||
"@mattiasbuelens/web-streams-polyfill": "0.1.0"
|
||||
},
|
||||
"devEngines": {
|
||||
"node": "8.x || 9.x || 10.x"
|
||||
|
|
|
@ -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');
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = require('./unstable-fizz.node');
|
|
@ -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');
|
||||
}
|
|
@ -32,12 +32,16 @@
|
|||
"server.node.js",
|
||||
"test-utils.js",
|
||||
"unstable-fire.js",
|
||||
"unstable-fizz.js",
|
||||
"unstable-fizz.browser.js",
|
||||
"unstable-fizz.node.js",
|
||||
"unstable-native-dependencies.js",
|
||||
"cjs/",
|
||||
"umd/"
|
||||
],
|
||||
"browser": {
|
||||
"./server.js": "./server.browser.js"
|
||||
"./server.js": "./server.browser.js",
|
||||
"./unstable-fizz.js": "./unstable-fizz.browser.js"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
|
|
|
@ -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>');
|
||||
});
|
||||
});
|
|
@ -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>');
|
||||
});
|
||||
});
|
|
@ -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,
|
||||
};
|
|
@ -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);
|
||||
}
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
|
@ -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');
|
|
@ -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;
|
|
@ -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');
|
||||
}
|
|
@ -10,7 +10,8 @@
|
|||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2",
|
||||
"regenerator-runtime": "^0.11.0",
|
||||
"react-reconciler": "*"
|
||||
"react-reconciler": "*",
|
||||
"react-stream": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0"
|
||||
|
@ -21,6 +22,7 @@
|
|||
"build-info.json",
|
||||
"index.js",
|
||||
"persistent.js",
|
||||
"server.js",
|
||||
"cjs/"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -0,0 +1,49 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a renderer of React that doesn't have a render target output.
|
||||
* It is useful to demonstrate the internals of the reconciler in isolation
|
||||
* and for testing semantics of reconciliation separate from the host
|
||||
* environment.
|
||||
*/
|
||||
|
||||
import ReactFizzStreamer from 'react-stream';
|
||||
|
||||
type Destination = Array<string>;
|
||||
|
||||
const ReactNoopServer = ReactFizzStreamer({
|
||||
scheduleWork(callback: () => void) {
|
||||
callback();
|
||||
},
|
||||
beginWriting(destination: Destination): void {},
|
||||
writeChunk(destination: Destination, buffer: Uint8Array): void {
|
||||
destination.push(JSON.parse(Buffer.from((buffer: any)).toString('utf8')));
|
||||
},
|
||||
completeWriting(destination: Destination): void {},
|
||||
close(destination: Destination): void {},
|
||||
flushBuffered(destination: Destination): void {},
|
||||
convertStringToBuffer(content: string): Uint8Array {
|
||||
return Buffer.from(content, 'utf8');
|
||||
},
|
||||
formatChunk(type: string, props: Object): Uint8Array {
|
||||
return Buffer.from(JSON.stringify({type, props}), 'utf8');
|
||||
},
|
||||
});
|
||||
|
||||
function render(children: React$Element<any>): Destination {
|
||||
let destination: Destination = [];
|
||||
let request = ReactNoopServer.createRequest(children, destination);
|
||||
ReactNoopServer.startWork(request);
|
||||
return destination;
|
||||
}
|
||||
|
||||
export default {
|
||||
render,
|
||||
};
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file intentionally does *not* have the Flow annotation.
|
||||
// Don't add it. See `./inline-typed.js` for an explanation.
|
||||
|
||||
export * from './src/ReactFiberReconciler';
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export * from 'react-dom/src/client/ReactDOMHostConfig';
|
|
@ -0,0 +1,25 @@
|
|||
# react-stream
|
||||
|
||||
This is an experimental package for creating custom React streaming server renderers.
|
||||
|
||||
**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.**
|
||||
|
||||
**Use it at your own risk.**
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var Renderer = require('react-stream');
|
||||
|
||||
var HostConfig = {
|
||||
// You'll need to implement some methods here.
|
||||
// See below for more information and examples.
|
||||
};
|
||||
|
||||
var MyRenderer = Renderer(HostConfig);
|
||||
|
||||
var RendererPublicAPI = {
|
||||
};
|
||||
|
||||
module.exports = RendererPublicAPI;
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This entry point is intentionally not typed. It exists only for third-party
|
||||
// renderers. The renderers we ship (such as React DOM) instead import a named
|
||||
// "inline" entry point (for example, `react-stream/inline.dom`). It uses
|
||||
// the same code, but the Flow configuration redirects the host config to its
|
||||
// real implementation so we can check it against exact intended host types.
|
||||
//
|
||||
// Only one renderer (the one you passed to `yarn flow <renderer>`) is fully
|
||||
// type-checked at any given time. The Flow config maps the
|
||||
// `react-stream/inline.<renderer>` import (which is *not* Flow typed) to
|
||||
// `react-stream/inline-typed` (which *is*) for the current renderer.
|
||||
// On CI, we run Flow checks for each renderer separately.
|
||||
|
||||
'use strict';
|
||||
|
||||
const ReactFizzStreamer = require('./src/ReactFizzStreamer');
|
||||
|
||||
// TODO: decide on the top-level export form.
|
||||
// This is hacky but makes it work with both Rollup and Jest.
|
||||
module.exports = ReactFizzStreamer.default || ReactFizzStreamer;
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This file must have the Flow annotation.
|
||||
//
|
||||
// This is the Flow-typed entry point for the renderer. It should not be
|
||||
// imported directly in code. Instead, our Flow configuration uses this entry
|
||||
// point for the currently checked renderer (the one you passed to `yarn flow`).
|
||||
//
|
||||
// For example, if you run `yarn flow dom`, `react-stream/inline.dom` points
|
||||
// to this module (and thus will be considered Flow-typed). But other renderers
|
||||
// (e.g. `react-test-renderer`) will see stream as untyped during the check.
|
||||
//
|
||||
// We can't make all entry points typed at the same time because different
|
||||
// renderers have different host config types. So we check them one by one.
|
||||
// We run Flow on all renderers on CI.
|
||||
|
||||
export * from './src/ReactFizzStreamer';
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file intentionally does *not* have the Flow annotation.
|
||||
// Don't add it. See `./inline-typed.js` for an explanation.
|
||||
|
||||
export * from './src/ReactFizzStreamer';
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// This file intentionally does *not* have the Flow annotation.
|
||||
// Don't add it. See `./inline-typed.js` for an explanation.
|
||||
|
||||
export * from './src/ReactFizzStreamer';
|
|
@ -0,0 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports = require('./cjs/react-stream.production.min.js');
|
||||
} else {
|
||||
module.exports = require('./cjs/react-stream.development.js');
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "react-stream",
|
||||
"description": "React package for creating custom streaming server renderers.",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"keywords": [
|
||||
"react"
|
||||
],
|
||||
"homepage": "https://reactjs.org/",
|
||||
"bugs": "https://github.com/facebook/react/issues",
|
||||
"license": "MIT",
|
||||
"files": [
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"index.js",
|
||||
"cjs/"
|
||||
],
|
||||
"main": "index.js",
|
||||
"repository": "facebook/react",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"object-assign": "^4.1.1",
|
||||
"prop-types": "^15.6.2"
|
||||
},
|
||||
"browserify": {
|
||||
"transform": [
|
||||
"loose-envify"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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 invariant from 'shared/invariant';
|
||||
|
||||
// We expect that our Rollup, Jest, and Flow configurations
|
||||
// always shim this module with the corresponding host config
|
||||
// (either provided by a renderer, or a generic shim for npm).
|
||||
//
|
||||
// We should never resolve to this file, but it exists to make
|
||||
// sure that if we *do* accidentally break the configuration,
|
||||
// the failure isn't silent.
|
||||
|
||||
invariant(false, 'This module must be shimmed by a specific renderer.');
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* 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 invariant from 'shared/invariant';
|
||||
|
||||
// We expect that our Rollup, Jest, and Flow configurations
|
||||
// always shim this module with the corresponding host config
|
||||
// (either provided by a renderer, or a generic shim for npm).
|
||||
//
|
||||
// We should never resolve to this file, but it exists to make
|
||||
// sure that if we *do* accidentally break the configuration,
|
||||
// the failure isn't silent.
|
||||
|
||||
invariant(false, 'This module must be shimmed by a specific renderer.');
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export type Destination = ReadableStreamController;
|
||||
|
||||
export function scheduleWork(callback: () => void) {
|
||||
callback();
|
||||
}
|
||||
|
||||
export function flushBuffered(destination: Destination) {
|
||||
// WHATWG Streams do not yet have a way to flush the underlying
|
||||
// transform streams. https://github.com/whatwg/streams/issues/960
|
||||
}
|
||||
|
||||
export function beginWriting(destination: Destination) {}
|
||||
|
||||
export function writeChunk(destination: Destination, buffer: Uint8Array) {
|
||||
destination.enqueue(buffer);
|
||||
}
|
||||
|
||||
export function completeWriting(destination: Destination) {}
|
||||
|
||||
export function close(destination: Destination) {
|
||||
destination.close();
|
||||
}
|
||||
|
||||
const textEncoder = new TextEncoder();
|
||||
|
||||
export function convertStringToBuffer(content: string): Uint8Array {
|
||||
return textEncoder.encode(content);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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 {Writable} from 'stream';
|
||||
|
||||
type MightBeFlushable = {flush?: () => void};
|
||||
|
||||
export type Destination = Writable & MightBeFlushable;
|
||||
|
||||
export function scheduleWork(callback: () => void) {
|
||||
setImmediate(callback);
|
||||
}
|
||||
|
||||
export function flushBuffered(destination: Destination) {
|
||||
// If we don't have any more data to send right now.
|
||||
// Flush whatever is in the buffer to the wire.
|
||||
if (typeof destination.flush === 'function') {
|
||||
// By convention the Zlib streams provide a flush function for this purpose.
|
||||
destination.flush();
|
||||
}
|
||||
}
|
||||
|
||||
export function beginWriting(destination: Destination) {
|
||||
destination.cork();
|
||||
}
|
||||
|
||||
export function writeChunk(destination: Destination, buffer: Uint8Array) {
|
||||
let nodeBuffer = ((buffer: any): Buffer); // close enough
|
||||
destination.write(nodeBuffer);
|
||||
}
|
||||
|
||||
export function completeWriting(destination: Destination) {
|
||||
destination.uncork();
|
||||
}
|
||||
|
||||
export function close(destination: Destination) {
|
||||
destination.end();
|
||||
}
|
||||
|
||||
export function convertStringToBuffer(content: string): Uint8Array {
|
||||
return Buffer.from(content, 'utf8');
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/**
|
||||
* 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 {Destination} from './ReactFizzHostConfig';
|
||||
import type {ReactNodeList} from 'shared/ReactTypes';
|
||||
|
||||
import {
|
||||
scheduleWork,
|
||||
beginWriting,
|
||||
writeChunk,
|
||||
completeWriting,
|
||||
flushBuffered,
|
||||
close,
|
||||
} from './ReactFizzHostConfig';
|
||||
import {formatChunk} from './ReactFizzFormatConfig';
|
||||
import {REACT_ELEMENT_TYPE} from 'shared/ReactSymbols';
|
||||
|
||||
type OpaqueRequest = {
|
||||
destination: Destination,
|
||||
children: ReactNodeList,
|
||||
completedChunks: Array<Uint8Array>,
|
||||
flowing: boolean,
|
||||
};
|
||||
|
||||
export function createRequest(
|
||||
children: ReactNodeList,
|
||||
destination: Destination,
|
||||
): OpaqueRequest {
|
||||
return {destination, children, completedChunks: [], flowing: false};
|
||||
}
|
||||
|
||||
function performWork(request: OpaqueRequest): void {
|
||||
let element = (request.children: any);
|
||||
request.children = null;
|
||||
if (element && element.$$typeof !== REACT_ELEMENT_TYPE) {
|
||||
return;
|
||||
}
|
||||
let type = element.type;
|
||||
let props = element.props;
|
||||
if (typeof type !== 'string') {
|
||||
return;
|
||||
}
|
||||
request.completedChunks.push(formatChunk(type, props));
|
||||
if (request.flowing) {
|
||||
flushCompletedChunks(request);
|
||||
}
|
||||
|
||||
flushBuffered(request.destination);
|
||||
}
|
||||
|
||||
function flushCompletedChunks(request: OpaqueRequest) {
|
||||
let destination = request.destination;
|
||||
let chunks = request.completedChunks;
|
||||
request.completedChunks = [];
|
||||
|
||||
beginWriting(destination);
|
||||
try {
|
||||
for (let i = 0; i < chunks.length; i++) {
|
||||
let chunk = chunks[i];
|
||||
writeChunk(destination, chunk);
|
||||
}
|
||||
} finally {
|
||||
completeWriting(destination);
|
||||
}
|
||||
close(destination);
|
||||
}
|
||||
|
||||
export function startWork(request: OpaqueRequest): void {
|
||||
request.flowing = true;
|
||||
scheduleWork(() => performWork(request));
|
||||
}
|
||||
|
||||
export function startFlowing(
|
||||
request: OpaqueRequest,
|
||||
desiredBytes: number,
|
||||
): void {
|
||||
request.flowing = false;
|
||||
flushCompletedChunks(request);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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 React;
|
||||
let ReactNoopServer;
|
||||
|
||||
describe('ReactServer', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
|
||||
React = require('react');
|
||||
ReactNoopServer = require('react-noop-renderer/server');
|
||||
});
|
||||
|
||||
it('can call render', () => {
|
||||
let result = ReactNoopServer.render(<div>hello world</div>);
|
||||
expect(result).toEqual([{type: 'div', props: {children: 'hello world'}}]);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This is a host config that's used for the `react-stream` package on npm.
|
||||
// It is only used by third-party renderers.
|
||||
//
|
||||
// Its API lets you pass the host config as an argument.
|
||||
// However, inside the `react-stream` we treat host config as a module.
|
||||
// This file is a shim between two worlds.
|
||||
//
|
||||
// It works because the `react-stream` bundle is wrapped in something like:
|
||||
//
|
||||
// module.exports = function ($$$config) {
|
||||
// /* renderer code */
|
||||
// }
|
||||
//
|
||||
// So `$$$config` looks like a global variable, but it's
|
||||
// really an argument to a top-level wrapping function.
|
||||
|
||||
declare var $$$hostConfig: any;
|
||||
export opaque type Destination = mixed; // eslint-disable-line no-undef
|
||||
|
||||
export const formatChunk = $$$hostConfig.formatChunk;
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export * from 'react-dom/src/server/ReactDOMFizzServerFormatConfig';
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export * from 'react-dom/src/server/ReactDOMFizzServerFormatConfig';
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// This is a host config that's used for the `react-stream` package on npm.
|
||||
// It is only used by third-party renderers.
|
||||
//
|
||||
// Its API lets you pass the host config as an argument.
|
||||
// However, inside the `react-stream` we treat host config as a module.
|
||||
// This file is a shim between two worlds.
|
||||
//
|
||||
// It works because the `react-stream` bundle is wrapped in something like:
|
||||
//
|
||||
// module.exports = function ($$$config) {
|
||||
// /* renderer code */
|
||||
// }
|
||||
//
|
||||
// So `$$$config` looks like a global variable, but it's
|
||||
// really an argument to a top-level wrapping function.
|
||||
|
||||
declare var $$$hostConfig: any;
|
||||
export opaque type Destination = mixed; // eslint-disable-line no-undef
|
||||
|
||||
export const scheduleWork = $$$hostConfig.scheduleWork;
|
||||
export const beginWriting = $$$hostConfig.beginWriting;
|
||||
export const writeChunk = $$$hostConfig.writeChunk;
|
||||
export const completeWriting = $$$hostConfig.completeWriting;
|
||||
export const flushBuffered = $$$hostConfig.flushBuffered;
|
||||
export const close = $$$hostConfig.close;
|
||||
export const convertStringToBuffer = $$$hostConfig.convertStringToBuffer;
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export * from '../ReactFizzHostConfigBrowser';
|
|
@ -0,0 +1,10 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
export * from '../ReactFizzHostConfigNode';
|
|
@ -18,15 +18,19 @@ const configTemplate = fs
|
|||
.readFileSync(__dirname + '/config/flowconfig')
|
||||
.toString();
|
||||
|
||||
function writeConfig(renderer) {
|
||||
function writeConfig(renderer, isFizzSupported) {
|
||||
const folder = __dirname + '/' + renderer;
|
||||
mkdirp.sync(folder);
|
||||
|
||||
const fizzRenderer = isFizzSupported ? renderer : 'custom';
|
||||
const config = configTemplate.replace(
|
||||
'%REACT_RENDERER_FLOW_OPTIONS%',
|
||||
`
|
||||
module.name_mapper='react-reconciler/inline.${renderer}$$' -> 'react-reconciler/inline-typed'
|
||||
module.name_mapper='ReactFiberHostConfig$$' -> 'forks/ReactFiberHostConfig.${renderer}'
|
||||
module.name_mapper='react-stream/inline.${renderer}$$' -> 'react-stream/inline-typed'
|
||||
module.name_mapper='ReactFizzHostConfig$$' -> 'forks/ReactFizzHostConfig.${fizzRenderer}'
|
||||
module.name_mapper='ReactFizzFormatConfig$$' -> 'forks/ReactFizzFormatConfig.${fizzRenderer}'
|
||||
`.trim(),
|
||||
);
|
||||
|
||||
|
@ -61,6 +65,6 @@ ${disclaimer}
|
|||
// so that we can run those checks in parallel if we want.
|
||||
inlinedHostConfigs.forEach(rendererInfo => {
|
||||
if (rendererInfo.isFlowTyped) {
|
||||
writeConfig(rendererInfo.shortName);
|
||||
writeConfig(rendererInfo.shortName, rendererInfo.isFizzSupported);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -17,6 +17,15 @@ jest.mock('react-reconciler/persistent', () => {
|
|||
return require.requireActual('react-reconciler/persistent');
|
||||
};
|
||||
});
|
||||
const shimFizzHostConfigPath = 'react-stream/src/ReactFizzHostConfig';
|
||||
const shimFizzFormatConfigPath = 'react-stream/src/ReactFizzFormatConfig';
|
||||
jest.mock('react-stream', () => {
|
||||
return config => {
|
||||
jest.mock(shimFizzHostConfigPath, () => config);
|
||||
jest.mock(shimFizzFormatConfigPath, () => config);
|
||||
return require.requireActual('react-stream');
|
||||
};
|
||||
});
|
||||
|
||||
// But for inlined host configs (such as React DOM, Native, etc), we
|
||||
// mock their named entry points to establish a host config mapping.
|
||||
|
@ -55,6 +64,46 @@ inlinedHostConfigs.forEach(rendererInfo => {
|
|||
|
||||
return renderer;
|
||||
});
|
||||
|
||||
if (rendererInfo.isFizzSupported) {
|
||||
jest.mock(`react-stream/inline.${rendererInfo.shortName}`, () => {
|
||||
let hasImportedShimmedConfig = false;
|
||||
|
||||
// We want the renderer to pick up the host config for this renderer.
|
||||
jest.mock(shimFizzHostConfigPath, () => {
|
||||
hasImportedShimmedConfig = true;
|
||||
return require.requireActual(
|
||||
`react-stream/src/forks/ReactFizzHostConfig.${
|
||||
rendererInfo.shortName
|
||||
}.js`
|
||||
);
|
||||
});
|
||||
jest.mock(shimFizzFormatConfigPath, () => {
|
||||
hasImportedShimmedConfig = true;
|
||||
return require.requireActual(
|
||||
`react-stream/src/forks/ReactFizzFormatConfig.${
|
||||
rendererInfo.shortName
|
||||
}.js`
|
||||
);
|
||||
});
|
||||
|
||||
const renderer = require.requireActual('react-stream');
|
||||
// If the shimmed config factory function above has not run,
|
||||
// it means this test file loads more than one renderer
|
||||
// but doesn't reset modules between them. This won't work.
|
||||
if (!hasImportedShimmedConfig) {
|
||||
throw new Error(
|
||||
`Could not import the "${rendererInfo.shortName}" renderer ` +
|
||||
`in this suite because another renderer has already been ` +
|
||||
`loaded earlier. Call jest.resetModules() before importing any ` +
|
||||
`of the following entry points:\n\n` +
|
||||
rendererInfo.entryPoints.map(entry => ` * ${entry}`)
|
||||
);
|
||||
}
|
||||
|
||||
return renderer;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Make it possible to import this module inside
|
||||
|
|
|
@ -158,6 +158,22 @@ const bundles = [
|
|||
externals: ['react', 'stream'],
|
||||
},
|
||||
|
||||
/******* React DOM Fizz Server *******/
|
||||
{
|
||||
bundleTypes: [NODE_DEV, NODE_PROD, UMD_DEV, UMD_PROD],
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-dom/unstable-fizz.browser',
|
||||
global: 'ReactDOMFizzServer',
|
||||
externals: ['react'],
|
||||
},
|
||||
{
|
||||
bundleTypes: [NODE_DEV, NODE_PROD, FB_WWW_DEV, FB_WWW_PROD],
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-dom/unstable-fizz.node',
|
||||
global: 'ReactDOMFizzServer',
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
/******* React ART *******/
|
||||
{
|
||||
bundleTypes: [
|
||||
|
@ -320,6 +336,28 @@ const bundles = [
|
|||
}),
|
||||
},
|
||||
|
||||
/******* React Noop Server Renderer (used for tests) *******/
|
||||
{
|
||||
bundleTypes: [NODE_DEV, NODE_PROD],
|
||||
moduleType: RENDERER,
|
||||
entry: 'react-noop-renderer/server',
|
||||
global: 'ReactNoopRendererServer',
|
||||
externals: ['react', 'expect'],
|
||||
// React Noop uses generators. However GCC currently
|
||||
// breaks when we attempt to use them in the output.
|
||||
// So we precompile them with regenerator, and include
|
||||
// it as a runtime dependency of React Noop. In practice
|
||||
// this isn't an issue because React Noop is only used
|
||||
// in our tests. We wouldn't want to do this for any
|
||||
// public package though.
|
||||
babel: opts =>
|
||||
Object.assign({}, opts, {
|
||||
plugins: opts.plugins.concat([
|
||||
require.resolve('babel-plugin-transform-regenerator'),
|
||||
]),
|
||||
}),
|
||||
},
|
||||
|
||||
/******* React Reconciler *******/
|
||||
{
|
||||
bundleTypes: [NODE_DEV, NODE_PROD],
|
||||
|
@ -338,6 +376,15 @@ const bundles = [
|
|||
externals: ['react'],
|
||||
},
|
||||
|
||||
/******* React Stream *******/
|
||||
{
|
||||
bundleTypes: [NODE_DEV, NODE_PROD],
|
||||
moduleType: RECONCILER,
|
||||
entry: 'react-stream',
|
||||
global: 'ReactStream',
|
||||
externals: ['react'],
|
||||
},
|
||||
|
||||
/******* Reflection *******/
|
||||
{
|
||||
moduleType: RENDERER_UTILS,
|
||||
|
|
|
@ -272,6 +272,66 @@ const forks = Object.freeze({
|
|||
);
|
||||
},
|
||||
|
||||
'react-stream/src/ReactFizzHostConfig': (
|
||||
bundleType,
|
||||
entry,
|
||||
dependencies,
|
||||
moduleType
|
||||
) => {
|
||||
if (dependencies.indexOf('react-stream') !== -1) {
|
||||
return null;
|
||||
}
|
||||
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||
return null;
|
||||
}
|
||||
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||
for (let rendererInfo of inlinedHostConfigs) {
|
||||
if (rendererInfo.entryPoints.indexOf(entry) !== -1) {
|
||||
if (!rendererInfo.isFizzSupported) {
|
||||
return null;
|
||||
}
|
||||
return `react-stream/src/forks/ReactFizzHostConfig.${
|
||||
rendererInfo.shortName
|
||||
}.js`;
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
'Expected ReactFizzHostConfig to always be replaced with a shim, but ' +
|
||||
`found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +
|
||||
'Did you mean to add it there to associate it with a specific renderer?'
|
||||
);
|
||||
},
|
||||
|
||||
'react-stream/src/ReactFizzFormatConfig': (
|
||||
bundleType,
|
||||
entry,
|
||||
dependencies,
|
||||
moduleType
|
||||
) => {
|
||||
if (dependencies.indexOf('react-stream') !== -1) {
|
||||
return null;
|
||||
}
|
||||
if (moduleType !== RENDERER && moduleType !== RECONCILER) {
|
||||
return null;
|
||||
}
|
||||
// eslint-disable-next-line no-for-of-loops/no-for-of-loops
|
||||
for (let rendererInfo of inlinedHostConfigs) {
|
||||
if (rendererInfo.entryPoints.indexOf(entry) !== -1) {
|
||||
if (!rendererInfo.isFizzSupported) {
|
||||
return null;
|
||||
}
|
||||
return `react-stream/src/forks/ReactFizzFormatConfig.${
|
||||
rendererInfo.shortName
|
||||
}.js`;
|
||||
}
|
||||
}
|
||||
throw new Error(
|
||||
'Expected ReactFizzFormatConfig to always be replaced with a shim, but ' +
|
||||
`found no mention of "${entry}" entry point in ./scripts/shared/inlinedHostConfigs.js. ` +
|
||||
'Did you mean to add it there to associate it with a specific renderer?'
|
||||
);
|
||||
},
|
||||
|
||||
// We wrap top-level listeners into guards on www.
|
||||
'react-dom/src/events/EventListener': (bundleType, entry) => {
|
||||
switch (bundleType) {
|
||||
|
|
|
@ -46,29 +46,29 @@
|
|||
"filename": "react-dom.development.js",
|
||||
"bundleType": "UMD_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 725515,
|
||||
"gzip": 167737
|
||||
"size": 725813,
|
||||
"gzip": 167799
|
||||
},
|
||||
{
|
||||
"filename": "react-dom.production.min.js",
|
||||
"bundleType": "UMD_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 100307,
|
||||
"gzip": 32617
|
||||
"size": 99920,
|
||||
"gzip": 32521
|
||||
},
|
||||
{
|
||||
"filename": "react-dom.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 720713,
|
||||
"gzip": 166331
|
||||
"size": 721011,
|
||||
"gzip": 166399
|
||||
},
|
||||
{
|
||||
"filename": "react-dom.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 100301,
|
||||
"gzip": 32146
|
||||
"size": 99914,
|
||||
"gzip": 32052
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOM-dev.js",
|
||||
|
@ -165,8 +165,8 @@
|
|||
"filename": "react-dom-server.browser.development.js",
|
||||
"bundleType": "UMD_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 120524,
|
||||
"gzip": 32011
|
||||
"size": 122056,
|
||||
"gzip": 32469
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-server.browser.production.min.js",
|
||||
|
@ -179,8 +179,8 @@
|
|||
"filename": "react-dom-server.browser.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 116562,
|
||||
"gzip": 31037
|
||||
"size": 118094,
|
||||
"gzip": 31495
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-server.browser.production.min.js",
|
||||
|
@ -207,8 +207,8 @@
|
|||
"filename": "react-dom-server.node.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 118530,
|
||||
"gzip": 31584
|
||||
"size": 120062,
|
||||
"gzip": 32036
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-server.node.production.min.js",
|
||||
|
@ -221,29 +221,29 @@
|
|||
"filename": "react-art.development.js",
|
||||
"bundleType": "UMD_DEV",
|
||||
"packageName": "react-art",
|
||||
"size": 507548,
|
||||
"gzip": 112066
|
||||
"size": 507846,
|
||||
"gzip": 112120
|
||||
},
|
||||
{
|
||||
"filename": "react-art.production.min.js",
|
||||
"bundleType": "UMD_PROD",
|
||||
"packageName": "react-art",
|
||||
"size": 92284,
|
||||
"gzip": 28330
|
||||
"size": 91897,
|
||||
"gzip": 28219
|
||||
},
|
||||
{
|
||||
"filename": "react-art.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-art",
|
||||
"size": 437685,
|
||||
"gzip": 94610
|
||||
"size": 437983,
|
||||
"gzip": 94680
|
||||
},
|
||||
{
|
||||
"filename": "react-art.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-art",
|
||||
"size": 56431,
|
||||
"gzip": 17393
|
||||
"size": 56044,
|
||||
"gzip": 17298
|
||||
},
|
||||
{
|
||||
"filename": "ReactART-dev.js",
|
||||
|
@ -291,29 +291,29 @@
|
|||
"filename": "react-test-renderer.development.js",
|
||||
"bundleType": "UMD_DEV",
|
||||
"packageName": "react-test-renderer",
|
||||
"size": 450653,
|
||||
"gzip": 97378
|
||||
"size": 450951,
|
||||
"gzip": 97435
|
||||
},
|
||||
{
|
||||
"filename": "react-test-renderer.production.min.js",
|
||||
"bundleType": "UMD_PROD",
|
||||
"packageName": "react-test-renderer",
|
||||
"size": 57674,
|
||||
"gzip": 17698
|
||||
"size": 57293,
|
||||
"gzip": 17617
|
||||
},
|
||||
{
|
||||
"filename": "react-test-renderer.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-test-renderer",
|
||||
"size": 445754,
|
||||
"gzip": 96206
|
||||
"size": 446052,
|
||||
"gzip": 96263
|
||||
},
|
||||
{
|
||||
"filename": "react-test-renderer.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-test-renderer",
|
||||
"size": 57342,
|
||||
"gzip": 17539
|
||||
"size": 56955,
|
||||
"gzip": 17453
|
||||
},
|
||||
{
|
||||
"filename": "ReactTestRenderer-dev.js",
|
||||
|
@ -375,29 +375,29 @@
|
|||
"filename": "react-reconciler.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-reconciler",
|
||||
"size": 435479,
|
||||
"gzip": 93068
|
||||
"size": 435777,
|
||||
"gzip": 93120
|
||||
},
|
||||
{
|
||||
"filename": "react-reconciler.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-reconciler",
|
||||
"size": 57593,
|
||||
"gzip": 17242
|
||||
"size": 57202,
|
||||
"gzip": 17158
|
||||
},
|
||||
{
|
||||
"filename": "react-reconciler-persistent.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-reconciler",
|
||||
"size": 433889,
|
||||
"gzip": 92426
|
||||
"size": 434187,
|
||||
"gzip": 92481
|
||||
},
|
||||
{
|
||||
"filename": "react-reconciler-persistent.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-reconciler",
|
||||
"size": 57604,
|
||||
"gzip": 17248
|
||||
"size": 57213,
|
||||
"gzip": 17164
|
||||
},
|
||||
{
|
||||
"filename": "react-reconciler-reflection.development.js",
|
||||
|
@ -515,15 +515,15 @@
|
|||
"filename": "ReactDOM-dev.js",
|
||||
"bundleType": "FB_WWW_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 742105,
|
||||
"gzip": 167549
|
||||
"size": 742241,
|
||||
"gzip": 167544
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOM-prod.js",
|
||||
"bundleType": "FB_WWW_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 318358,
|
||||
"gzip": 58562
|
||||
"size": 317018,
|
||||
"gzip": 58396
|
||||
},
|
||||
{
|
||||
"filename": "ReactTestUtils-dev.js",
|
||||
|
@ -550,8 +550,8 @@
|
|||
"filename": "ReactDOMServer-dev.js",
|
||||
"bundleType": "FB_WWW_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 117649,
|
||||
"gzip": 30639
|
||||
"size": 119227,
|
||||
"gzip": 31112
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOMServer-prod.js",
|
||||
|
@ -564,78 +564,78 @@
|
|||
"filename": "ReactART-dev.js",
|
||||
"bundleType": "FB_WWW_DEV",
|
||||
"packageName": "react-art",
|
||||
"size": 445159,
|
||||
"gzip": 93560
|
||||
"size": 445295,
|
||||
"gzip": 93558
|
||||
},
|
||||
{
|
||||
"filename": "ReactART-prod.js",
|
||||
"bundleType": "FB_WWW_PROD",
|
||||
"packageName": "react-art",
|
||||
"size": 189135,
|
||||
"gzip": 32266
|
||||
"size": 187912,
|
||||
"gzip": 32090
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-dev.js",
|
||||
"bundleType": "RN_FB_DEV",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 573357,
|
||||
"gzip": 124963
|
||||
"size": 573493,
|
||||
"gzip": 124971
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-prod.js",
|
||||
"bundleType": "RN_FB_PROD",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 245987,
|
||||
"gzip": 43227
|
||||
"size": 244566,
|
||||
"gzip": 43021
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-dev.js",
|
||||
"bundleType": "RN_OSS_DEV",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 573046,
|
||||
"gzip": 124866
|
||||
"size": 573182,
|
||||
"gzip": 124874
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-prod.js",
|
||||
"bundleType": "RN_OSS_PROD",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 231080,
|
||||
"gzip": 40077
|
||||
"size": 229659,
|
||||
"gzip": 39880
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-dev.js",
|
||||
"bundleType": "RN_FB_DEV",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 563440,
|
||||
"gzip": 122415
|
||||
"size": 563576,
|
||||
"gzip": 122418
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-prod.js",
|
||||
"bundleType": "RN_FB_PROD",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 225188,
|
||||
"gzip": 38730
|
||||
"size": 223730,
|
||||
"gzip": 38540
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-dev.js",
|
||||
"bundleType": "RN_OSS_DEV",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 563475,
|
||||
"gzip": 122429
|
||||
"size": 563611,
|
||||
"gzip": 122433
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-prod.js",
|
||||
"bundleType": "RN_OSS_PROD",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 225224,
|
||||
"gzip": 38745
|
||||
"size": 223766,
|
||||
"gzip": 38555
|
||||
},
|
||||
{
|
||||
"filename": "ReactTestRenderer-dev.js",
|
||||
"bundleType": "FB_WWW_DEV",
|
||||
"packageName": "react-test-renderer",
|
||||
"size": 453421,
|
||||
"gzip": 95442
|
||||
"size": 453557,
|
||||
"gzip": 95443
|
||||
},
|
||||
{
|
||||
"filename": "ReactShallowRenderer-dev.js",
|
||||
|
@ -718,22 +718,22 @@
|
|||
"filename": "react-dom.profiling.min.js",
|
||||
"bundleType": "NODE_PROFILING",
|
||||
"packageName": "react-dom",
|
||||
"size": 103137,
|
||||
"gzip": 32687
|
||||
"size": 102985,
|
||||
"gzip": 32673
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-profiling.js",
|
||||
"bundleType": "RN_OSS_PROFILING",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 236392,
|
||||
"gzip": 41298
|
||||
"size": 235342,
|
||||
"gzip": 41248
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-profiling.js",
|
||||
"bundleType": "RN_OSS_PROFILING",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 229595,
|
||||
"gzip": 40005
|
||||
"size": 228530,
|
||||
"gzip": 39962
|
||||
},
|
||||
{
|
||||
"filename": "Scheduler-dev.js",
|
||||
|
@ -767,22 +767,22 @@
|
|||
"filename": "ReactDOM-profiling.js",
|
||||
"bundleType": "FB_WWW_PROFILING",
|
||||
"packageName": "react-dom",
|
||||
"size": 324711,
|
||||
"gzip": 59847
|
||||
"size": 323954,
|
||||
"gzip": 59824
|
||||
},
|
||||
{
|
||||
"filename": "ReactNativeRenderer-profiling.js",
|
||||
"bundleType": "RN_FB_PROFILING",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 251555,
|
||||
"gzip": 44455
|
||||
"size": 250505,
|
||||
"gzip": 44397
|
||||
},
|
||||
{
|
||||
"filename": "ReactFabric-profiling.js",
|
||||
"bundleType": "RN_FB_PROFILING",
|
||||
"packageName": "react-native-renderer",
|
||||
"size": 229554,
|
||||
"gzip": 39988
|
||||
"size": 228489,
|
||||
"gzip": 39945
|
||||
},
|
||||
{
|
||||
"filename": "react.profiling.min.js",
|
||||
|
@ -795,8 +795,8 @@
|
|||
"filename": "react-dom.profiling.min.js",
|
||||
"bundleType": "UMD_PROFILING",
|
||||
"packageName": "react-dom",
|
||||
"size": 103046,
|
||||
"gzip": 33256
|
||||
"size": 102894,
|
||||
"gzip": 33243
|
||||
},
|
||||
{
|
||||
"filename": "scheduler-tracing.development.js",
|
||||
|
@ -937,6 +937,90 @@
|
|||
"packageName": "eslint-plugin-react-hooks",
|
||||
"size": 4943,
|
||||
"gzip": 1815
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOMFizzServer-dev.js",
|
||||
"bundleType": "FB_WWW_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 3772,
|
||||
"gzip": 1432
|
||||
},
|
||||
{
|
||||
"filename": "ReactDOMFizzServer-prod.js",
|
||||
"bundleType": "FB_WWW_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 2211,
|
||||
"gzip": 874
|
||||
},
|
||||
{
|
||||
"filename": "react-noop-renderer-server.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-noop-renderer",
|
||||
"size": 1861,
|
||||
"gzip": 869
|
||||
},
|
||||
{
|
||||
"filename": "react-noop-renderer-server.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-noop-renderer",
|
||||
"size": 804,
|
||||
"gzip": 482
|
||||
},
|
||||
{
|
||||
"filename": "react-stream.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-stream",
|
||||
"size": 4633,
|
||||
"gzip": 1683
|
||||
},
|
||||
{
|
||||
"filename": "react-stream.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-stream",
|
||||
"size": 1224,
|
||||
"gzip": 655
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.browser.development.js",
|
||||
"bundleType": "UMD_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 3704,
|
||||
"gzip": 1463
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.browser.production.min.js",
|
||||
"bundleType": "UMD_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 1227,
|
||||
"gzip": 697
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.browser.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 3528,
|
||||
"gzip": 1416
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.browser.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 1063,
|
||||
"gzip": 628
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.node.development.js",
|
||||
"bundleType": "NODE_DEV",
|
||||
"packageName": "react-dom",
|
||||
"size": 3780,
|
||||
"gzip": 1443
|
||||
},
|
||||
{
|
||||
"filename": "react-dom-unstable-fizz.node.production.min.js",
|
||||
"bundleType": "NODE_PROD",
|
||||
"packageName": "react-dom",
|
||||
"size": 1122,
|
||||
"gzip": 659
|
||||
}
|
||||
]
|
||||
}
|
|
@ -18,6 +18,8 @@ module.exports = {
|
|||
__REACT_DEVTOOLS_GLOBAL_HOOK__: true,
|
||||
// CommonJS / Node
|
||||
process: true,
|
||||
setImmediate: true,
|
||||
Buffer: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 5,
|
||||
|
|
|
@ -18,6 +18,9 @@ module.exports = {
|
|||
__REACT_DEVTOOLS_GLOBAL_HOOK__: true,
|
||||
// FB
|
||||
__DEV__: true,
|
||||
// Node.js Server Rendering
|
||||
setImmediate: true,
|
||||
Buffer: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 5,
|
||||
|
|
|
@ -9,8 +9,15 @@
|
|||
module.exports = [
|
||||
{
|
||||
shortName: 'dom',
|
||||
entryPoints: ['react-dom'],
|
||||
entryPoints: ['react-dom', 'react-dom/unstable-fizz.node'],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: true,
|
||||
},
|
||||
{
|
||||
shortName: 'dom-browser',
|
||||
entryPoints: ['react-dom/unstable-fizz.browser'],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: true,
|
||||
},
|
||||
{
|
||||
shortName: 'fire',
|
||||
|
@ -21,25 +28,34 @@ module.exports = [
|
|||
shortName: 'art',
|
||||
entryPoints: ['react-art'],
|
||||
isFlowTyped: false, // TODO: type it.
|
||||
isFizzSupported: false,
|
||||
},
|
||||
{
|
||||
shortName: 'native',
|
||||
entryPoints: ['react-native-renderer'],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: false,
|
||||
},
|
||||
{
|
||||
shortName: 'fabric',
|
||||
entryPoints: ['react-native-renderer/fabric'],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: false,
|
||||
},
|
||||
{
|
||||
shortName: 'test',
|
||||
entryPoints: ['react-test-renderer'],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: false,
|
||||
},
|
||||
{
|
||||
shortName: 'custom',
|
||||
entryPoints: ['react-reconciler', 'react-reconciler/persistent'],
|
||||
entryPoints: [
|
||||
'react-reconciler',
|
||||
'react-reconciler/persistent',
|
||||
'react-stream',
|
||||
],
|
||||
isFlowTyped: true,
|
||||
isFizzSupported: true,
|
||||
},
|
||||
];
|
||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -94,6 +94,18 @@
|
|||
lodash "^4.17.10"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@mattiasbuelens/web-streams-polyfill@0.1.0":
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@mattiasbuelens/web-streams-polyfill/-/web-streams-polyfill-0.1.0.tgz#c06ebfa7e00cc512a878c3aaae4cf113ac89ac24"
|
||||
integrity sha512-oMsvblvOezdM/j1ph0uU8s6Wm0EfCyMZtZcxQ232CqSpjm08lrKPizeMltN0eVv4dQf0DDFaxUFyiz8x51lgAA==
|
||||
dependencies:
|
||||
"@types/whatwg-streams" "^0.0.6"
|
||||
|
||||
"@types/whatwg-streams@^0.0.6":
|
||||
version "0.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/whatwg-streams/-/whatwg-streams-0.0.6.tgz#5062c67efb695c886fe3dbb9618df35aac418503"
|
||||
integrity sha512-O4Hat94N1RUCObqAbVUtd6EcucseqBcpfbFXzy12CYF6BQVHWR+ztDA3YPjewCmdKHYZ5VA7TZ5hq2bMyqxiBw==
|
||||
|
||||
abab@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e"
|
||||
|
|
Loading…
Reference in New Issue