mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Log top-level renders with console.time
Behind a flag.
This commit is contained in:
@@ -19,6 +19,7 @@ var ReactDOMComponentTree = require('ReactDOMComponentTree');
|
||||
var ReactDOMContainerInfo = require('ReactDOMContainerInfo');
|
||||
var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
|
||||
var ReactElement = require('ReactElement');
|
||||
var ReactFeatureFlags = require('ReactFeatureFlags');
|
||||
var ReactMarkupChecksum = require('ReactMarkupChecksum');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
var ReactReconciler = require('ReactReconciler');
|
||||
@@ -96,6 +97,17 @@ function mountComponentIntoNode(
|
||||
shouldReuseMarkup,
|
||||
context
|
||||
) {
|
||||
var markerName;
|
||||
if (ReactFeatureFlags.logTopLevelRenders) {
|
||||
var wrappedElement = wrapperInstance._currentElement.props;
|
||||
var type = wrappedElement.type;
|
||||
markerName = 'React mount: ' + (
|
||||
typeof type === 'string' ? type :
|
||||
type.displayName || type.name
|
||||
);
|
||||
console.time(markerName);
|
||||
}
|
||||
|
||||
var markup = ReactReconciler.mountComponent(
|
||||
wrapperInstance,
|
||||
transaction,
|
||||
@@ -103,6 +115,11 @@ function mountComponentIntoNode(
|
||||
ReactDOMContainerInfo(wrapperInstance, container),
|
||||
context
|
||||
);
|
||||
|
||||
if (markerName) {
|
||||
console.timeEnd(markerName);
|
||||
}
|
||||
|
||||
wrapperInstance._renderedComponent._topLevelWrapper = wrapperInstance;
|
||||
ReactMount._mountImageIntoNode(
|
||||
markup,
|
||||
|
||||
@@ -279,4 +279,35 @@ describe('ReactMount', function() {
|
||||
ReactDOM.unmountComponentAtNode(container);
|
||||
expect(Object.keys(ReactMount._instancesByReactRootID).length).toBe(1);
|
||||
});
|
||||
|
||||
it('marks top-level mounts', function() {
|
||||
var ReactFeatureFlags = require('ReactFeatureFlags');
|
||||
|
||||
var Foo = React.createClass({
|
||||
render: function() {
|
||||
return <Bar />;
|
||||
},
|
||||
});
|
||||
|
||||
var Bar = React.createClass({
|
||||
render: function() {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
|
||||
try {
|
||||
ReactFeatureFlags.logTopLevelRenders = true;
|
||||
spyOn(console, 'time');
|
||||
spyOn(console, 'timeEnd');
|
||||
|
||||
ReactTestUtils.renderIntoDocument(<Foo />);
|
||||
|
||||
expect(console.time.argsForCall.length).toBe(1);
|
||||
expect(console.time.argsForCall[0][0]).toBe('React mount: Foo');
|
||||
expect(console.timeEnd.argsForCall.length).toBe(1);
|
||||
expect(console.timeEnd.argsForCall[0][0]).toBe('React mount: Foo');
|
||||
} finally {
|
||||
ReactFeatureFlags.logTopLevelRenders = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
var CallbackQueue = require('CallbackQueue');
|
||||
var PooledClass = require('PooledClass');
|
||||
var ReactFeatureFlags = require('ReactFeatureFlags');
|
||||
var ReactPerf = require('ReactPerf');
|
||||
var ReactReconciler = require('ReactReconciler');
|
||||
var Transaction = require('Transaction');
|
||||
@@ -149,11 +150,29 @@ function runBatchedUpdates(transaction) {
|
||||
var callbacks = component._pendingCallbacks;
|
||||
component._pendingCallbacks = null;
|
||||
|
||||
var markerName;
|
||||
if (ReactFeatureFlags.logTopLevelRenders) {
|
||||
var namedComponent = component;
|
||||
// Duck type TopLevelWrapper. This is probably always true.
|
||||
if (
|
||||
component._currentElement.props ===
|
||||
component._renderedComponent._currentElement
|
||||
) {
|
||||
namedComponent = component._renderedComponent;
|
||||
}
|
||||
markerName = 'React update: ' + namedComponent.getName();
|
||||
console.time(markerName);
|
||||
}
|
||||
|
||||
ReactReconciler.performUpdateIfNecessary(
|
||||
component,
|
||||
transaction.reconcileTransaction
|
||||
);
|
||||
|
||||
if (markerName) {
|
||||
console.timeEnd(markerName);
|
||||
}
|
||||
|
||||
if (callbacks) {
|
||||
for (var j = 0; j < callbacks.length; j++) {
|
||||
transaction.callbackQueue.enqueue(
|
||||
|
||||
@@ -904,4 +904,37 @@ describe('ReactUpdates', function() {
|
||||
expect(renderCount).toBe(1);
|
||||
});
|
||||
|
||||
it('marks top-level updates', function() {
|
||||
var ReactFeatureFlags = require('ReactFeatureFlags');
|
||||
|
||||
var Foo = React.createClass({
|
||||
render: function() {
|
||||
return <Bar />;
|
||||
},
|
||||
});
|
||||
|
||||
var Bar = React.createClass({
|
||||
render: function() {
|
||||
return <div />;
|
||||
},
|
||||
});
|
||||
|
||||
var container = document.createElement('div');
|
||||
ReactDOM.render(<Foo />, container);
|
||||
|
||||
try {
|
||||
ReactFeatureFlags.logTopLevelRenders = true;
|
||||
spyOn(console, 'time');
|
||||
spyOn(console, 'timeEnd');
|
||||
|
||||
ReactDOM.render(<Foo />, container);
|
||||
|
||||
expect(console.time.argsForCall.length).toBe(1);
|
||||
expect(console.time.argsForCall[0][0]).toBe('React update: Foo');
|
||||
expect(console.timeEnd.argsForCall.length).toBe(1);
|
||||
expect(console.timeEnd.argsForCall[0][0]).toBe('React update: Foo');
|
||||
} finally {
|
||||
ReactFeatureFlags.logTopLevelRenders = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule ReactFeatureFlags
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var ReactFeatureFlags = {
|
||||
// When true, call console.time() before and .timeEnd() after each top-level
|
||||
// render (both initial renders and updates). Useful when looking at prod-mode
|
||||
// timeline profiles in Chrome, for example.
|
||||
logTopLevelRenders: false,
|
||||
};
|
||||
|
||||
module.exports = ReactFeatureFlags;
|
||||
Reference in New Issue
Block a user