Babel is pretty amazing. But, it's even doing something else automatically that we haven't realized yet! Back in admin_article_form.js, and it doesn't matter where, but down in ReferenceList, I'm going to add var stuff = new WeakSet([]);:

... lines 1 - 47
class ReferenceList
{
constructor($element) {
var stuff = new WeakSet([]);
... lines 52 - 81
}
... lines 83 - 136
}
... lines 138 - 163

WeakSet is an object that was introduced to JavaScript, um, ECMAScript in 2015. Because the Encore watch script is running, go over and refresh the built file. Here it is: var stuff = new WeakSet([]);.

New Features & Polyfills

That's not surprising, right? I mean, we're telling Babel that we only need to support really new browsers, so there's no need to rewrite this to some old, compatible code... right? Well... it's more complicated than that. WeakSet is not a new syntax that Babel can simply change to some old syntax: it's an entirely new feature! There are a bunch of these and some are really important, like the Promise object and the fetch() function for AJAX calls.

To support totally new features, you need something called a polyfill. A polyfill is a normal JavaScript library that adds a feature if it's missing. For example, there's a polyfill just for WeakSet, which you can import if you want to make sure that WeakSet will work in any browser.

But, keeping track of whether or not you imported a polyfill... and whether or not you even need a polyfill - maybe the feature is already available in the browsers you need to support - is a pain! So... Encore pre-configures Babel to... just do it for us.

Check it out. Go back to package.json and change this to support older browsers:

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

Then, just like before, go to your terminal and manually clear the Babel cache:

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

And restart Encore:

yarn watch

Ok, let's go back to the browser, refresh the built JavaScript file and search for WeakSet. It still looks exactly like our original code. But now, just search for "weak". Woh. This is a bit hard to read, but it's importing something called core-js/modules/es.weak-set.

This core-js package is a library full of polyfills. Babel realized that we're trying to use WeakSet and so it automatically added an import statement for the polyfill! This is identical to us manually going to the top of the file and adding import 'core-js/modules/es.weak-set'. How cool is that?!

A Polyfill from the Past!

And... this is not the first time Babel has automatically added a polyfill! Open up build/app.js. Back in the editor, the get_nice_message module used a String method called repeat():

export default function(exclamationCount) {
return 'Hello Webpack Encore! Edit me in assets/js/app.js'+'!'.repeat(exclamationCount);
};

Whelp, it turns out that repeat() is a fairly new feature!

Search for "repeat" in the built file. There it is: it's importing core-js/modules/es.string.repeat. When I used this function, I wasn't even thinking about whether or not that feature was new and if it was available in the browsers we need to support! But because Encore has our back, it wasn't a problem. That's a powerful idea.

By the way, this is all configured in webpack.config.js: it's this .configureBabel() method:

... lines 1 - 2
Encore
... lines 4 - 48
// enables @babel/preset-env polyfills
.configureBabel(() => {}, {
useBuiltIns: 'usage',
corejs: 3
})
... lines 54 - 76
;
... lines 78 - 79

Generally-speaking, this is how you can configure Babel. The useBuiltIns: 'usage' and corejs: 3 are the key parts. Together, these say:

Please, automatically import polyfills when you see that I'm using a new feature and I've already installed version 3 of corejs.

That package was pre-installed in the original package.json we got from the recipe.

Next: let's demystify a feature that we disabled way back at the beginning of this tutorial: the single runtime chunk.

Leave a comment!

  • 2019-05-15 Krzysztof Krakowiak

    Thanks Ryan, I really appreciate that you always answering my questions, this is really helpful. Again - Thanks a lot!

  • 2019-05-14 weaverryan

    Hey Krzysztof Krakowiak!

    > Does it transpile/poly-fill code from node_modules too?

    Excellent question! By default, no, it does not. Actually, it's a setting of Babel and Encore pre-configures it to *not* process things in node_modules/ - here is some info about that - https://github.com/symfony/.... We do this for performance - Babel slows things down and *usually* you don't need Babel to be executed on node_modules stuff (that's not *always* true, but running it all the time when you usually don't need it would be a huge pain). You had an interesting situation where you had a 3rd party module that didn't support IE11. In a sense, you were "fixing" their code. Ideally, 3rd party libraries would support all "reasonable" version of browsers.

    > What about: "@babel/plugin-transform-runtime", is this plugin required for anything?

    To be honest with you, I'm not sure. You could try adding this and see if it has any affect. I'm not familiar with this plugin... it *might* save on some filesize - but I really don't know. Sorry I can't give you a better answer on that one!

    Cheers!

  • 2019-05-11 Krzysztof Krakowiak

    Hello Ryan, could you tell something more about Babel? Does it transpile/poly-fill code from node_modules too? I had issue with one dependency from node_modules under IE11, and to resolve it I copied it to asset/vendor folder ad now it works.

    Before this tutorial I had different babel configuration through encore, not sure what are the differences, but I had poly-fills included in my main.js, but I have changed it now to your setup and all works :)

    What about: "@babel/plugin-transform-runtime", is this plugin required for anything?