Building Flipkart Lite: A Progressive Web App

There have been a few turning points in the history of the web platform that radically changed how web apps were built, deployed and experienced. Ajax was one such pivot that led to a profound shift in web engineering and user experience. It allowed web applications to be responsive enough to challenge the conventional desktop apps. The same shift is now underway on mobile where web apps can finally be as performant, immersive, and engaging as native apps.

With the adoption of Extensible Web Manifesto browser vendors started introducing new low-level APIs based on the feedback from developers. Low-level APIs enable developers to build new libraries, frameworks and tools on top of them instead of having to rely on high-level generalised APIs. The advent of these APIs brings unprecedented capabilities to the web.

We at Flipkart decided to live on this bleeding edge and build a truly powerful and technically advanced web app while working to further evolve these APIs.

Here’s a look at how we’ve created an extremely Immersive, Engaging and a High-Performance Secure app.

Immersive

Web Apps have an instant and always updated distribution. However, there are too many variables with network connectivity that impede us from a providing a seamless experience. There have been multiple attempts at enabling offline web apps in the past, such as AppCache and using LocalStorage/ IndexedDB. However, these solutions failed to model complex offline use cases described below, making it painful to develop and debug issues. Service Workers replace these approaches by providing a scriptable network proxy in the browser that allows you to handle the requests programmatically. Service Workers can be scripted to intercept every network request and serve a response from cache even when the user is offline.

Offline Experience

We chose to use SW-Toolbox, a Service Workers wrapper library that enables using simple patterns such as NetworkFirst, CacheFirst or NetworkOnly. SW-Toolbox provides an LRU cache used in our app for storing previous search results on the browse page and last few visited product pages. The toolbox also has TTL-based cache invalidation mechanism that we use to purge out of date content. Service Workers provide low-level scriptable primitives that make this possible.

SW-Toolbox example

Making the right solution work was as hard as devising it. We faced a wide spectrum of challenges from implementation issues to dev tooling bugs. We are collaborating with browser vendors to resolve these challenges and are actively contributing to SW-Toolbox.

One significant learning that emerged from our use of Service Workers was to build a “kill switch”. It is easy to end up with bugs in Service Workers and stale responses. Having a reliable mechanism to purge all caches has helped us to be proactively ready for any contingencies or surprises.

Another cornerstone of a truly immersive experience is a fullscreen, standalone experience launched right from the home screen. This is what the Add to Home Screen (A2HS) prompt allows us to do. When the user chooses to add to home screen, the browser creates a high-quality icon on the home screen based on the metadata in the Web Manifest. The A2HS prompt is shown automatically to the user based on a heuristic that is specific to each browser. On Chrome, if the user has visited the site twice within a defined period, the prompt will trigger. In the newer Chrome versions, the prompt can be invoked programmatically.

While the heuristic is indispensable to prevent spam on the web platform, we felt it was too conservative and convinced the Chrome team to tweak the heuristic for more commonly occurring scenarios. Based on our feedback, experiments are underway by the Chrome team to shorten the required delay between visits to the web app.

Pro Tip: While developing for Add To Home Screen, you can disable the heuristic on Chrome by visiting the chrome://flags and enabling Bypass user engagement checks

The latest version of Chrome supports the generation of a splash screen that shows up when the web app is launched from the home screen. It seamlessly fades in on the first paint of the app. This radically improves the launch experience and perceived performance.

Splash Screen

Engaging

Being able to re-engage with our users on the web has always been a challenge. With the introduction of the Web Push API, we now have the capability to send Push Notifications to our users, even when the browser is closed. This is possible because Service Workers can be restarted even when no tab is open, allowing push events to deliver notifications to the users.

High Performance

Our focus was on two primary areas: Network and Rendering Performance. The app architecture is simply static HTML shells + API data. We pre-render the shells on server side during build time with critical CSS inlined. This leads to a quick first paint without waiting on CSS or JS to load. Once the async JS is loaded, API calls for data are made which fill in the content of the shells. With Service Workers, data consumption from the network can be reduced significantly by responding to requests from the cache. HTML shells are always served from the cache first and updated asynchronously in the background. This approach also helped in reducing the dependency on the network strength and eliminating all latencies on a repeat visit. On the client-side, Flipkart Lite is Single Page App based on React.js and our in-house Flux implementation Phrontend.js which is has been open sourced.

Rendering Performance has always been a challenge for the web. We identified significant improvements in performance when GPU handled rasterization compared to CPU. Hence, we decided to leverage GPU rasterization on Chrome (Project Ganesh), by including the required meta tag in our HTML.

FPS Meter — GPU raster: On

The key is to avoid SVGs in performance-critical paths. SVGs being vectors, cannot leverage the same GPU optimizations currently. However, on latest Chrome versions this should be fixed. On the other hand, we have carefully balanced the right number of GPU-accelerated layers by measuring composition vs. paint costs. Thirdly, we’re using GPU friendly animations namely Opacity and Transform transitions.

Profiling on various mobile devices using Chrome Dev Tools Timeline panel and Chrome Tracing, helped us identify multiple bottlenecks and optimization paths. This helped us make the best of each frame during an animation and reach our 60fps target. We use the RAIL model for our performance budgets and strive to match and exceed expectations on each of the metrics.

Secure

End-to-end HTTPS encryption ensures a secure browsing session for our users. We also use Content Security Policy as an added layer of security against XSS and data injection attacks.

All of this put together, manifested into a stellar experience for our users. It’s been a remarkable journey building this web app, working with browser vendors and pushing the limits of web platform on mobile. The revolution is here and its time for developers to start leveraging these incredible new capabilities. The web is truly what you make of it, and we have only just begun.

Introducing the Flipkart Lite Team — Abhinav Rastogi, Boopathi Rajaa, Jai Santhosh, Abinash Mohapatra, Epuri, Karan Peri, Bharat KS, Baisampayan Saha, Mohammed Bilal, Ayesha Rana, Suvonil Chatterjee, Akshay Rajwade and Amar Nagaram


Special thanks to Alex Russell, Paul Kinlan, Joe Marini, Smriti Advani, and Amar Nagaram, for their review and invaluable feedback on this post.