The @babel/polyfill
package allows you to emulate an ES6+ environment. Effectively, it ensures your ES6+ code is backwards compatible with older browsers and environments. It sounds like a golden fixture in modern JavaScript, right? Well, as of Babel 7.4.0, this powerful package had been deprecated. Composed of two dependent packages, core-js
and regenerator-runtime
, Babel now recommends installing them as dependencies and importing them at the top level of your application (think of index.js
in a React app, for example).
- core-js: a collection of polyfills to support stable and experimental features of the latest ECMAScript
- regenerator-runtime: a package to support generator functions and async/await syntax
However, there was an alarming caveat with this recommended solution: a significantly increased bundle size.
Since you’re globally importing all of the polyfills and regenerator-runtime, an increased bundle size is a given. Luckily, this isn’t the only way to inject polyfills and support generator and async functions. You can minimize your bundle size by including the packages as part of your bundling process (at compile time) and importing their modules only when they’re needed. Please see the steps below:
Note: I am using Node 12.14.1 and Webpack as my bundler of choice.
- Install
core-js
,@babel/core
,babel-loader
, and@babel/preset-env
as devDependencies.
yarn add core-js @babel/core babel-loader @babel/preset-env --dev
You may be wondering why you're not installing regenerator-runtime
. Well, if you study your lock file, you’ll notice that @babel/plugin-transform-regenerator
and @babel/runtime
are already included as dependencies to your previously installed packages. They’ll add compatibility for generator and async functions.
2. Next, to ensure the polyfills and Babel features are loaded at compile time, you will need to add babel-loader
to your Webpack configuration:
module: { rules: [ { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ }
]
}
3. Finally, in your .babelrc
file, add @babel/preset-env
as a preset with the following configuration:
["@babel/preset-env", { "useBuiltIns": "usage", "corejs": 3.6}]
- corejs: Here, you’re setting the version of
core-js
to target for polyfills. Setting the minor version ensures Babel will be able to support the latest, stable core-js features. - useBuiltIns: This option allows you to configure how Babel handles polyfills. It can be set to
entry
,usage
, orfalse
.
— The entry
option transforms direct imports of core-js to imports of the modules within core-js that are required by a target environment. If you were to use this option, you would need to add these import statements to the entry point of your app:
import 'core-js';import 'regenerator-runtime/runtime';
— By contrast, the usage
option automatically imports polyfills when they’re needed at the top level of each file for features that aren’t supported in the environment. You may be wondering if the polyfills will be excessively loaded when using the usage
option. Thankfully, the bundler only loads the same polyfill once.
Therefore, for this tutorial, employ the usage
option since you’re not using direct import statements for core-js and you’ll be able to take advantage of how polyfills will be automatically imported on an as needed basis for each file.