Building Flipkart Ads PWA - The Journey

October 5, 2022 | 8:40 PM - 9:00 PM (UTC)

  1. Proposition - why build a mobile client for Flipkart Ads

    Flipkart Ads, built back in 2019, mostly functions as a Desktop application till date. With our increasing user base, users were inclined to operate ads on mobile form factor as well, thus starting our journey of building the Flipkart Ads platform for Mobile.

  2. How did we arrive at PWA

    Being web developers the team was quite equipped with skills related to web frameworks and technologies. Web has come quite far in providing great experiences especially on mobile. Combining this with the ease of use and reach (cross platform) of web we eventually decided to build our Ads platform for mobile as a PWA

  3. We wanted to provide the best experience to our users and thus our major areas of focus were

3.1 Offline first

We wanted our application to be network resilient and function under all situations. Starting off with an offline first approach helped in achieving that.

Our application uses a tweaked version of StaleWhileRevalidate Strategy which ensures that the application loads instantly provided the data is available in cache, but resolving with updated data by consulting with network thereafter

3.2 Richer Install

UX for installation for PWA has received great overall for browsers like chrome (a very large portion of our user base), thus allowing us to provide an experience that truly mimics an app install

Timing is critical when it comes to installation, thus having the capability to decide when to trigger the installation helped us in being less intrusive for the user and only asking when they have spent sufficient time in the application.

3.3 Performance

Our application has a shell content architecture where some portion of the shell is Server Side Rendered and upon rendering, the client takes over with updating the data

We define our performance under two categories

3.3.1 Load time Performance - mostly looks at load performance and is mostly defined by core web vitals metrics

3.3.2 Run time Performance - looks at the performance while the user is using the application, this includes performance like scrolls, animations, api latencies, page to page navigations etc.

Since our application is route chunked, to provide better performance during page to page navigation, we maintain a graph that defines the set of associated (secondary) routes for the main route. These secondary routes are prefetched while the user is surfing on the main route.

Correctness with performance is one of the top priorities for our application. Access control is one of the defining pillars for our application. The fact the shell is also cached, our PWA ensures that access control information is always up-to-date. Thus we aren’t limited only to prefetching static assets but we also make a high priority api prefetch request to get the updated access control information this is mostly utilized in repeat visits when the shell is served from the cache

  1. Infra and arch reuse

The Server side was already hosted on a graphql service that helped us in making flexible queries for each user agent (desktop/mobile). The PWA, hosted as a micro frontend, mostly piggybacks on the already existing infrastructure for authentication and authorization built for the desktop application. We define Access Controls for both url routes as well as api routes. For ex: 1. URL based access control could be defined like: <Route path=”campaigns” component={Campaigns} roles={[“Admin”]} />

2. Api authorization is implemented using graphql directives. For e.g.: type Query { getData: Data @authorization(roles: [“Admin”]) }

  1. Service Worker and Responsibilities

Service Worker is responsible for caching both the shell and the data, since we use POST Http verb for graphql requests our service worker basically handles the conversion while caching the responses One of the biggest challenges with caching is cache eviction, we use workbox for defining and implementing the service worker this allows us to provide more nuanced controls like time based expiration for Cache entries.

Since we use tweaked version of StaleWhileRevalidate Strategy the plugin system and extensible strategy system helped in achieving that

Ex Strategy: class StaleWhileRevalidateForPost extends StaleWhileRevalidate { constructor(options) { this.super(options); }

_handle(request, handler, …) { // Process the request } }

Ex Plugin: export const CacheFetchReportPlugin = { // listen to certain lifecycle updates }

Our Application follows the SemVar versioning system and this allows us to define how the application should react to the version changes, ex: minor, moderate or breaking changes. The SemVar Version is also used to define the kill switch for the service worker, in case something goes wrong wrt persistent caching Basically Service worker maintains the local version of the application and if the changes wrt to the remote version are breaking it ensures that the relevant caches are cleared

  1. Things going ahead

  2. How we can use Http Early Hints for our PWA

  3. Implementing Push Notification to send communication to our users

  • Abinash Mohapatra

    I love JS, Sneakers and bikes.

    I am Abinash, working on Ads Platform team, ex Flipkart Lite @Flipkart. I talk about GraphQL, PWA, Performance, Animations and Sneakers.