Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

browserslist: What Browsers do you need to Support?

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

PostCSS is running! Let's see what it does! Go back to your browser. We haven't reloaded the page yet. I'll search for app.css and click to open that. Search for one of the vendor prefixes: -webkit. Ok, so before adding PostCSS, we have 77 occurrences - coming from our code and Bootstrap.

In theory, if we told PostCSS that we need to support really old browsers, this number should get way higher! How can we do that? Some config in postcss.config.js? Actually, no. It's way cooler than that.

Hello browserslist

In the JavaScript world, there is a wonderful library called browserslist. It's a pretty simple idea: browserslist allows you to describe which browsers your site needs to support, in a bunch of useful ways. Then, any tool that needs this information can read it from a central spot.

Check it out: open up your package.json file. Yes, this is where we'll configure what browsers we need to support. Add a new key: browserslist set to an array:

30 lines package.json
{
... lines 2 - 25
"browserslist": [
... line 27
]
}

You can do a ton of things in here - like say that you want to support the last "2" versions of every browser or any browser that is used by more than 1% of the web or some specific browser that you know is used a lot on your site. Yea, browserslist uses real-world usage data to figure out which browsers you should support!

Let's use a simple example: > .05%:

30 lines package.json
{
... lines 2 - 25
"browserslist": [
"> .05%"
]
}

This is actually a pretty unrealistic setting. This says: I want to support all browsers that have at least .05% of the global browser usage. So this will include some really old browsers that, maybe only .06% of the world uses!

Stop and restart Webpack to force a rebuild and make sure PostCSS reads the new setting:

yarn watch

Now, go back, refresh app.css, search again for -webkit and woh! 992 results! That's amazing! By the way, there is also a tool called BrowserList-GA that reads from your Google Analytics account and dumps a data file with your real-world usage data. You can then use that in your browserslist config, by saying something like: > 0.5% in my stats, which literally means: support any browsers that is responsible for more than .5% of traffic from my site's real-world data. Cool.

Configuring Babel

So what about our JavaScript? Does Babel read this same browserslist config? Totally! Search for .js and click to open the compiled admin_article_form.js file. Inside, search for $autocomplete. Yep! We saw earlier that Babel is outputting var $autoComplete, even though this was originally const $autoComplete. That makes sense: we said that we want to support really old browsers.

So... what if we change the browserslist config to > 5%?

30 lines package.json
{
... lines 2 - 25
"browserslist": [
"> 5%"
]
}

That's probably still a bit unrealistic: this will only support the most popular browsers and versions: pretty much no old stuff. Stop and re-run Encore:

yarn watch

Then move back over to admin_article_form.js and refresh. I'll do a force refresh to be sure... then search for $autoComplete. And... huh? It's still var? Hmm, that might be right... but const was added in 2015 - it should be fully supported by all modern browsers by now.

It turns out... it is, and we're not seeing the changes due to a small bug in Babel. Behind the scenes, Babel uses some smart caching so that it doesn't need to reparse and recompile every JavaScript file every time Webpack builds. But, at the time of recording, Babel's cache isn't smart enough to know that it needs invalidate itself when the browserslist config changes.

Once you know this, it's no big deal: anytime you change the browserslist config, you need to manually clear Babel's cache. In my terminal, I'll run:

rm -rf node_modules/.cache/babel-loader/

Now restart Encore:

yarn watch

Let's check it out! Refresh and search for $autoComplete. There it is: const $autoComplete. Look also for class ReferenceList. Now that we're only supporting new browsers, that code doesn't need to be rewritten either.

Oh, but there is one type of thing that Babel can't simply rewrite into code that's compatible with olders browsers. When you use a totally new feature of JavaScript - like the fetch() function for AJAX calls, you need to include a polyfill library so that old browsers have this. But... even for this, Babel has a trick up its sleeve. That's next.

Leave a comment!

6
Login or Register to join the conversation
Mina-R Avatar

what if i want to suppot not very old versions of browser and last versions

Reply

Hey @Mina-R

You can select or exclude specific browser versions, or you can say something like "last 2 Chrome versions". You can learn more about Browserlist features here https://browsersl.ist/

Cheers!

Reply
Mina-R Avatar

hi i think know there is no need to clear cache in babel

Reply

Does it get cleared automatically now?

Reply
Default user avatar
Default user avatar Stefano Alletti | posted 2 years ago

What can I do if I want to create two entries with two different "browserlists", as indicated in this article?

https://philipwalton.com/ar...

Reply

Hey @Stefano!

Ah, interesting question! Using the browserslist key in package.json is a cool way to store your browser config, but obviously, it's not the only way - and it suffers from the fact that it can't be configured like you're asking. In the article you linked to, they are configuring it directly on the "env" babel preset. You can configure this directly in Encore with the configureBabelPresetEnv function - https://github.com/symfony/webpack-encore/blob/7d4f434800fc4f24691e58563a3b3df7699fbdb7/index.js#L994 - so something like this:


Encore.configureBabelPresetEnv(function(options) {
    options.targets = { browsers: [] };
});

Let me know if that helps!

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial works great with Symfony5!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "aws/aws-sdk-php": "^3.87", // 3.91.4
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.1
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-time-bundle": "^1.8", // 1.9.0
        "league/flysystem-aws-s3-v3": "^1.0", // 1.0.22
        "league/flysystem-cached-adapter": "^1.0", // 1.0.9
        "liip/imagine-bundle": "^2.1", // 2.1.0
        "nexylan/slack-bundle": "^2.0,<2.2.0", // v2.1.0
        "oneup/flysystem-bundle": "^3.0", // 3.0.3
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.3.1
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.2.5
        "symfony/console": "^4.0", // v4.2.5
        "symfony/flex": "^1.9", // v1.17.6
        "symfony/form": "^4.0", // v4.2.5
        "symfony/framework-bundle": "^4.0", // v4.2.5
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.2.5
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "^4.0", // v4.2.5
        "symfony/validator": "^4.0", // v4.2.5
        "symfony/web-server-bundle": "^4.0", // v4.2.5
        "symfony/webpack-encore-bundle": "^1.4", // v1.5.0
        "symfony/yaml": "^4.0", // v4.2.5
        "twig/extensions": "^1.5" // v1.5.4
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.1.0
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/debug-bundle": "^3.3|^4.0", // v4.2.5
        "symfony/dotenv": "^4.0", // v4.2.5
        "symfony/maker-bundle": "^1.0", // v1.11.5
        "symfony/monolog-bundle": "^3.0", // v3.3.1
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.2.5
        "symfony/profiler-pack": "^1.0", // v1.0.4
        "symfony/var-dumper": "^3.3|^4.0" // v4.2.5
    }
}

What JavaScript libraries does this tutorial use?

// package.json
{
    "devDependencies": {
        "@symfony/webpack-encore": "^0.27.0", // 0.27.0
        "autocomplete.js": "^0.36.0",
        "autoprefixer": "^9.5.1", // 9.5.1
        "bootstrap": "^4.3.1", // 4.3.1
        "core-js": "^3.0.0", // 3.0.1
        "dropzone": "^5.5.1", // 5.5.1
        "font-awesome": "^4.7.0", // 4.7.0
        "jquery": "^3.4.0", // 3.4.0
        "popper.js": "^1.15.0",
        "postcss-loader": "^3.0.0", // 3.0.0
        "sass": "^1.29.0", // 1.29.0
        "sass-loader": "^7.0.1", // 7.3.1
        "sortablejs": "^1.8.4", // 1.8.4
        "webpack-notifier": "^1.6.0" // 1.7.0
    }
}
userVoice