How I built a super fast Uber clone for mobile web

16,310 reads

This post is about my learning on performance techniques used to make Uber mobile web using React as fast as possible.

Motivation

It’s been a year since Flipkart Lite was launched and few months since Housing Go was launched and I was always fascinated with the idea of how mobile web is a future and I wanted to give a try.

First I needed an app on which I can implement the perf techniques, and Uber had just recently launched their app with new design and it looked promising so I decided to clone the app using React.

It took me some time to build the basic implementation of the app, I have used https://github.com/uber/react-map-gl for the map and used svg-overlay to create a path from the source and destination along with the html-overlay.

Below is the gif of the app with basic interaction.

Now that I had the basic app to work on, I started to improve the performance of it.

I have used Chrome Lighthouse to check the performance of the web app in each stage.

initially load time looked like this.

To improve the above stats I have used following techniques

Code Splitting — reduces load time from 19sec to 4sec

First thing I did was used webpack code splitting techniques to divide the app into various chunks based on the route and load what is needed for that particular route.

This I did by using the getComponent api of react-router where I require the component only when the route is requested.

I also extracted the vendor code using CommonChunkPlugin in webpack.

With this I have reduced the load time from 19secs to 4secs.

Performance metrics using code splitting

2. Server side rendering — reduces load time from 4sec to 921ms

I then implemented SSR by rendering the initial route on the server and passing on to the client.

I used Express for this on the backend and used match api of the react-router

Thanks to SSR, now the load time is 921ms.

Performance metrics using SSR

3. Compressed static assets — reduces load time from 921ms to 546ms

Then I decided to compress all the static files, this I did this by using CompressionPlugin in the webpack

and express-static-gzip to serve the compressed file from the server which falls back to uncompressed if required file is not found.

yippee I saved almost 400ms. Good job, Narendra!

Performance metrics after compressing the assets

4. Caching — helped load time of repeat visits from ~500ms to ~300ms

Now that i had improved the performance of my web app from 19seconds to 546ms, I wanted to cache static assets so the repeat visits are much faster.

I did this by using sw-toolbox for browsers which support service workers

and cache-control headers for browsers which don’t support.

By doing this I improved the repeat visit by approximately 200ms.

Repeat visit without service worker

Repeat visit with service worker

5. Preload and then load

I have used <link rel="preload" ... as="script"> in the head tag and used prefetch for the browser which doesn’t support preload.

At the end of the body I load the application JS in a regular <script> tag.

For more about preload and prefetch please visit https://css-tricks.com/prefetching-preloading-prebrowsing/

Finally tested with Google PageSpeed and this is the result

Scores from PageSpeed Insights

This has been a good learning for me, I know I can optimize more and will keep exploring. Performance improvement is an ongoing process this is just a benchmark to what I have achieved. Give a try with your app and let me know your story.

Github: https://github.com/narendrashetty/uber-mobile-web

Live Demo: https://uberweb.herokuapp.com/ or

https://uberweb-v2.herokuapp.com/

Please give a visit to the demo on your mobile browser and share your inputs with me. (Since I hosted it on heroku, it’s goes down when it has no visits. Don’t lose patience if it doesn’t load at first :P Such an irony).

Maintaining Performance is like a chess, one wrong move and it undos lot of hardwork done.

Thanks for reading, If you liked this article, click “Recommend” or write a response below. You can connect with me on Twitter @narendra_shetty.

Tags