React Native

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

It’s been a year since Flipkart Lite launched and few months since Housing Go launched, and I was always fascinated with the idea of how the 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 its app with a new design, and it looked promising, so I decided to clone the app using React.

It took me some time to build the underlying implementation of the app. I used 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 essential interaction.

Now that I had the necessary 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

The first thing I use a webpack code-splitting technique to divide the app into various chunks based on the route and load cf what needed for that particular route.

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

  require.ensure([], (require) => {
    cb(null, require('../components/Home').default);
  }, 'HomeView');

I also extracted the vendor code using CommonChunkPlugin in webpack.

  'entry': {
    'app': './src/index.js',
    'vendor': [
  'output': {
    'path': path.resolve(__dirname, './dist'),
    'publicPath': '/',
    'filename': 'static/js/[name].[hash].js',
    'chunkFilename': 'static/js/[name].[hash].js'
  'plugins': [
    new webpack.optimize.CommonsChunkPlugin({
      name: ['vendor'],
      minChunks: Infinity,
      filename: 'static/js/[name].[hash].js',


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

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

server.use((req, res)=> {
    'routes': routes,
    'location': req.url
  }, (error, redirectLocation, renderProps) => {
    if (error) {
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname +;
    } else if (renderProps) {

      // Create a new Redux store instance
      const store = configureStore();

      // Render the component to a string
      const html = renderToString(

      const preloadedState = store.getState();

      fs.readFile('./dist/index.html', 'utf8', function (err, file) {
        if (err) {
          return console.log(err);
        let document = file.replace(/
<\/div>/, `
`); document = document.replace(/'preloadedState'/, `'${JSON.stringify(preloadedState)}'`); res.setHeader('Cache-Control', 'public, max-age=31536000'); res.setHeader("Expires", new Date( + 2592000000).toUTCString()); res.send(document); }); } else { res.status(404).send('Not found') } }); });

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

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

  'plugins': [
    new CompressionPlugin({
      test: /\.js$|\.css$|\.html$/

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

server.use('/static', expressStaticGzip('./dist/static', {
  'maxAge': 31536000,
  setHeaders: function(res, path, stat) {
    res.setHeader("Expires", new Date( + 2592000000).toUTCString());
    return res;

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

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

toolbox.router.get('(.*).js', toolbox.fastest, {
  'cache': {
    'name': `js-assets-${VERSION}`,
    'maxEntries': 50,
    'maxAgeSeconds': 2592e3

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

res.setHeader("Expires", new Date( + 2592000000).toUTCString());


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



5. Preload and then load
I have used

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 tag.
For more about preload and prefetch please visit

Finally tested with Google PageSpeed and this is the result


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.

Live Demo: or

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).


CC App Screenshots


CC Web Screenshots

Click here to chat with us


Whoops, looks like something went wrong.