Autoprefixer 7.0 and Browserslist 2.0 — Martian Chronicles, Evil Martians’ team blog
Martian Chronicles
Evil Martians’ team blog
Front-end

Autoprefixer 7.0 and Browserslist 2.0

Autoprefixer 7.0 is 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 to deal with browser-specific CSS prefixes, based on the work I was doing in Evil Martians as a front-end developer. In May 2017, Autoprefixer hits its next major release—7.0 “Coelestem adspicit lucem”.

The new version uses brand new PostCSS 6.0 with lower memory usage. Dmitry Semigradsky rewrote Autoprefixer entirely from CoffeeScript to Babel. 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 do you wish to target in your application. This way, Autoprefixer will only add the CSS prefixes required for selected browsers.

autoprefixer({ browsers })

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

That is why since the first version Autoprefixer supports specific queries to select browsers according to the Can I Use browser usage database. 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 front-end 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 it specified in a single place.

To make this vision real, two years ago, with Autoprefixer 5.0, we have 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. Start with the obvious: Autoprefixer loads the list of supported browsers from the browserslist key in package.json. You don’t need to do anything else—Autoprefixer will find and load the config automatically.

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, it will be fixed in the next major release.

eslint-plugin-compat is a plugin for ESLint to warn you 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 an 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 browsers option in Autoprefixer.
  2. BROWSERSLIST environment variable.
  3. browserslist or .browserslistrc config file.
  4. 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 specifying target browsers in package.json only. Even if Autoprefixer is the only tool you are going to use, don’t specify them 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 prefixes previously added by Autoprefixer.

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

Autoprefixer 7

Autoprefixer has been using Browserslist for two years already. Now, after two successful years, we are 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 is natural to complain about the node_modules directory size. To have a separate copy of the whole development environment specific for a project is a great feature—but not all npm packages care about their size in a way that is respectful to the user.

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

Ben Briggs, one of the key developers in 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, caniuse-lite size is only 1 MB—7 times less! Autoprefixer 7 and Browserslist 2 depend on caniuse-lite instead of caniuse-db.

Better performance

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

Luckily for us, Aarni Koskela from Finland went to war with Browserlist bottlenecks—and he has won.

GitHub party

GitHub party

He has found many problematic places; we have fixed some of them in previous patch releases. However, we have waited for a major release to ship his main improvement.

Browserslist 2 ships with caching for file system operations.

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

However, please note that most tools do not empty 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 is a reasonable trade-off.

Browserslist 2 caching benchmark

Browserslist 2 caching benchmark

Changes in last n versions for the 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, China online market is enormous, 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 browsers differentiation (like using -webkit--only prefixes for mobile browsers).

So that is why Autoprefixer 7 and Browserslist 2 last 2 version will select 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 browserslist key in package.json.
  2. Update to Autoprefixer 7 to reduce node_modules size and make it faster.

Enjoy the release!