blog.jakoblind.no

How to create a custom .browserlistrc for babel-preset-env

With @babel/preset-env you can define which browsers your app supports. You do that by editing the .browserlistrc. Most tutorials and docs recommend to start with a generic configuration that supports most commonly used browsers:

> 0.25%
not dead

But how can you customize @babel/preset-env to your app to make your bundle as small and efficient as possible?

What you can do is look in our Google Analytics to see user statistics

But how are you supposed to translate what you see in GA

…to a .browserlistrc config file?

A quick recap of babel-preset-env.

Before we start, what is babel-preset-env again? Here’s a quick recap.

Babel translates ES6 code to ES5 code that all browsers understand. Babel is built up of plugins. For each ES6 feature you want to support, you must enable a plugin for it. There are many babel plugins, and it’s not easy to maintain them individually. That’s why babel-preset-env was created. Instead of manually deciding which plugins to use, you tell which browsers you support and babel-preset-env translates this to a list of plugins automagically. Learn more in my post about babel-preset-env or How to use ES6 with Babel and webpack

Use your GA stats as input to babel preset env

So a couple of days ago I was working with the Babel config of createapp.dev and I was thinking… how can I customize this to use the stats from my GA? I threw out the question on Twitter and got a reply from @tbassetto. Sometimes Twitter is good for other things than procrastinating!

He recommended me to check out browserslist-ga and it was exactly what I was looking for. With this tool, you can fetch all stats from GA, and generate a stats file that babel-preset-env can read from. Let’s have a look.

Start the tool like this in the root directory of your project (no further installation necessary):

npx browserslist-ga

When you do, it’ll ask you to log in to your Google account. According to the documentation, it only uses your session to fetch the stats. I trust them that it doesn’t do anything evil, but haven’t checked their code.

After you run the tool it’ll generate a browserslist-stats.json giving you all the stats in a nice JSON file that Babel can understand. If you look in the file, you’ll see that it’s a JSON object containing all browser versions

Now you can use this as input in your babel config by adding in my stats, like this:

"targets": {
  "browsers": ["> 0.25% in my stats"]
}

This config reads from browserslist-stats.json and it supports browser versions that represents 0.25% or more.

Let’s look into how your custom config differs from the generic config.

How do I know which browsers my config will support?

When using babel-preset-env things are a bit magical. You define some rules for which browsers you support and then you just trust everything will work out fine.

But we are programmers and we want to have control of what’s going on under the hood. To get complete information, add debug: true in your .babelrc config, like this:

{
  presets: [
    [
      '@babel/preset-env',
      {
        debug: true
      }
    ]
  ]
}

This feature is not very well documented, I had worked with babel for months before I found it.

When debug is enabled and you build, it prints to console everything you need to know.

It prints which browsers it’ll support:

{
  "chrome": "49",
  "edge": "17",
  "firefox": "68",
  "ie": "11",
  "ios": "11.3",
  "safari": "5.1",
  "samsung": "9.2"
}

It also prints which plugins and polyfills it uses.

Use debug: true to compare

Now you can compare your custom config with the generic one. Just run babel twice and save the output in a text file.

For my stats it looks like this:

{
  "android": "76",
  "chrome": "67",
  "firefox": "68",
  "ios": "12.2",
  "safari": "12.1"
}

And comparing to just using ”> 0.25%” globally:

{
  "chrome": "49",
  "edge": "17",
  "firefox": "68",
  "ie": "11",
  "ios": "11.3",
  "safari": "5.1",
  "samsung": "9.2"
}

I can see there are lots of things the same, but some differences. My users are running Android, and newer versions of Chrome and Safari. But they don’t use Samsung phones that much.

So which one should you pick? What I do is that I use both of them.

"targets": {
  "browsers": ["> 0.25%", "> 0.25% in my stats"]
}

This way I can be pretty confident most users will be covered. The bundle size get’s a little bit bigger, but it’s worth it.

The cons of using browserslist-ga

If your site doesn’t have much traffic, your data might be not representable for future users. Also, some of your users might have shut off GA tracking so you don’t get the full picture. What you can do is combine using both your stats and the global stats like I described above.

Another thing is you must remember to keep stats up-to-date. New web browsers come out every week. Because the browser stats file is not generated run time, you must remember to regenerate it manually - or create an automated way to do it. You could, for example, integrate it in your CI/CD pipeline if you have one.


tags: