 So good afternoon, everyone. So I think exciting day so far. And there are so many wonderful talk. I've been here since morning and listen to love talking about the security. And also Rahul talking about the complete front-end architecture, a lot of optimization they have done, the micro front-ends. And then Mohit realized us that the performance are building for one side of the community is not the only responsibility what we carry. We have a responsibility towards other people or other customer as well. And Lena talked about the micro front-ends are not only way to think about there are systems which can be done beautifully or can be worked beautifully using monolithic. And so my talk is more about building a high-performance mobile-first web applications. And before I begin, let me introduce myself. So I'm Upendra and I lead a web platform for Mentra and Jabang both. And I also lead some of the backend functions for Mentra and Jabang both. So let me walk you through with the agenda. So for any problem you saw, so first you should know the problem. And that's where I'm going to talk about the defining the problem, what we used to have in Jabang mobile experience. The next will be via PWA. There is a lot of talk about the PWA in recent times and a lot of companies has started building PWA. They have made a lovely PWA and I'm going to talk about why we decided to build a PWA. So next is early decisions and technology choices we made. So I'll walk you through the sum of the decision-making factors in our PWA implementation and the overall consumer experience. Implementation details and relations we learned. So I'll go through the, I'll deep dive basically all the details about the implementation and some of the mistakes we made and how we learned from that. And the last thing which will be more about accepting performance in the organization as a first-class citizen, how we started thinking about the performance as a go-to strategy for every release which goes to the production. So let's talk about the problem statement. So mobile traffic was increasing. I think this is nothing new to the community or I guess in past three, four years we have more mobile user in India than typical people who have computers, right? So this was a trend across the technology. Suboptimal performance on mobile, this was definitely a problem. Once you build a software and once it gets old you always have this suboptimal performance. One of the key factor of having this poor performance was desktop first design. I think when we built a new web in back in 2015 so that was a approach we took which was desktop first design and a lot of components we implemented which was mean to be for the desktop user and we carried those into mobile application. There are components which was not primarily even required for the mobile web. It was actually there in the web pages and that was creating a lot of performance bottleneck. Outdated UX, so this was another problem in what was good or what was very user friendly in back in 2015 was no longer was good enough for the consumer to engage. And so these are the four fundamental problems what we have seen in our application and today majorly I'm going to cover about the performance optimization what we did for the, when we build a Jabong PWA. So why we need a PWA? I guess one of the core responsibility for us being in the consumer domain which should allow or empower our customer to choose what platform they want to use rather than we are asking them to come to the mobile app or mobile web or desktop. And this was the go-to strategy about thinking about the optimizing the user experience and PWA is a term which is primarily for the user experience, right? All the capabilities PWA provides which is maybe you can think about having the app icon on your mobile phone or in desktop this is more about the user experience engaging user experience. That's what that's what was the thinking behind building a PWA, right? And this was the tagline which is more about the fast integrated reliable engaging user experience across the platform and any kind of a network condition, right? Be it slow 3G or a fast 3G or 4 3G or it will be a web app or desktop. So some of the early decisions, right? I think Arvind covered beautifully about the role of the people building any of the best consumer product, right? And how their startup being able to produce some of the good quality product with very lean team, right? And so that's where the people are very important when you start or when you think about any product. So having the right people for the right job with the right skills and the right mindset is very important. And one of the very fundamental thing when you build a product. So this is more about not about the code you write. This is more about the problem you solve and the technology you use to that solve that particular problem. And that's where the people mindset is very important. They're focusing more on the solving problem and using technology as a tool. Domain knowledge, customer behavior, and so these are the two important aspect when you solve a problem because once you understand more about the problem you understand your customer. You know the domain you are operating in then you would be able to take the right decisions. And this was one of the key factor when we started thinking about the design and the architecture. And we made the decisions about the architecture and technologies based on the domain knowledge we had and the behavior we have seen about our users. Microfrontense, I think already one of the session Rahul has covered about the microfrontend importance. And that's where we, and Mintra by the way has implemented this like four or five years back and when the microfrontends were not very popular. So in Jabong when we started implementing PWA we have also gone ahead with the microfrontend approach. And this was also very critical and played a big part in terms of shipping entire product in six weeks. So from the typically any consumer domain product you might get a lot of pushback building anything on a mobile web especially, right? Because the apps are already doing a lot of a good job. So that's where we have got only six weeks to push ship this particular PWA to the production. And this particular approach actually helped us in terms of building, separating the concerns and we divided entire monolithic web application to three parts. One was the discovery where most of the product search happens basically you choose the right product and the payment and the order. So in this particular session or talk I'm mostly going to talk about the discovery microfrontend app which we optimize. And the next was based on the experience in the past, right? So we have been doing this react angular a lot of technology in the last past one year, right? And we have a good enough experience in terms of how to think about the building and application what could be the right bundle, JavaScript bundle size in order to get the optimal performance of the web application. So initial thought was just go ahead with the 20 KBs of JavaScript bundle size. Some more about the technology choices. So choosing react over react, primarily two reasons. One is its size which is a three KB and second was the consumer behavior. So in typical e-commerce and discovery kind of application. So most of the things what happens user lands on any of the landing pages. He clicks on any of the banner goes to the list page where the catalog user can see multiple products. Click on the one of the product and goes to the product. So this is the most flow which is related to a navigation of pages, right? So routing kind of an application. So that's where we don't really needed a lot of optimal algorithm in terms of having a virtual DOM and very fast processing diff algorithm. So that's where the technology choices choice becomes very clear that we really want to go ahead with the very optimal or very minimalistic JavaScript size library. Then we have started building and obviously the redux was another choice for the state management. We started building with the redux. Then we realized that when we are starting using redux we need to leverage the react implementation and also the router implementation of the redux. And again, this was not the original thought we had because we really wanted to keep the bundle size as low as 20 KBs. So then we thought there is not much benefit out of using redux. Then we thought redux is generally a philosophy, right? It's a guidelines how you can interact or how you can manage state. So that's where we thought of building in-house system to manage a state. And then we have a Rota library, which is I guess 700 bytes for the state management. And we named this one JS. So I'm not going to cover more about the one JS and then the third party libraries, right? So I think using third party libraries is again carrying a lot of burden, right? So it's like, I see this as a problem. Let's say one family has four people in their home, but they think about they might be having six people or maybe once in a while or twice in a year, their parents or their grandparents or there are a bunch of relatives visiting them in summers, right? So why should we buy a bus, right? Because when we need to go out with the entire family, we should have a bus because everybody will be in the same vehicle and we can interact with each other. And so exactly the same problem. Having a library which gives you a lot of features which you might not need, right? And so that's where we would have not thought about the 20 KBs probably we would have end up using a lot of frameworks or libraries. So that's where that's hot behind that only use the bytes, number of bytes you really want to use, right? So do not become greedy to use so many features in a library. So this is the idea behind that apart from using preact and preact router, we did not use any third party library at all. That's strategy. So by the first principle, it's if we go back to the fundamentals, right? A website is a collection of web pages and a web page is a composition of styles, your markup, few JavaScripts and interaction between the elements in the web page. If you could optimize these resources, a web page is constructed by, right? So if you could optimize rendering JavaScript, CSS, fonts and images, the entire website is already optimized and we have gone ahead with the same strategy. So let me walk you through with the implementation details now. So the first thing was rendering optimization. Again, the principle was very simple that put first things first, right? So everything which is required in terms of making your page interactive, having the content which is visual to the user and making the website meaningful for the user, only ship those resources. By the same lines, what we have done, we have used some of these methods like hybrid rendering, reduced initial payload, and lining critical CSS, mark the word critical because that's where this is very important. HTTP to server push, preloading critical resources. So these are the basic methods we used in order to achieve a very fast meaningful paint. So what is hybrid rendering? So if you break your page into a web page in two parts, right? First is above the fold and second is below the fold. So above the fold, which is user is interested below the fold, they might be interested they might not be interested. So by the principle putting first thing first, so the whole focus is on ensuring that we are rendering the first fold as soon as possible. So what we did, we applied server side rendering for the above the fold content. So everything from the image to the URL, everything was built in the server, right? So we are not resolving even the image URL in the browser for the first fold. And the second fold, it was mostly a reactive strategy. If user will scroll then probably we are going to show this otherwise we don't really need to bother because user don't have no intent of looking at the below the fold content. So this was the typical strategy and this is what I mean by rendering hybrid rendering. So let us look at the code basically and this is a exact code which is doing hybrid rendering. So you could see this on demand loading which is one simple utility we have created to just make any component to follow the reactive approach. And this is the below the fold content. So anything which you see above the widget group is basically the primary content we are more intended towards optimizing. So this is typically the implementation of hybrid rendering where you have below the fold only rendered when user scrolls are shown some intent towards looking at those content. So reduced payload again on the same line. I'll just add how we are fetching the resources which is required to render the below the fold content. If you see this clusters of resources there are dots small dots right. So these are the resources only fetched only requested when user scroll from the homepage. So this is how we reduce the initial payload in order to optimize the overall rendering performance also the reduced the payload of the webpage. And then critical CSS again the word critical is important. We need to identify the critical resources right. So usually we have when we build an architecture we have a tendency to think about style guides responsive designs adding a lot of reusable Java CSS in one common file. So for example, if I talk about bootstrap as a library or as a utility right. So it has a lot of CSS components. So you have a dialogue box you have a form field elements you have responsive nets responsive grids and accordion blah blah blah so many things right. So that's where it is like generic CSS in order to find the critical that means what is required in the webpage. So for us what was required the images right. Probably the grid probably some of the text we were showing so that's where what we did. So we just put only very critical part of it nothing else right. So if I talk about so it could be the heading or copy text or some of the element which was related for the having the responsive images kind of a thing right. So identifying the critical CSS is very important. Just we need not to be very greedy in terms of adding so many things from if we are coming from the old school of designing a webpage. So server push and multiplexing. So multiplexing comes by default if you enable HTTP2 in your application you will get the multiplexing. You can see that's the same connection ID being used to fetch the multiple resources right. So in HTTP2 if you create more connection once probably you can use for multiple requests. Server push was important for us because we were using CDN and Akamai. So Akamai has the feature to do this for us. So we offloaded this to Akamai. They have their own machine learning algorithm to find out all the critical resources required in a particular webpage. So they have this URL to resources mapping and by enabling that we were able to have all the critical resources pushed from the server even before it was asked right. So this was actually very helpful because I think this helped us in terms of improving the first meaningful pain. So next is preload critical request. So I think so again so because when we talk about the critical this is again very important to have your enough context about the finding the right critical resources. So apart from typical JavaScript CSS and fonts the most critical part was having this hero banner preloading because this actually helped us to preload the banner much earlier when it was requested. And this is when we have improved the first meaningful pen significantly. If you see this particular comparison before and after in slow 3G. So you could see the when the hero banner is getting rendered in after as compared to before. So this is the impact of actually realizing that you could even preload some of your the main content or the hero banner on your web application. So next is JavaScript optimization. I think I covered a lot in terms of optimizing the boot up time because reducing the payload or reducing the main bundle size help in terms of having a good or optimization towards the load time and the pass and compile time. So by optimizing the overall bundle size the first problem was solved. So next was more about the execution of JavaScript. Right, so then we focused more on the execution which could be the runtime execution or the execution when JavaScript loaded first. So code is splitting and after they're splitting pre-caching those resources which was required in the future maybe the route level components or the component level bundle itself is pre-caching with the service worker and then optimization of the runtime JavaScript which is a responsiveness of JavaScript how soon basically you respond to the scroll event or any kind of animation which triggered by the user action. So I'm just give you a very brief overview about the one JS here. So this is a typical one JS component look like in our code base. So these are all the pure functions, right? So you could see this is a pre-act code but it doesn't seem like a pre-act code, right? And this is a pure functional programming approach where we have created a small function which is a maintainable, which is testable, which is basically reusable. So these are the lifecycle methods. We just created a different name because internally we are going to bind this with the pre-act. These are the actions. You could simply think this is the action in Redux or any kind of a similar statement management library but these are the pure functions. Event handlers, typical JavaScript event handlers. These are the properties in state. So any component in our code base can subscribe to these properties and once these property gets changed or updated, the component is going to be re-rendered. So typical anything which is a react or pre-act world scenario and this is actually the component which is we can say the presentational component, right? Because all the markups, so because I think there was always a confusion or debate on the smart component or dumb component, presentational component or business components, right? So that's where we have actually segregated. So this looks completely neat and clean. There is no markup at all. Now all the markup, all the, so JSX which is all the HTML goes in there. So let's come back to the code splitting. This is the home page, only one JavaScript bundle which is initially it was 15.4 KB but later when we did some of the more polyfills and all it got a little bit more bytes but this was the home page rendering. It just clicks on any of the banner. We are loading all the resources which is required to render this particular page. Again, even if you are able to see that even the script related to Google Analytics and click streams or any kind of analytics or third party things also coming on as part of the route transaction. Again, pre-caching of these resources. So obviously when we are leveraging the capabilities of the browser we are ensuring that we are having all the critical resources pre-cached by the service worker. Again, once user clicks on any of the product page gets loaded and the resources which is required or responsible to fetch this particular page are loaded by through the service worker. And then again, the route label and component labels code splitting are implemented across the website. This is a typical page, product page look like. So you could see the primarily three or four section in one of the template or the markup. So I will particularly talk about the bottom two which is a deferred component of the on-demand components. A deferred component basically a lazy loading of the component. Once your pages are rendered from the server side or it just first above the full content are ready and you might have some dynamic content like you. So we had like offers. So offers are dynamic. So that's where it goes in the deferred component because these are the important ingredient of the interest of the consumer. But anything which is not very primarily required part of the above the fold it has gone again on-demand. So this is again the reactive approach, right? If users is going to show some intent towards looking at those content which is at the bottom of the page then only we are going to construct that, right? And this basically worked pretty well and I'm going to show the business numbers again which shows these are the actual, these approach work pretty well for us in order to have the more user engagement and having the better business matters. So this is again the comparison of the JavaScript optimization earlier it used to be 88 KB after that vendor become 8.3 KB JavaScript before was to one 8 KB later 122 KB how this is 122 KB because we need to count Google Analytics, GTM a lot of third-party libraries like Facebook or marketing pixels, right? So that's counting for this 122 KB. 18 KB JavaScript, initial JavaScript which is responsible for making page interactive. So it's just 18 KB. Runtime performance optimization. That's again so it was more about when user click on any of the when you start interacting with the webpage we need to ensure that all the identify the long task which is taking more than 100 seconds or 200 second and breaking those long task into the smaller task. If you have studied about the real model which was advocated by a lot of blocks in Google by the Google. So this particular explains that 100 MS is the right time to respond to the any action user takes on your webpage and all the visual changes basically, right? So any animation we need to show that has been gone into the request animation frame in order to we should avoid any friction or any kind of a jank in a kind of showing animations. Instrumentation and analytics. Definitely we have users web worker ensuring that we are not blocking user action where we are not doing anything which is basically engaging the main thread, right? So keeping the main thread healthy and ideal was the go-to approach and that's where a lot of computation, a lot of heavy lifting has been done to the web worker in order to manage data manipulation, massaging for the instrumentation or analytics. Memorization of the window function. So there is a lot of time we need to call windows APIs in order to get the typically in e-commerce and the application nature of the application what we have. So we have a lot of images to show and in a single page might be a different size of images we need to show. So calculating these images, right dimension for the images, responsive images we need to get the viewport height width and so right. So what we used to do earlier, we used to call these window function every time we really needed it. So we have seen it was causing a lot of reflows when we are calling these functions. So we started memorizing these functions, right? So the next time, so once this function is getting called, it was just save all these dimensions or all the window properties which was required in the future into the memory and next time when we used to call these functions this was fetched out from the memory. So this is how we optimize the JavaScript runtime performance, right? Yeah, so image optimization. Again, this was a very basic hygiene I would say. I think in first place it should have been fixed but we were never enough not able to crack this because basically the problem with the approach where we were building, we have built entire application using desktop first approach, right? So a lot of images which was even not on the correct size. We were using the images which is primarily for main for the desktop or maybe probably for the tablets. Using the right image dimension, I think this is a need of today's any mobile web application because you have a different browser having a different kind of image optimization, right? So WebP, for example, is a Chrome but might not work in Safari but Safari has its own version of lightweight images. So a lot of these we did with using again third party because this is not our core business so we leverage a lot of functionality from the cloudinary in order to optimize the images having the right dimensions, having right types, having right quality of the images based on the network and based on the user device. Again, there are many times when we use JavaScript, we were using basically a JavaScript to construct the image URL, right? So which dimension it should be, which type it should be. So that was actually delaying the constructing the, showing up the images, right? So we optimize and minimize the use of JavaScript in order to construct the image URL before it shows up. So these are the basically the image optimization methods we tried and you could see the difference, right? I think that's what I was saying. So we were not doing a good job. 940, 54 KBs, MSB4 and 56.6 KB images after, right? So this is something which is fundamentally wrong or we did wrong basically. So this was a basic hygiene of the system what we fixed as part of the optimization. And these are the visually, so difference. So earlier in fast 3G we used to take 18 seconds after the optimization, all the optimization I talk about we were close to 3.5 second. Again, slow 3G, if you see the difference again, it's a 3X faster now, 42 seconds, no way user is going to continue with your app. Most probably it will not come back again, right? And 11 seconds probably in 3G we still have a scope to optimize it. We're still on it, right? So performance is something which is not done one time. It is a continuous process. And we are still trying to optimize it, how good we can do. These are the Lighthouse scores. You can see the suboptimal performance numbers on top and then later on these are like the perfect hundred. So I think happy ending to the entire optimization project. And these are the more detailed one. First content full paint 0.8 second, meaningful paint 0.8 second, speed index, that means the visually completeness of your website which was 2.1 seconds, 1.1 time to interactive. So this is something which is, you can see about the user experience. So probably you will like the new one which is much more cleaner, much more faster. And the left one which is, sorry, even I would not like to see that again. So the performance, first-class decision. So what we did basically in order to achieve that, right? So managing performance budgets. So we are using Lighthouse performance budget tool in order to ensure that every time our Jenkins jobs are running, it is actually not breaking the rules we have set. Webpack plug-ins also we are using. So every time developer is going to run the build, if the JavaScript size is going to exceed by 20 KBs, it will, the build will break. So user are more agile or more thankful about adding any feature they can go back and talk to product that we need to remove something or we need to think about that how we could ensure that the bundle size is not going to increase. So these are the Jenkins jobs for the daily reports. We have set up a performance testing as a release acceptance criteria. So none of the releases are going if the performance criteria is not met. So these are the basically shifting towards or the developer is starting adjusting to the first having this performance as a first-class decision, right? So nobody goes or think that if we are not meeting the performance criteria, things are going to work, right? So this is also how we started shifting towards or having a better mindset about the performance for the developer. Business mattress, there are business folks possibly they would like it. So the all greens and basically once we have completed this project in six weeks, right? And this is actually the pitch for the getting the another project where we are going to optimize and we actually got the another project where we optimize the payment app again. So I think this is important because I think everything I talk about is not something very smooth, right? It's just we tried it and everything worked, right? This is a very important thing. TTI optimization was tough. Though we have shipped the entire project in six weeks to the production but TTI optimization was good enough, no. So reaching 85 Lighthouse score was easy but it took another three months to reach to the 100, right? Even as very minute details we have gone ahead and deep dive and reaching there was actually a tough task. It's not easier, I could say. The utils trap again, I was talking about just putting up like a lot of JavaScript or the code into a single file. And generally this is what we do. A lot of common functions we put into a single file that gets heavy over the time and eventually we end up having a big JavaScript file. So this is again challenges. We need to refactor code a lot in terms of ensuring that we are reaching the 20KB size what we have thought about. Analytics and other third party JavaScript was nightmare, still a nightmare, still be fixed again. If you go to probably if you run a test again for the Jabong possibly you might not see 100 because of some third party library getting included. So this is a part of parcel of the business, right? So we need to have a revenue, a lot of metrics, things has to be done, retargeting pixels. So again, this happens over the time and we need to keep talking to our business folks and getting these optimization. So this was a challenge, still a challenge and going to be a challenge. Polyfills, again, polyfills we need to, generally what we do, we add core JS or polyfills, Babel polyfills, which is the 30KB size again. So how we did it, basically we have gone ahead to MDN, pick that particular polyfills implementation at the MDN and put that into our code base. So this is how we reduce from 30KB to 1.5KB for the polyfills. Side notes, ability to push changes to the production daily and experiment friendly environment. This was actually a big help because we were able to not going into the too many discussion, we were able to push to the production validate the concept we were thinking or the methods we were thinking to optimize the content. Ask experts for help. I guess we have done this a lot. We have consistently worked with the Google folks for past six to nine months in order to get a lot of technical advancement or the help from them. The two hours through six week product shipping was not easy. So we used to have a two hours check in daily basis. If anybody is blocked or to ensure that we are unblocking that guy or at least having them to solving the right problem. We are still learning. So while I'm saying all of these things, still we haven't learned a lot. We are still trying to optimize things. We are still learning new things and putting those into the implementation for our web app. The summary, so this is everything we did in order to achieve the numbers I have shown. So the passive listeners and probably the intersection observer I did not talk about but this is also we have the network API. So we have used the API in order to have lower quality images for the slow 3G devices so that the user is still able to see the images and can do the intended behavior. So yeah, that's it. Thank you. So I think I have just one minute. So if you guys have any question, possibly shoot at me. Hi, you talked about the container management that you guys have written in about 700 bytes, right? The store or the container management, you wrote in-house for about, with about 700 bytes. State management? Yeah. Okay. So can you talk a little bit about it, like what's inside just 700 bytes? This is, that's what I'm saying, right? So Redux is just a thought process or maybe the pattern you could use. We implemented just the same thing. Possibly we did not needed a lot of things which Redux offered you. We just have done the same thing. Having a, rather than having a multiple reducer, we have put everything in our single, all the properties in a single file and we have just had two methods which is a subscribe and a subscribe unsubscribe. So every component which is subscribing those properties were basically able to just call those subscribe method under the hood and subscribe to those properties. And internally that implementation of that react component with Redux were able to actually high level component, typically in any react application you have seen this provider thing, right? So we have implemented the provider and provider basically as the top level component which used to take care of the rendering of or calling the render function of the component which is actually subscribed to a particular component. Once the component was actually getting unmounted, we were just able to unsubscribe those components. So it was a very simple implement. It's the same as the Redux. Thank you.