Differential Serving — Food for latest browsers

Megha Gupta
Walmart Global Tech Blog
4 min readJun 22, 2020
Credit: pixabay.com : https://pixabay.com/illustrations/browsers-internet-web-design-1273344/
Credit: pixabay.com

Differential serving is a modern technique for serving latest javascript bundles to modern browsers.

There are lots of questions around this topic for a while. In WalmartLabs we saw around 10% to 25% reduction in minified bundle size and used this technique to help our overall site speed.

In this blog, I will cover some of these questions. (WHAT, WHY and HOW)

What is Differential Serving?

Why do we need it?

How do we implement it?

WHAT ?

The idea behind differential serving is that the app generates two bundles

  1. Default bundle: While bundling your apps this JS bundle must be already generating — supported by all browsers since it is transpiled to ES5 along with few polyfills.
  2. ES6 bundle: As a part of differential serving this bundle has the exact same functionality, but has no polyfills attached which makes it much smaller in size and only works in supported modern browsers.

WHY ?

The benefit here is older browsers can have a separate bundle with supporting features like polyfills or transforms, For modern browsers, it will have a separate bundle which supports es6- which are small in size hence faster to execute — which implied more site speed and better performance.

Also, There are more than 80% Walmart users using modern JS supported browsers and this feature help a big chunk of our population with a better user experience.

HOW ?

There are two major steps to implement it:

  1. Generate two different bundles — default and es6 bundles
  2. Serve right bundle to browser.

In order to generate two builds of the same app involves few Babel configuration for targeted browsers.

In WalmartLabs all apps are Electrode based. It’s babel configurations are inherited from here, at the app level config has to set with targets and browser list. To simplify configuration layers, webpack config will look like below:

Above configuration will generate es6 bundle where some important configurations are: “@babel/preset-env” preset with modern browser versions in “targets” and “useBuiltIns” value to “entry”. Also, “modules” value to “auto” or “commonjs” based on production build.

In order to serve es6 bundle, the first task to detect the browser types and versions to qualify as modern browser to understand es6 bundles.
One good way to do is by using user-agent to check the browser type. Using library called “bowser

Some devs use Browserslist Useragent library, but I find Bowser has much smaller size and optimized and multi-platform support.

In the electrode specific app, to choose es6 bundle in these latest browsers, it required to set this parameter “request.query.__dist” value to es6

With this configuration in any electrode app, while building it babel transpiles the whole app excluding node modules for es6 bundles, but you can add logic to include and exclude certain node modules from babel transpiling, But I will keep this blog simple in order to understand the main steps clearly.

In the end when you run the app you see this es6.web.bundle.js bundle served to modern browsers otherwise it serves defaut.web.bundle.js

The new shiny es6 bundles are 10% to 25% smaller in size than default bundles. We expected performance and site speed gains along the same lines, but in reality it was a bit different.

But it was not the case in reality. Since we started using Brotli compression in the production, It’s a compression mechanism works much better on default bundles than the es6 bundles — which brought the size difference between these bundles to ~3–5 % only. That, quite explains reason for seeing lower performance gains than expected.

Summary

We started implementing differential serving in start to mid of 2019 where it was quite early in stages across the industry. We learned about its performance gains, pros and cons while experimenting.

Walmart is a huge company, especially cart and checkout section’s performance definitely crucial for business and revenue. Over the time as codebase grows with new features and functionalities differential serving provides better gains in site speed and performance.

Also, this sets up a platform, which enables us to continue to serve modern JS to supported browsers as new features in JS get released.

--

--