Babel's preset-env

As for the TL;DR version:

Preset-env setup should be optimized to the browsers your customers really use, and bundle size should be configured for core-js based on your needs, whether you are a full stack developer or a JavaScript developer. By doing so, you may publicize the exact browsers that work with your app while still taking advantage of the cutting-edge capabilities of JavaScript.

Background

As part of the Bot Defender solution, we here at PerimeterX keep up a JS script written by an outside party.

If you've ever worked on a third-party script, you know how difficult it can be to ensure that it continues to function across your customers' websites, millions of browsers, and dozens of operating systems. Consequently, I was extremely careful when I was tasked with migrating BabelJS from the preset-2015 environment to the preset-env environment and updating our build system's libraries. With the help of preset-env, I was able to learn some of babelJS's inner workings and uncover several fascinating features.

What, exactly, did the yearly presets do?

The Babel presets for each year (preset-2015, preset-2016, etc.) were primarily concerned with backporting ES6 JavaScript capabilities to ES5. This facilitated the use of modern JavaScript features like promises, let and const, and arrow functions by developers at any point of the development process.

An increasing number of options were included in each year's default setting. To get any further functionality, additional polyfill libraries were required. For the default polyfills, Babel used the babel-polyfill library.

It's also worth noting that some features, including const and let, were converted to var without breaking the existing code. Other features, like promises, needed supplemental code. Your bundle now contains all the feature support code, whether or not you actually use any of it. This may have resulted in the inclusion of dead code and an unnecessary increase in size.

Finally, I'll point out that I had to modify the polyfills because the yearly presets didn't give me the option to specify which browsers I wanted to support.

Important shifts with preset-env

The primary goal of preset-env was to consolidate annual presets into a single, regularly updated collection. However, the following modifications resulted from this modification and the modifications made to the babel library itself:

Changing to core-js from the babel-polyfill lib

As a result, Babel no longer relies on its own polyfill library but instead on core-js to supply modules for supporting new JS capabilities. Code using array.reduce, setTimeout, and array.indexOf to fix browser bugs astonished me when I ran it with the updated setup. Since there is almost no documentation for each module in core-js, I cloned the repo and pored over the code and commit history to get a sense of what each module does. In a short time, I learned that core-js not only performs ES6ES5 modifications (referred to as plugins), but also includes modules for repairing unsupported syntax or partial implementations of previous JavaScript capabilities. Further, it "polyfills" existing functionality with additional capabilities, such as the ability to use symbols in previously unsupported contexts. Depending on the browser type and version, different modules may be activated and used to provide different capabilities. This is determined by code that is executed within the browser.

If you want babel to always include corejs polyfills, just once per file, or for each occurrence of a certain feature in your code, you can configure this behavior with the preset-env useBuiltins flag. Including only what is necessary to make your code work is the best practice. I found that when I enabled the preset-env debug:true flag in conjunction with the useBuiltins: use directive, babel indicated which of my files relied on which modules in core-js. As I dug more into the core-js library, I discovered that its logic for determining whether you utilize a feature in your code depends on the occurrence of particular keywords and, in certain cases, adds needless code.