The Airbnb Tech Blog

Creative engineers and data scientists building a world where you can belong anywhere. http://airbnb.io

React Performance Fixes on Airbnb Listing Pages

Joe Lencioni
The Airbnb Tech Blog
11 min readDec 5, 2017

--

Airbnb has some incredible listings in Cuba…and also a corner of the office inspired by Habana Vieja
airbnb.com listing detail page: https://www.airbnb.com/rooms/8357

Methodology

Initial render

webpack-internal:///36:36 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) ut-placeholder-label screen-reader-only"
(server) ut-placeholder-label" data-reactid="628"
~/airbnb ❯❯❯ ag ut-placeholder-label
app/assets/javascripts/components/o2/PlaceholderLabel.jsx
85: 'input-placeholder-label': true,
app/assets/stylesheets/p1/search/_SearchForm.scss
77: .input-placeholder-label {
321:.input-placeholder-label,
spec/javascripts/components/o2/PlaceholderLabel_spec.jsx
25: const placeholderContainer = wrapper.find('.input-placeholder-label');
101.63 ms spent re-rendering Redux-connected SummaryContainer
export default class SummaryIconRow extends React.Component {
...
}
export default class SummaryIconRow extends React.PureComponent {
...
}
103.15 ms spent re-rendering BookIt
8.52 ms spent re-rendering BookIt

Scrolling around

Really bad scrolling performance on Airbnb listing pages before any fixes
Slightly improved scrolling performance of Airbnb listing pages after some fixes
58.80 ms spent re-rendering StickyNavigationController
const anchors = React.Children.map(children, (child, index) => {      
return React.cloneElement(child, {
selected: activeAnchorIndex === index,
onPress(event) { onAnchorPress(index, event); },
});
});
const anchors = React.Children.map(children, (child, index) => {      
return React.cloneElement(child, {
selected: activeAnchorIndex === index,
index,
onPress: this.handlePress,
});
});
class NavigationAnchor extends React.Component {
constructor(props) {
super(props);
this.handlePress = this.handlePress.bind(this);
}
handlePress(event) {
this.props.onPress(this.props.index, event);
}
render() {
...
}
}
32.85 ms spent re-rendering StickyNavigationController
18.45 ms spent in _handleScroll
this.state = { inViewport: false };
this.inViewport = false;
1.16ms spent in scroll event handler
32.24 ms spent in AboutThisListingContainer re-render
render() {
...
const finalExperiments = {
...experiments,
...this.state.experiments,
};
return (
<WrappedComponent
{...otherProps}
experiments={finalExperiments}
/>
);
}
const getExperiments = createSelector(
({ experimentsFromProps }) => experimentsFromProps,
({ experimentsFromState }) => experimentsFromState,
(experimentsFromProps, experimentsFromState) => ({
...experimentsFromProps,
...experimentsFromState,
}),
);
...render() {
...
const finalExperiments = getExperiments({
experimentsFromProps: experiments,
experimentsFromState: this.state.experiments,
});
return (
<WrappedComponent
{...otherProps}
experiments={finalExperiments}
/>
);
}
function getFilteredAmenities(amenities) {
return amenities.filter(shouldDisplayAmenity);
}
Improved scrolling performance on Airbnb listing pages after these fixes

Clicking on things

42.38 ms re-rendering ReviewsContent
12.38 ms re-rendering ReviewsContent

Typing stuff

61.32 ms re-rendering Redux-connected ReviewsContainer
3.18 ms re-rendering ReviewsHeader

What did we learn?

--

--

The Airbnb Tech Blog
The Airbnb Tech Blog

Published in The Airbnb Tech Blog

Creative engineers and data scientists building a world where you can belong anywhere. http://airbnb.io

Joe Lencioni
Joe Lencioni

Written by Joe Lencioni

Founder and CTO at Happo screenshot testing (prev Airbnb). Making web since the 90s. he/him dad in Minnesota.