Performance Optimizations in Twitter Lite: Code Splitting, Rendering, Images, Redux, and Service Workers
This article explains how Twitter Lite, one of the world’s largest React.js PWAs, eliminates a range of performance bottlenecks through route‑based code splitting, avoiding frame‑dropping functions, using smaller images, optimizing React lifecycle methods, improving Redux updates, and leveraging Service Workers for faster asset delivery.
The article demonstrates practical techniques used in Twitter Lite to improve web‑app performance, targeting both common and obscure bottlenecks.
1. Browser‑side optimizations
Route‑based code splitting was introduced via Webpack’s CommonsChunkPlugin to reduce the initial bundle from several megabytes to three independent chunks, cutting the main bundle load time from 5 s to 3 s on a simulated 3G connection.
const plugins = [
// extract vendor and webpack's module manifest
new webpack.optimize.CommonsChunkPlugin({
names: [ 'vendor', 'manifest' ],
minChunks: Infinity
}),
// extract common modules from all the chunks (requires no 'name' property)
new webpack.optimize.CommonsChunkPlugin({
async: true,
children: true,
minChunks: 4
})
];Functions that cause frame drops were removed, and a custom VirtualScroller component was built to render only visible tweet fragments, eliminating costly height calculations.
Image sizes were reduced, decreasing decode time from ~300 ms per large image to ~16 ms for a small image, which translates to a drop from 18 frames to a single frame for rendering.
2. React optimizations
Using shouldComponentUpdate prevented unnecessary re‑renders of entire conversation trees when a tweet was liked, saving roughly 0.1 s per interaction.
Heavy computations were moved from componentWillMount to componentDidMount , allowing the UI to become interactive sooner.
Dangerously setting inner HTML for SVG icons was replaced with proper JSX components, cutting SVG mount time by about 60 %.
A higher‑order component deferComponentRender was introduced to delay rendering of expensive components until two animation frames had passed:
import hoistStatics from 'hoist-non-react-statics';
import React from 'react';
export default function deferComponentRender(WrappedComponent) {
class DeferredRenderWrapper extends React.Component {
constructor(props, context) {
super(props, context);
this.state = { shouldRender: false };
}
componentDidMount() {
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => this.setState({ shouldRender: true }));
});
}
render() {
return this.state.shouldRender ?
: null;
}
}
return hoistStatics(DeferredRenderWrapper, WrappedComponent);
}3. Redux optimizations
Frequent state updates from controlled inputs were throttled by keeping draft tweet text in component state, reducing key‑press latency on low‑end devices by over 50 %.
Batching multiple Redux actions into a single dispatch cut render counts roughly in half, as shown by Chrome React Perf screenshots.
4. Service Worker strategies
Pre‑caching assets with Service Workers reduced page load on a 3G network from ~6 s to ~1.5 s (≈75 % improvement). Delaying Service Worker registration until after critical API, CSS, and image requests prevented it from blocking the browser’s concurrent request limit.
Overall, the article lists a collection of incremental yet measurable performance improvements that together make Twitter Lite a fast, responsive Progressive Web App.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.