Autoprefixer 7.0 and Browserslist 2.0

Cover for Autoprefixer 7.0 and Browserslist 2.0

Autoprefixer 7.0 has been released! Learn about the key features—and why the addition of Browserslist 2.0 is the largest change.

Autoprefixer was released four years ago to create a universal tool for dealing with browser-specific CSS prefixes. It was based on the work I was doing with Evil Martians as a frontend developer. In May 2017, Autoprefixer hit its next major release—7.0 “Coelestem adspicit lucem”.

This new version uses the brand new PostCSS 6.0 with lower memory usage. Dmitry Semigradsky has entirely rewritten Autoprefixer from CoffeeScript to Babel. Additionally, Node 0.12 is not supported anymore, and Grid Layout prefixes are disabled by default.

However, the most significant change in Autoprefixer 7.0 is the new Browserslist 2.0.

What is Browserslist?

With Autoprefixer, you can specify which browser versions you wish to target in your application; Autoprefixer will only add the CSS prefixes required for selected browsers.

autoprefixer({ browsers })

From the very start, we’ve recommended against freezing browser versions with a specific number. Browsers update way too often these days, and it’s easy to forget to update the supported versions in your config.

That’s why Autoprefixer has supported specific queries to select browsers according to the Can I Use browser usage database since the first version. For example, > 1% will select all browser versions with more than 1% in global usage (according to statistics).

autoprefixer({ browsers: 'last 2 versions, > 1%' })

However, the need to have a list of targeted browsers is not unique to Autoprefixer. Modern frontend development implicates the use of linters and many other tools, so it may be a good practice to move the “supported browsers” list to a standard config file to have this specified in a single place.

To make this vision real, two years ago, with Autoprefixer 5.0, we moved our browser queries parser to a separate library called Browserslist. It reads browser selection queries from package.json and could be used in many different tools:

  "browserslist": [
    "last 2 versions",
    ">1%"
  ]

Who uses Browserslist

Browserslist users

Browserslist users

Autoprefixer. Let’s start with the obvious: Autoprefixer loads a list of supported browsers from the browserslist key in package.json. You don’t need to do anything else; Autoprefixer will automatically find and load the config.

babel-preset-env is the “Autoprefixer for JavaScript”. It won’t compile ES2015+ syntax if it already knows all your target browsers support it natively.

  "babel": {
    "presets": [
      [
        "env",
        {
          "targets": {
            "browsers": "last 2 version",
            "node": 4
          },
          "loose": true
        }
      ]
    ]
  }

Unfortunately, right now, babel-preset-env will not work with the Browserslist config out of the box—however, this will be fixed in the next major release.

eslint-plugin-compat is a plugin for ESLint that warns when not all targeted browsers can support your JavaScript code. It supports Browserslist config out of the box; it takes the list of target browser versions and checks that your code uses JavaScript APIs supported by all of the specified browsers.

stylelint-no-unsupported-browser-features works like eslint-plugin-compat, but for CSS. Stylelint is outstanding and the most popular CSS linter. This Stylelint plugin makes sure that all targeted browsers support all used CSS properties. It supports Browserslist config out of the box as well.

postcss-normalize only includes the necessary parts of normalize.css, based on your list of supported browsers.

How to use Browserslist

Browserslist is a JavaScript library. If your frontend tool of choice includes support for Browserslist, it will look for browser version-specifying queries in the following places, going from first to last:

  1. Tool options. Think the browsers option in Autoprefixer.
  2. The BROWSERSLIST environment variable.
  3. The browserslist or .browserslistrc config file.
  4. The browserslist key in package.json.

Browserslist will look for config files and package.json recursively in directories from bottom to the top. If you have a components/header/header.css file, Browserslist will check components/header/ for configs first, followed by components/, and then the root of the project.

We recommend only specifying target browsers in package.json. Even if Autoprefixer is the only tool you’re going to use, don’t specify your target browsers in Autoprefixer’s browsers option.

Many tools have Autoprefixer included (postcss-cssnext, old webpack versions). If you use the browser option, “other” Autoprefixers will not see your browser requirements. As a result, they could remove the prefixes previously added by Autoprefixer.

If you set browser requirements in the Browserslist config instead, all your tools can use the same config.

Autoprefixer 7

Autoprefixer has already been using Browserslist for two years. Now, after these years of success, we’re finally introducing Browserslist 2.0 with the following important changes:

  1. Reduced node_modules size.
  2. Better performance with filesystem caching.
  3. Changes in the last n versions query.

Reduced node_modules size

Black hole vs. node_modules joke

Vladislav Kozulya’s joke based on The mysterious boundary article by Andrew Grant

In the JavaScript community, it’s natural to complain about the size of the node_modules directory. Having a separate copy of the entire development environment specific for a project is a great feature, but not all npm packages care about their size in a way that’s respectful to the user.

caniuse-db is one of these “offending” packages—it was designed primarily for the “Can I Use” website and it needs (and has) lots of data that’s irrelevant for Autoprefixer and Browserslist. As a result, caniuse-db is an enormous 7 MB!

Ben Briggs, one of the key developers in the PostCSS community, came up with a solution—he created caniuse-lite. A script takes the caniuse-db package, removes unneeded data, compresses the rest, and automatically releases a new caniuse-lite package following every caniuse-db release.

As a result, the size of caniuse-lite is only 1 MB—7 times less! Accordingly, Autoprefixer 7 and Browserslist 2 depend on caniuse-lite instead of caniuse-db.

Better performance

Unfortunately, many significant tools use synchronous APIs; hence, Browserslist must work with synchronous APIs as well. However, many file system operations can be required to find a config file.

Luckily for us, Finnish developer Aarni Koskela decided to tackle Browserlist bottlenecks—to great success.

GitHub party

GitHub party

He found many problematic places and we’ve fixed some of them in previous patch releases. However, we’ve been waiting for a major release to ship his primary improvement: Browserslist 2 ships with caching for file system operations.

As a result, Browserslist is now 6 times faster; this could make an average Gulp config 5 to 10% faster.

However, please note that most tools do not empty the Browserslist cache by themselves, so you need to restart your webpack development server to see changes. Fortunately, Browserslist config changes are relatively rare, so it’s a reasonable trade-off.

Browserslist 2 caching benchmark

Browserslist 2 caching benchmark

Changes in last n versions for a better Web

From the very beginning, Autoprefixer’s last 2 versions selected 2 last browser versions, but not from all browsers—just the most popular ones. As it turns out, that was a mistake.

There are no “main” browsers in the real world. For instance, the online market is enormous in China, and there are a lot of popular local browsers in China. We cannot just ignore local browsers—The Web should be accessible to everyone.

In fact, Autoprefixer itself was created to stop browser differentiation (like using -webkit--only prefixes for mobile browsers).

So, this is why Autoprefixer 7 and Browserslist 2 last 2 version will select the 2 last versions of all browsers.

Don’t worry about the size—gzip compresses prefixes quite well, so most likely, you will not see any differences in size. See our discussion with Eric Bidelman from Google.

To summarize,

  1. Move your browsers list from Autoprefixer’s browsers option to the browserslist key in package.json.
  2. Update to Autoprefixer 7 to reduce the size of node_modules and make it faster.

Enjoy the release!

Join our email newsletter

Get all the new posts delivered directly to your inbox. Unsubscribe anytime.