Babel polyfill is dead. Long live core-js!

January 08, 2020

I encountered problems in some projects with core-js versions. After resolving them, I want to share to you my findings

@babel/polyfill is deprecated

@babel/polyfill has been deprecated since babel version of 7.4.0.

@babel/polyfill is combination of core-js and regenerator-runtime but it tingly coupled to core-js@2 and cannot provide smooth migration to core-js@3

Official @babel/polyfill documentation

Long live core-js

What is core-js? core-js github link

  • It is a polyfill of the JavaScript standard library, which supports:
    • The latest ECMAScript standard.
    • ECMAScript standard library proposals.
    • Some WHATWG / W3C standards (cross-platform or closely related ECMAScript).
  • It is maximally modular: you can easily choose to load only the features you will be using.
  • It can be used without polluting the global namespace.
  • It is tightly integrated with babel: this allows many optimizations of core-js import.

Long story short - core-js is modularized set of polyfills with can be used independently or with babel

Simplest migration for manual import from @babel/polyfill to core-js is change

import "@babel/polyfill";

to

import "core-js/stable";
import "regenerator-runtime/runtime";

More examples

@babel/preset-env with core-js

@babel/preset-env has 2 different modes, which can be enabled with the useBuiltIns option: entry and usage, which optimize imports of core-js in different ways.

Babel 7.4.0 introduces both changes commons to the two modes and specific to each mode.

Since @babel/preset-env now supports core-js@2 and core-js@3, useBuiltIns requires setting a new option, corejs, which specifies the used version (corejs: 2 or corejs: 3). If it isn't directly set, corejs: 2 will be used by default and it will show a warning.

To make it possible for Babel to support new core-js features introduced in future minor versions, you also can specify the minor core-js version used in your project. For example, if you want to use core-js@3.1 and take advantage of new features added in that version, you can set the corejs option to 3.1: corejs: '3.1' or corejs: { version: '3.1' }.

One of the most important parts of @babel/preset-env was the source providing data about the features supported by different target engines, to understand whether something needs to be polyfilled by core-js or not.

Should I use core-js@2 or core-js@3?

Short answer - you should use version 3. Why? Coz it maintainable.

Force core-js@3 by adding concrete dependably

npm i --save-dev core-js@3 @babel/runtime-corejs3

Configure @babel/preset-env in .babelrc to use core-js version 3

presets: [
  ["@babel/preset-env", {
    useBuiltIns: "usage", // or "entry"
    corejs: 3,
  }]
]

In case you are using @babel/transform-runtime

plugins: [
  ["@babel/transform-runtime", {
    corejs: 3,
  }]
]

otherwise, your project will end up unbuildable

Customized preset-env also support core-js

NuxtJS

@nuxt/babel-preset-app also support core-js configuration by extending nuxt.config.js build section:

{
   /*
   ** Build configuration
   */
  build: {
    babel: {
      presets({ isServer }) {
        return [
          [
            '@nuxt/babel-preset-app',
            {
              buildTarget: isServer ? 'server' : 'client',
              corejs: { version: 3 } // or version: 2
            }
          ]
        ]
      }
    },
    extend(config, ctx) {}
  }
}

Also insure to install correct dependency:

npm i --save-dev core-js@2 @babel/runtime-corejs2

Core js build errors

Errors like

Module not found: Error: Can't resolve 'core-js/modules

Indicate what you encounter problem with invalid core-js version. You should force concrete version on your project to eliminate headache. Use -

npm i --save-dev core-js@3 @babel/runtime-corejs3

or

npm i --save-dev core-js@2 @babel/runtime-corejs2