Bug 1253781 - Better perf with pure render. r=gl
There are few easy wins that greatly improve our perf with React:
* Add the PureRenderMixin to pure components that always render the same thing
given the same props and state. This implements React's shouldComponentUpdate
as a shallow equality check of the props and state, so render() will be
skipped if they match the previous values.
* Change action dispatch functions so they are only created once instead of on
each render(). If an outer component creates new functions for each render()
call, then the PureRenderMixin equality check fails for only the new function
instances, even though no data has changed.
MozReview-Commit-ID: D96X048nEF4
--- a/devtools/client/responsive.html/app.js
+++ b/devtools/client/responsive.html/app.js
@@ -18,36 +18,47 @@ let App = createClass({
displayName: "App",
propTypes: {
location: Types.location.isRequired,
viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
onExit: PropTypes.func.isRequired,
},
+ onRotateViewport(id) {
+ this.props.dispatch(rotateViewport(id));
+ },
+
+ onResizeViewport(id, width, height) {
+ this.props.dispatch(resizeViewport(id, width, height));
+ },
+
render() {
let {
- dispatch,
location,
viewports,
onExit,
} = this.props;
+ let {
+ onRotateViewport,
+ onResizeViewport,
+ } = this;
+
return dom.div(
{
id: "app",
},
GlobalToolbar({
onExit,
}),
Viewports({
location,
viewports,
- onRotateViewport: id => dispatch(rotateViewport(id)),
- onResizeViewport: (id, width, height) =>
- dispatch(resizeViewport(id, width, height)),
+ onRotateViewport,
+ onResizeViewport,
})
);
},
});
module.exports = connect(state => state)(App);
--- a/devtools/client/responsive.html/components/browser.js
+++ b/devtools/client/responsive.html/components/browser.js
@@ -1,23 +1,25 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
require("devtools/client/shared/vendor/react");
const Types = require("../types");
module.exports = createClass({
displayName: "Browser",
+ mixins: [ addons.PureRenderMixin ],
+
propTypes: {
location: Types.location.isRequired,
width: Types.viewport.width.isRequired,
height: Types.viewport.height.isRequired,
isResizing: PropTypes.bool.isRequired,
},
render() {
--- a/devtools/client/responsive.html/components/global-toolbar.js
+++ b/devtools/client/responsive.html/components/global-toolbar.js
@@ -1,22 +1,24 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { getStr } = require("./utils/l10n");
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
require("devtools/client/shared/vendor/react");
module.exports = createClass({
displayName: "GlobalToolbar",
+ mixins: [ addons.PureRenderMixin ],
+
propTypes: {
onExit: PropTypes.func.isRequired,
},
render() {
let {
onExit,
} = this.props;
--- a/devtools/client/responsive.html/components/viewport-toolbar.js
+++ b/devtools/client/responsive.html/components/viewport-toolbar.js
@@ -1,21 +1,23 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
require("devtools/client/shared/vendor/react");
module.exports = createClass({
displayName: "ViewportToolbar",
+ mixins: [ addons.PureRenderMixin ],
+
propTypes: {
onRotateViewport: PropTypes.func.isRequired,
},
render() {
let {
onRotateViewport,
} = this.props;
--- a/devtools/client/responsive.html/components/viewport.js
+++ b/devtools/client/responsive.html/components/viewport.js
@@ -17,23 +17,44 @@ module.exports = createClass({
propTypes: {
location: Types.location.isRequired,
viewport: PropTypes.shape(Types.viewport).isRequired,
onResizeViewport: PropTypes.func.isRequired,
onRotateViewport: PropTypes.func.isRequired,
},
+ onResizeViewport(width, height) {
+ let {
+ viewport,
+ onResizeViewport,
+ } = this.props;
+
+ onResizeViewport(viewport.id, width, height);
+ },
+
+ onRotateViewport() {
+ let {
+ viewport,
+ onRotateViewport,
+ } = this.props;
+
+ onRotateViewport(viewport.id);
+ },
+
render() {
let {
location,
viewport,
- onResizeViewport,
+ } = this.props;
+
+ let {
onRotateViewport,
- } = this.props;
+ onResizeViewport,
+ } = this;
return dom.div(
{
className: "viewport",
},
ResizableViewport({
location,
viewport,
--- a/devtools/client/responsive.html/components/viewports.js
+++ b/devtools/client/responsive.html/components/viewports.js
@@ -33,17 +33,16 @@ module.exports = createClass({
{
id: "viewports",
},
viewports.map(viewport => {
return Viewport({
key: viewport.id,
location,
viewport,
- onResizeViewport: (width, height) =>
- onResizeViewport(viewport.id, width, height),
- onRotateViewport: () => onRotateViewport(viewport.id),
+ onResizeViewport,
+ onRotateViewport,
});
})
);
},
});