How we built Twitter Lite

Tweet

We’re excited to introduce you to Twitter Lite, a Progressive Web App that is available at mobile.twitter.com. Twitter Lite is fast and responsive, uses less data, takes up less storage space, and supports push notifications and offline use in modern browsers. The web is becoming a platform for lightweight apps that can be accessed on-demand, installed without friction, and incrementally updated. Over the last year we’ve adopted new, open web APIs and significantly improved the performance and user experience.

Architecture overview

Twitter Lite is a client-side JavaScript application and a small, simple Node.js server. The server handles user authentication, constructs the initial state of the app, and renders the initial HTML application shell. Once loaded in the browser, the app requests data directly from the Twitter API. The simplicity of this basic architecture has helped us deliver exceptional service reliability and efficiency at scale – Twitter Lite an order of magnitude less expensive to run than our server-rendered desktop website.

The client-side JavaScript application is developed, built, and tested with many open source libraries including React, Redux, Normalizr, Globalize, Babel, Webpack, Jest, WebdriverIO, and Yarn. Relying on established open source software has allowed us to spend more time improving the user-experience, increasing our iteration speed, and working on Twitter-specific problems such as processing and manipulating Timeline and Tweet data.

We write modern JavaScript (ES2015 and beyond) that is compiled with Babel and bundled with Webpack. API response data is first processed by Normalizr – which allows us to de-duplicate items and transform data into more efficient forms – before being sent to various Redux modules used for fetching, storing, and retrieving remote and local data. The UI is implemented with several hundred React components that do everything from render text to manage virtual lists, lazy load modules, and defer rendering. Twitter Lite supports 42 languages, and we use Globalize to deliver localized numbers, dates, and messages.

Designing for performance

Hundreds of millions of people visit mobile.twitter.com every month. We want Twitter Lite to be the best way to use Twitter when your connectivity is slow, unreliable, limited, or expensive. We have been able to achieve speed and reliability through a series of incremental performance improvements known as the PRPL pattern and by using the new capabilities of modern browsers on Android (e.g., Google Chrome) which include Service Worker, IndexedDB, Web App Install Banners, and Web Push Notifications.

Availability

Twitter Lite is network resilient. To reach every person on the planet, we need to reach people on slow and unreliable networks. When available, we use a Service Worker to enable temporary offline browsing and near-instant loading on repeat visits, regardless of the network conditions. The Service Worker caches the HTML application shell and static assets, along with a few popular emoji. And when scripts or data fail to load we provide “Retry” buttons to help users recover from the failure. All together, these changes improve reliability and contribute to significantly faster loading and startup times on repeat visits.

Progressive loading

Twitter Lite is interactive in under 5 seconds over 3G on most devices. Most of the world is using 2G or 3G networks; a fast initial experience is essential. Over the last 3 months we’ve reduced average load times by over 30% and 99th percentile time-to-interactive latency by over 25%. To achieve this, the app streams the initial HTML response to the browser, sending instructions to preload critical resources while the server constructs the initial app state. Using webpack, the app’s scripts are broken up into granular pieces and loaded on demand. This means that the initial load only requires resources needed for the visible screen. (When available, a Service Worker will precache additional resources and allow instant future navigations to other screens.) These changes allow us to progressive load the app so people can sooner consume and create Tweets.

Rendering

Twitter Lite breaks up expensive rendering work. Although we’ve taken care to optimize the rendering of our components, the Tweet is a complex composite component, and rendering infinite lists of Tweets requires additional performance considerations. We implemented our own virtualized list component; it only renders the content visible within the viewport, incrementally renders items over multiple frames using the requestAnimationFrame API, and preserves scroll position across screens. Further improvements to perceived performance were possible by deferring non-critical rendering to idle periods using the requestIdleCallback API.

Data usage

Twitter Lite reduces data use by default, serving smaller media resources and relying on cached data. We’ve optimized images to reduce their impact on data usage by as much as 40% as you scroll through a timeline. “Data saver” mode further reduces data usage by replacing images in Tweets and Direct Messages with a small, blurred preview. A HEAD request for the image helps us to display its size alongside a button to load it on demand. And at 1-3% the size of our native apps, Twitter Lite requires only a fraction of the device storage space.

Design systems and iteration speed

Increasing our capability to iterate quickly helps us to maintain a high quality user experience. We rely heavily on flexbox for layout and a small, fixed number of colors, font sizes, and lengths. Twitter Lite is built from a component-based responsive design system that allows the app to fit any form factor. Working with UI components has helped us established a shared vocabulary between design and engineering that encourages rapid iteration and reuse of existing building blocks. Some of our most complex features, such as mixed-content Timelines, can be created from as little as 30 lines of code configuring and connecting a Redux module to a React component.

Looking ahead

Building a fast web app at this scale, and keeping it fast, is a significant challenge involving design, product, and engineering from multiple teams at Twitter. We’re excited about our progress and experimenting with HTTP/2, GraphQL, and alternative compression formats to further reduce load times and data consumption. In the coming months, we’ll be shipping more improvements to the accessibility, safety, design, functionality, and performance of Twitter Lite.