React reconciler package (#10758)

* Initial commit of react-reconciler bundle

* I think it’s working 🙀

* React reconciler: slightly better description and README

* Drop react-reconciler version to an unstable release number

* Convert to moduleType enum and fix packaging

* eslint

* s/Renderer/Reconciler in docs

* yarn prettier

* change names of things in the react-reconciler readme

* change predicate

* rollup: flip object-assign shimming check

* copy noop renderer into react-reconciler fixture

* Change reconciler fixture test

* prettier

* Remove a bunch of Noop test renderer

* Delete a bunch of stuff we don’t care about for reconciler teesting. Add flow pragmas for future flow pragma testing

* Remove PATENTS

* Update Reconciler fixture docs

* ReactDOMUnstableNativeDependencies should be ISOMORPHIC

* Inline fixture renderer

* Make it "RENDERER"

* There is no UMD build. It also doesn't need propTypes.

* Tweak how the reconciler is built

* Record sizes

* Update README.md
This commit is contained in:
Dustan Kasten
2017-10-11 14:29:26 -04:00
committed by Dan Abramov
parent fb0199b73c
commit 111731dedd
11 changed files with 620 additions and 38 deletions

View File

@@ -0,0 +1,13 @@
# React Reconciler Test Fixture
This folder exists for **React contributors** only.
If you use React you don't need to worry about it.
These fixtures are a smoke-screen verification that the built React Reconciler distribution works.
To test, from the project root:
* `yarn build`
* `cd fixtures/reconciler`
* `yarn test`
They should run as part of the CI check.

View File

@@ -0,0 +1,366 @@
/**
* This is a renderer of React that doesn't have a render target output.
* It is used to test that the react-reconciler package doesn't blow up.
*
* @flow
*/
'use strict';
var React = require('react');
var assert = require('assert');
var ReactFiberReconciler = require('react-reconciler');
var emptyObject = require('fbjs/lib/emptyObject');
var assert = require('assert');
const UPDATE_SIGNAL = {};
var scheduledCallback = null;
type Container = {rootID: string, children: Array<Instance | TextInstance>};
type Props = {prop: any, hidden?: boolean};
type Instance = {|
type: string,
id: number,
children: Array<Instance | TextInstance>,
prop: any,
|};
type TextInstance = {|text: string, id: number|};
var instanceCounter = 0;
function appendChild(
parentInstance: Instance | Container,
child: Instance | TextInstance
): void {
const index = parentInstance.children.indexOf(child);
if (index !== -1) {
parentInstance.children.splice(index, 1);
}
parentInstance.children.push(child);
}
function insertBefore(
parentInstance: Instance | Container,
child: Instance | TextInstance,
beforeChild: Instance | TextInstance
): void {
const index = parentInstance.children.indexOf(child);
if (index !== -1) {
parentInstance.children.splice(index, 1);
}
const beforeIndex = parentInstance.children.indexOf(beforeChild);
if (beforeIndex === -1) {
throw new Error('This child does not exist.');
}
parentInstance.children.splice(beforeIndex, 0, child);
}
function removeChild(
parentInstance: Instance | Container,
child: Instance | TextInstance
): void {
const index = parentInstance.children.indexOf(child);
if (index === -1) {
throw new Error('This child does not exist.');
}
parentInstance.children.splice(index, 1);
}
var NoopRenderer = ReactFiberReconciler({
getRootHostContext() {
return emptyObject;
},
getChildHostContext() {
return emptyObject;
},
getPublicInstance(instance) {
return instance;
},
createInstance(type: string, props: Props): Instance {
const inst = {
id: instanceCounter++,
type: type,
children: [],
prop: props.prop,
};
// Hide from unit tests
Object.defineProperty(inst, 'id', {value: inst.id, enumerable: false});
return inst;
},
appendInitialChild(
parentInstance: Instance,
child: Instance | TextInstance
): void {
parentInstance.children.push(child);
},
finalizeInitialChildren(
domElement: Instance,
type: string,
props: Props
): boolean {
return false;
},
prepareUpdate(
instance: Instance,
type: string,
oldProps: Props,
newProps: Props
): null | {} {
return UPDATE_SIGNAL;
},
commitMount(instance: Instance, type: string, newProps: Props): void {
// Noop
},
commitUpdate(
instance: Instance,
updatePayload: Object,
type: string,
oldProps: Props,
newProps: Props
): void {
instance.prop = newProps.prop;
},
shouldSetTextContent(type: string, props: Props): boolean {
return (
typeof props.children === 'string' || typeof props.children === 'number'
);
},
resetTextContent(instance: Instance): void {},
shouldDeprioritizeSubtree(type: string, props: Props): boolean {
return !!props.hidden;
},
now: Date.now,
createTextInstance(
text: string,
rootContainerInstance: Container,
hostContext: Object,
internalInstanceHandle: Object
): TextInstance {
var inst = {text: text, id: instanceCounter++};
// Hide from unit tests
Object.defineProperty(inst, 'id', {value: inst.id, enumerable: false});
return inst;
},
commitTextUpdate(
textInstance: TextInstance,
oldText: string,
newText: string
): void {
textInstance.text = newText;
},
appendChild: appendChild,
appendChildToContainer: appendChild,
insertBefore: insertBefore,
insertInContainerBefore: insertBefore,
removeChild: removeChild,
removeChildFromContainer: removeChild,
scheduleDeferredCallback(callback) {
if (scheduledCallback) {
throw new Error(
'Scheduling a callback twice is excessive. Instead, keep track of ' +
'whether the callback has already been scheduled.'
);
}
scheduledCallback = callback;
},
prepareForCommit(): void {},
resetAfterCommit(): void {},
});
var rootContainers = new Map();
var roots = new Map();
var DEFAULT_ROOT_ID = '<default>';
let yieldedValues = null;
function* flushUnitsOfWork(n: number): Generator<Array<mixed>, void, void> {
var didStop = false;
while (!didStop && scheduledCallback !== null) {
var cb = scheduledCallback;
scheduledCallback = null;
yieldedValues = null;
var unitsRemaining = n;
cb({
timeRemaining() {
if (yieldedValues !== null) {
return 0;
}
if (unitsRemaining-- > 0) {
return 999;
}
didStop = true;
return 0;
},
});
if (yieldedValues !== null) {
const values = yieldedValues;
yieldedValues = null;
yield values;
}
}
}
var Noop = {
getChildren(rootID: string = DEFAULT_ROOT_ID) {
const container = rootContainers.get(rootID);
if (container) {
return container.children;
} else {
return null;
}
},
// Shortcut for testing a single root
render(element: React$Element<any>, callback: ?Function) {
Noop.renderToRootWithID(element, DEFAULT_ROOT_ID, callback);
},
renderToRootWithID(
element: React$Element<any>,
rootID: string,
callback: ?Function
) {
let root = roots.get(rootID);
if (!root) {
const container = {rootID: rootID, children: []};
rootContainers.set(rootID, container);
root = NoopRenderer.createContainer(container);
roots.set(rootID, root);
}
NoopRenderer.updateContainer(element, root, null, callback);
},
flush(): Array<mixed> {
return Noop.flushUnitsOfWork(Infinity);
},
flushUnitsOfWork(n: number): Array<mixed> {
let values = [];
for (const value of flushUnitsOfWork(n)) {
values.push(...value);
}
return values;
},
batchedUpdates: NoopRenderer.batchedUpdates,
deferredUpdates: NoopRenderer.deferredUpdates,
unbatchedUpdates: NoopRenderer.unbatchedUpdates,
flushSync: NoopRenderer.flushSync,
};
type TestProps = {|
active: boolean,
|};
type TestState = {|
counter: number,
|};
let instance = null;
class Test extends React.Component<TestProps, TestState> {
state = {counter: 0};
increment() {
this.setState(({counter}) => ({
counter: counter + 1,
}));
}
render() {
return [this.props.active ? 'Active' : 'Inactive', this.state.counter];
}
}
const Children = props => props.children;
Noop.render(
<main>
<div>Hello</div>
<Children>
Hello world
<span>{'Number '}{42}</span>
<Test active={true} ref={t => (instance = t)} />
</Children>
</main>
);
Noop.flush();
const actual1 = Noop.getChildren();
const expected1 = [
{
type: 'main',
children: [
{type: 'div', children: [], prop: undefined},
{text: 'Hello world'},
{
type: 'span',
children: [{text: 'Number '}, {text: '42'}],
prop: undefined,
},
{text: 'Active'},
{text: '0'},
],
prop: undefined,
},
];
assert.deepEqual(
actual1,
expected1,
'Error. Noop.getChildren() returned unexpected value.\nExpected:\ ' +
JSON.stringify(expected1, null, 2) +
'\n\nActual:\n ' +
JSON.stringify(actual1, null, 2)
);
if (instance === null) {
throw new Error('Expected instance to exist.');
}
instance.increment();
Noop.flush();
const actual2 = Noop.getChildren();
const expected2 = [
{
type: 'main',
children: [
{type: 'div', children: [], prop: undefined},
{text: 'Hello world'},
{
type: 'span',
children: [{text: 'Number '}, {text: '42'}],
prop: undefined,
},
{text: 'Active'},
{text: '1'},
],
prop: undefined,
},
];
assert.deepEqual(
actual2,
expected2,
'Error. Noop.getChildren() returned unexpected value.\nExpected:\ ' +
JSON.stringify(expected2, null, 2) +
'\n\nActual:\n ' +
JSON.stringify(actual2, null, 2)
);
const beginGreen = '\u001b[32m';
const endGreen = '\u001b[39m';
console.log(beginGreen + 'Reconciler package is OK!' + endGreen);

View File

@@ -0,0 +1,10 @@
{
"name": "react-fixtures",
"version": "0.1.0",
"private": true,
"scripts": {
"test:dev": "NODE_PATH=../../build/packages ../../node_modules/.bin/babel-node ./index",
"test:prod": "NODE_PATH=../../build/packages NODE_ENV=production ../../node_modules/.bin/babel-node ./index",
"test": "npm run test:dev && npm run test:prod"
}
}

View File

@@ -0,0 +1,39 @@
# react-reconciler
This is an experimental package for creating custom React 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 Reconciler = require('react-reconciler');
var ReconcilerConfig = {
// You'll need to implement some methods here.
// See below for more information and examples.
};
var MyRenderer = Reconciler(ReconcilerConfig);
var RendererPublicAPI = {
render(element, container, callback) {
// Call MyRenderer.updateContainer() to schedule changes on the roots.
// See ReactDOM, React Native, or React ART for practical examples.
}
};
module.exports = RendererPublicAPI;
```
## Practical Examples
* [React ART](https://github.com/facebook/react/blob/master/src/renderers/art/ReactARTFiberEntry.js)
* [React DOM](https://github.com/facebook/react/blob/master/src/fb/ReactDOMFiberFBEntry.js)
* [React Native](https://github.com/facebook/react/blob/master/src/renderers/native/ReactNativeFiberRenderer.js)
If these links break please file an issue and well fix them. They intentionally link to the latest versions since the API is still evolving.
This [third-party tutorial](https://github.com/nitin42/Making-a-custom-React-renderer) is relatively up-to-date and may be helpful.

7
packages/react-reconciler/index.js vendored Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-reconciler.production.min.js');
} else {
module.exports = require('./cjs/react-reconciler.development.js');
}

View File

@@ -0,0 +1,35 @@
{
"name": "react-reconciler",
"description": "React package for creating custom renderers.",
"version": "0.1.0",
"keywords": [
"react"
],
"homepage": "https://facebook.github.io/react/",
"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": {
"fbjs": "^0.8.16",
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
},
"browserify": {
"transform": [
"loose-envify"
]
}
}

View File

@@ -3,4 +3,8 @@
set -e
npm run build -- --extract-errors
git checkout -- scripts/error-codes/codes.json
git checkout -- scripts/error-codes/codes.json
# Check that the standalone reconciler isn't borked
cd fixtures/reconciler
yarn test

View File

@@ -34,6 +34,8 @@ const FB_PROD = Bundles.bundleTypes.FB_PROD;
const RN_DEV = Bundles.bundleTypes.RN_DEV;
const RN_PROD = Bundles.bundleTypes.RN_PROD;
const RECONCILER = Bundles.moduleTypes.RECONCILER;
const reactVersion = require('../../package.json').version;
const requestedBundleTypes = (argv.type || '')
.split(',')
@@ -78,7 +80,13 @@ function getHeaderSanityCheck(bundleType, hasteName) {
}
}
function getBanner(bundleType, hasteName, filename) {
function getBanner(bundleType, hasteName, filename, moduleType) {
if (moduleType === RECONCILER) {
// Standalone reconciler is only used by third-party renderers.
// It is handled separately.
return getReconcilerBanner(bundleType, filename);
}
switch (bundleType) {
// UMDs are not wrapped in conditions.
case UMD_DEV:
@@ -112,7 +120,13 @@ function getBanner(bundleType, hasteName, filename) {
}
}
function getFooter(bundleType) {
function getFooter(bundleType, filename, moduleType) {
if (moduleType === RECONCILER) {
// Standalone reconciler is only used by third-party renderers.
// It is handled separately.
return getReconcilerFooter(bundleType);
}
// Only need a footer if getBanner() has an opening brace.
switch (bundleType) {
// Non-UMD DEV bundles need conditions to help weak dead code elimination.
@@ -125,7 +139,46 @@ function getFooter(bundleType) {
}
}
function updateBabelConfig(babelOpts, bundleType) {
// TODO: this is extremely gross.
// But it only affects the "experimental" standalone reconciler build.
// The goal is to avoid having any shared state between renderers sharing it on npm.
// Ideally we should just remove shared state in all Fiber modules and then lint against it.
// But for now, we store the exported function in a variable, and then put the rest of the code
// into a closure that makes all module-level state private to each call.
const RECONCILER_WRAPPER_INTRO = `var $$$reconciler;\nmodule.exports = function(config) {\n`;
const RECONCILER_WRAPPER_OUTRO = `return ($$$reconciler || ($$$reconciler = module.exports))(config);\n};\n`;
function getReconcilerBanner(bundleType, filename) {
let banner = `${Header.getHeader(filename, reactVersion)}\n\n'use strict';\n\n\n`;
switch (bundleType) {
case NODE_DEV:
banner += `if (process.env.NODE_ENV !== "production") {\n${RECONCILER_WRAPPER_INTRO}`;
break;
case NODE_PROD:
banner += RECONCILER_WRAPPER_INTRO;
break;
default:
throw new Error(
'Standalone reconciler does not support ' + bundleType + ' builds.'
);
}
return banner;
}
function getReconcilerFooter(bundleType) {
switch (bundleType) {
case NODE_DEV:
return `\n${RECONCILER_WRAPPER_OUTRO}\n}`;
case NODE_PROD:
return `\n${RECONCILER_WRAPPER_OUTRO}`;
default:
throw new Error(
'Standalone reconciler does not support ' + bundleType + ' builds.'
);
}
}
function updateBabelConfig(babelOpts, bundleType, filename) {
switch (bundleType) {
case FB_DEV:
case FB_PROD:
@@ -166,16 +219,23 @@ function handleRollupWarnings(warning) {
console.warn(warning.message || warning);
}
function updateBundleConfig(config, filename, format, bundleType, hasteName) {
function updateBundleConfig(
config,
filename,
format,
bundleType,
hasteName,
moduleType
) {
return Object.assign({}, config, {
banner: getBanner(bundleType, hasteName, filename),
banner: getBanner(bundleType, hasteName, filename, moduleType),
dest: Packaging.getPackageDestination(
config,
bundleType,
filename,
hasteName
),
footer: getFooter(bundleType),
footer: getFooter(bundleType, filename, moduleType),
format,
interop: false,
});
@@ -309,7 +369,7 @@ function getPlugins(
filename,
bundleType,
hasteName,
isRenderer,
moduleType,
manglePropertiesOnProd,
useFiber,
modulesToStub
@@ -317,7 +377,7 @@ function getPlugins(
const plugins = [
babel(updateBabelConfig(babelOpts, bundleType)),
alias(
Modules.getAliases(paths, bundleType, isRenderer, argv['extract-errors'])
Modules.getAliases(paths, bundleType, moduleType, argv['extract-errors'])
),
];
@@ -453,7 +513,7 @@ function createBundle(bundle, bundleType) {
external: Modules.getExternalModules(
bundle.externals,
bundleType,
bundle.isRenderer
bundle.moduleType
),
onwarn: handleRollupWarnings,
plugins: getPlugins(
@@ -463,7 +523,7 @@ function createBundle(bundle, bundleType) {
filename,
bundleType,
bundle.hasteName,
bundle.isRenderer,
bundle.moduleType,
bundle.manglePropertiesOnProd,
bundle.useFiber,
bundle.modulesToStub
@@ -476,7 +536,8 @@ function createBundle(bundle, bundleType) {
filename,
format,
bundleType,
bundle.hasteName
bundle.hasteName,
bundle.moduleType
)
)
)

View File

@@ -20,6 +20,16 @@ const FB_PROD = bundleTypes.FB_PROD;
const RN_DEV = bundleTypes.RN_DEV;
const RN_PROD = bundleTypes.RN_PROD;
const moduleTypes = {
ISOMORPHIC: 'ISOMORPHIC',
RENDERER: 'RENDERER',
RECONCILER: 'RECONCILER',
};
const ISOMORPHIC = moduleTypes.ISOMORPHIC;
const RENDERER = moduleTypes.RENDERER;
const RECONCILER = moduleTypes.RECONCILER;
const babelOptsReact = {
exclude: 'node_modules/**',
presets: [],
@@ -51,7 +61,7 @@ const bundles = [
],
fbEntry: 'src/isomorphic/ReactEntry',
hasteName: 'React',
isRenderer: false,
moduleType: ISOMORPHIC,
label: 'core',
manglePropertiesOnProd: false,
name: 'react',
@@ -79,7 +89,7 @@ const bundles = [
externals: ['prop-types', 'prop-types/checkPropTypes'],
fbEntry: 'src/fb/ReactDOMFiberFBEntry',
hasteName: 'ReactDOMFiber',
isRenderer: true,
moduleType: RENDERER,
label: 'dom-fiber',
manglePropertiesOnProd: false,
name: 'react-dom',
@@ -112,7 +122,7 @@ const bundles = [
],
fbEntry: 'src/renderers/dom/test/ReactTestUtilsEntry',
hasteName: 'ReactTestUtils',
isRenderer: true,
moduleType: RENDERER,
label: 'test-utils',
manglePropertiesOnProd: false,
name: 'react-dom/test-utils',
@@ -147,7 +157,7 @@ const bundles = [
],
fbEntry: 'src/renderers/dom/shared/ReactDOMUnstableNativeDependenciesEntry',
hasteName: 'ReactDOMUnstableNativeDependencies',
isRenderer: false,
moduleType: RENDERER,
label: 'dom-unstable-native-dependencies',
manglePropertiesOnProd: false,
name: 'react-dom/unstable-native-dependencies',
@@ -176,7 +186,7 @@ const bundles = [
externals: ['prop-types', 'prop-types/checkPropTypes'],
fbEntry: 'src/renderers/dom/ReactDOMServerBrowserEntry',
hasteName: 'ReactDOMServer',
isRenderer: true,
moduleType: RENDERER,
label: 'dom-server-browser',
manglePropertiesOnProd: false,
name: 'react-dom/server.browser',
@@ -201,7 +211,7 @@ const bundles = [
},
entry: 'src/renderers/dom/ReactDOMServerNodeEntry',
externals: ['prop-types', 'prop-types/checkPropTypes', 'stream'],
isRenderer: true,
moduleType: RENDERER,
label: 'dom-server-server-node',
manglePropertiesOnProd: false,
name: 'react-dom/server.node',
@@ -237,7 +247,7 @@ const bundles = [
],
fbEntry: 'src/renderers/art/ReactARTFiberEntry',
hasteName: 'ReactARTFiber',
isRenderer: true,
moduleType: RENDERER,
label: 'art-fiber',
manglePropertiesOnProd: false,
name: 'react-art',
@@ -274,7 +284,7 @@ const bundles = [
'prop-types/checkPropTypes',
],
hasteName: 'ReactNativeFiber',
isRenderer: true,
moduleType: RENDERER,
label: 'native-fiber',
manglePropertiesOnProd: false,
name: 'react-native-renderer',
@@ -335,7 +345,7 @@ const bundles = [
externals: ['prop-types/checkPropTypes'],
fbEntry: 'src/renderers/testing/ReactTestRendererFiberEntry',
hasteName: 'ReactTestRendererFiber',
isRenderer: true,
moduleType: RENDERER,
label: 'test-fiber',
manglePropertiesOnProd: false,
name: 'react-test-renderer',
@@ -364,7 +374,7 @@ const bundles = [
],
fbEntry: 'src/renderers/testing/ReactShallowRendererEntry',
hasteName: 'ReactShallowRenderer',
isRenderer: true,
moduleType: RENDERER,
label: 'shallow-renderer',
manglePropertiesOnProd: false,
name: 'react-test-renderer/shallow',
@@ -389,7 +399,7 @@ const bundles = [
},
entry: 'src/renderers/noop/ReactNoopEntry',
externals: ['prop-types/checkPropTypes', 'jest-matchers'],
isRenderer: true,
moduleType: RENDERER,
label: 'noop-fiber',
manglePropertiesOnProd: false,
name: 'react-noop-renderer',
@@ -401,6 +411,32 @@ const bundles = [
'src/shared/**/*.js',
],
},
/******* React Reconciler *******/
{
babelOpts: babelOptsReact,
bundleTypes: [NODE_DEV, NODE_PROD],
config: {
destDir: 'build/',
globals: {
react: 'React',
},
moduleName: 'ReactReconciler',
sourceMap: false,
},
entry: 'src/renderers/shared/fiber/ReactFiberReconciler',
externals: ['react', 'prop-types/checkPropTypes'],
moduleType: RECONCILER,
label: 'react-reconciler',
manglePropertiesOnProd: false,
name: 'react-reconciler',
paths: [
'src/renderers/shared/**/*.js',
'src/ReactVersion.js',
'src/shared/**/*.js',
],
},
];
// Based on deep-freeze by substack (public domain)
@@ -423,5 +459,6 @@ deepFreeze(bundles);
module.exports = {
bundleTypes,
moduleTypes,
bundles,
};

View File

@@ -4,6 +4,7 @@ const resolve = require('path').resolve;
const basename = require('path').basename;
const sync = require('glob').sync;
const bundleTypes = require('./bundles').bundleTypes;
const moduleTypes = require('./bundles').moduleTypes;
const extractErrorCodes = require('../error-codes/extract-errors');
const exclude = [
@@ -21,6 +22,8 @@ const FB_PROD = bundleTypes.FB_PROD;
const RN_DEV = bundleTypes.RN_DEV;
const RN_PROD = bundleTypes.RN_PROD;
const ISOMORPHIC = moduleTypes.ISOMORPHIC;
const errorCodeOpts = {
errorMapFilePath: 'scripts/error-codes/codes.json',
};
@@ -87,7 +90,7 @@ function createModuleMap(paths, extractErrors, bundleType) {
return moduleMap;
}
function getNodeModules(bundleType, isRenderer) {
function getNodeModules(bundleType, moduleType) {
// rather than adding the rollup node resolve plugin,
// we can instead deal with the only node module that is used
// for UMD bundles - object-assign
@@ -97,9 +100,9 @@ function getNodeModules(bundleType, isRenderer) {
return {
// Bundle object-assign once in the isomorphic React, and then use
// that from the renderer UMD. Avoids bundling it in both UMDs.
'object-assign': isRenderer
? resolve('./scripts/rollup/shims/rollup/assign.js')
: resolve('./node_modules/object-assign/index.js'),
'object-assign': moduleType === ISOMORPHIC
? resolve('./node_modules/object-assign/index.js')
: resolve('./scripts/rollup/shims/rollup/assign.js'),
// include the ART package modules directly by aliasing them from node_modules
'art/modes/current': resolve('./node_modules/art/modes/current.js'),
'art/modes/fast-noSideEffects': resolve(
@@ -136,7 +139,7 @@ function ignoreReactNativeModules() {
];
}
function getExternalModules(externals, bundleType, isRenderer) {
function getExternalModules(externals, bundleType, moduleType) {
// external modules tell Rollup that we should not attempt
// to bundle these modules and instead treat them as
// external dependencies to the bundle. so for CJS bundles
@@ -144,11 +147,10 @@ function getExternalModules(externals, bundleType, isRenderer) {
// the top of the bundle. for UMD bundles this means having
// both a require and a global check for them
let externalModules = externals.slice();
switch (bundleType) {
case UMD_DEV:
case UMD_PROD:
if (isRenderer) {
if (moduleType !== ISOMORPHIC) {
externalModules.push('react');
}
break;
@@ -158,7 +160,7 @@ function getExternalModules(externals, bundleType, isRenderer) {
case RN_PROD:
fbjsModules.forEach(module => externalModules.push(module));
externalModules.push('object-assign');
if (isRenderer) {
if (moduleType !== ISOMORPHIC) {
externalModules.push('react');
}
break;
@@ -168,7 +170,7 @@ function getExternalModules(externals, bundleType, isRenderer) {
externalModules.push('object-assign');
externalModules.push('ReactCurrentOwner');
externalModules.push('lowPriorityWarning');
if (isRenderer) {
if (moduleType !== ISOMORPHIC) {
externalModules.push('React');
if (externalModules.indexOf('react-dom') > -1) {
externalModules.push('ReactDOM');
@@ -282,7 +284,7 @@ function replaceBundleStubModules(bundleModulesToStub) {
return stubbedModules;
}
function getAliases(paths, bundleType, isRenderer, extractErrors) {
function getAliases(paths, bundleType, moduleType, extractErrors) {
return Object.assign(
createModuleMap(
paths,
@@ -290,7 +292,7 @@ function getAliases(paths, bundleType, isRenderer, extractErrors) {
bundleType
),
getInternalModules(),
getNodeModules(bundleType, isRenderer),
getNodeModules(bundleType, moduleType),
getFbjsModuleAliases(bundleType)
);
}

View File

@@ -57,12 +57,12 @@
"gzip": 11028
},
"react-dom-unstable-native-dependencies.development.js (UMD_DEV)": {
"size": 86854,
"gzip": 21985
"size": 84930,
"gzip": 21288
},
"react-dom-unstable-native-dependencies.production.min.js (UMD_PROD)": {
"size": 15251,
"gzip": 5010
"size": 14441,
"gzip": 4650
},
"react-dom-unstable-native-dependencies.development.js (NODE_DEV)": {
"size": 80723,
@@ -207,6 +207,14 @@
"react-dom-test-utils.production.min.js (NODE_PROD)": {
"size": 11608,
"gzip": 4241
},
"react-reconciler.development.js (NODE_DEV)": {
"size": 279927,
"gzip": 58576
},
"react-reconciler.production.min.js (NODE_PROD)": {
"size": 38630,
"gzip": 12165
}
}
}