Usage

Installation

# global version
npm install --save core-js@3.51.0
# version without global namespace pollution
npm install --save core-js-pure@3.51.0
# bundled global version
npm install --save core-js-bundle@3.51.0

Entry points

You can import only the polyfills you need. CommonJS entry points are available for all polyfilled methods / constructors and namespaces. Just some examples:

// polyfill all `core-js` features, including early-stage proposals:
import "core-js";
// or:
import "core-js/full";
// polyfill all actual features - stable ES, web standards and stage 3 ES proposals:
import "core-js/actual";
// polyfill only stable features - ES and web standards:
import "core-js/stable";
// polyfill only stable ES features:
import "core-js/es";

// if you want to polyfill `Set`:
// all `Set`-related features, with early-stage ES proposals:
import "core-js/full/set";
// stable required for `Set` ES features, features from web standards and stage 3 ES proposals:
import "core-js/actual/set";
// stable required for `Set` ES features and features from web standards
// (DOM collections iterator in this case):
import "core-js/stable/set";
// only stable ES features required for `Set`:
import "core-js/es/set";
// the same without global namespace pollution:
import Set from "core-js-pure/full/set";
import Set from "core-js-pure/actual/set";
import Set from "core-js-pure/stable/set";
import Set from "core-js-pure/es/set";

// if you want to polyfill just the required methods:
import "core-js/full/set/intersection";
import "core-js/actual/array/find-last";
import "core-js/stable/queue-microtask";
import "core-js/es/array/from";

// polyfill async iterator helpers proposal:
import "core-js/proposals/async-iterator-helpers";
// polyfill all stage 2+ proposals:
import "core-js/stage/2";

Tip

The usage of the /actual/ namespace is recommended since it includes all actual JavaScript features and does not include unstable early-stage proposals that are available mainly for experiments.

Warning

  • The modules path is an internal API, does not inject all required dependencies and can be changed in minor or patch releases. Use it only for a custom build and/or if you know what you are doing.
  • If you use core-js with the extension of native objects, recommended to load all core-js modules at the top of the entry point of your application, otherwise, you can have conflicts.
    • For example, Google Maps uses its own Symbol.iterator, conflicting with Array.from, URLSearchParams and / or something else from core-js, see related issues.
    • Such conflicts are also resolvable by discovering and manually adding each conflicting entry from core-js.
  • core-js is extremely modular and uses a lot of very tiny modules, because of that, for usage in browsers, bundle up core-js instead of using a loader for each file; otherwise, you will have hundreds of requests.

CommonJS and prototype methods without global namespace pollution

In the pure version, we can't pollute prototypes of native constructors. Because of that, prototype methods are transformed into static methods. But with transpilers, we can use one more trick - bind operator and virtual methods. For this case, there are /virtual/ entry points. Example:

import fill from 'core-js-pure/actual/array/virtual/fill';
import findIndex from 'core-js-pure/actual/array/virtual/find-index';

Array(10)::fill(0).map((a, b) => b * b)::findIndex(it => it && !(it % 8)); // => 4

Warning

The bind operator is an early-stage ECMAScript proposal and usage of this syntax can be dangerous.

Babel

core-js is integrated with babel and is the base for polyfilling-related babel features:

Note

useBuiltIns and corejs options described below are available only in Babel 7; in Babel 8, they were replaced with babel-plugin-polyfill-corejs3.

@babel/polyfill

@babel/polyfill IS just the import of stable core-js features and regenerator-runtime for generators and async functions, so loading @babel/polyfill means loading the global version of core-js without ES proposals.

Now it's deprecated in favor of separate inclusion of required parts of core-js and regenerator-runtime and, for backward compatibility, @babel/polyfill is still based on core-js@2.

As a full equivalent of @babel/polyfill, you can use the following:

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

@babel/preset-env

@babel/preset-env has useBuiltIns option, which optimizes the use of the global version of core-js. With useBuiltIns option, you should also set corejs option to the used version of core-js, like corejs: '3.51'.

Important

It is recommended to specify the used minor core-js version, like corejs: '3.51', instead of corejs: 3, since with corejs: 3, modules added in minor core-js releases will not be injected.


  • useBuiltIns: 'entry' replaces imports of core-js with imports of only the modules required for a target environment. So, for example,
import 'core-js/stable';

with chrome 71 target will be replaced just to:

import 'core-js/modules/es.array.unscopables.flat';
import 'core-js/modules/es.array.unscopables.flat-map';
import 'core-js/modules/es.object.from-entries';
import 'core-js/modules/web.immediate';

It works for all entry points of global version of core-js and their combinations, for example for

import 'core-js/es';
import 'core-js/proposals/set-methods';
import 'core-js/full/set/map';

with chrome 71 target you will have as the result:

import 'core-js/modules/es.array.unscopables.flat';
import 'core-js/modules/es.array.unscopables.flat-map';
import 'core-js/modules/es.object.from-entries';
import 'core-js/modules/esnext.set.difference';
import 'core-js/modules/esnext.set.intersection';
import 'core-js/modules/esnext.set.is-disjoint-from';
import 'core-js/modules/esnext.set.is-subset-of';
import 'core-js/modules/esnext.set.is-superset-of';
import 'core-js/modules/esnext.set.map';
import 'core-js/modules/esnext.set.symmetric-difference';
import 'core-js/modules/esnext.set.union';
  • useBuiltIns: 'usage' adds to the top of each file imports of polyfills for features used in this file and not supported by target environments, so for:
// first file:
let set = new Set([1, 2, 3]);
// second file:
let array = Array.of(1, 2, 3);

if the target contains an old environment like IE 11 we will have something like:

// first file:
import 'core-js/modules/es.array.iterator';
import 'core-js/modules/es.object.to-string';
import 'core-js/modules/es.set';

var set = new Set([1, 2, 3]);
// second file:
import 'core-js/modules/es.array.of';

var array = Array.of(1, 2, 3);

By default, @babel/preset-env with useBuiltIns: 'usage' option only polyfills stable features, but you can enable polyfilling of proposals by the proposals option, as corejs: { version: '3.51', proposals: true }.

Important

In the case of useBuiltIns: 'usage', you should not add core-js imports by yourself, they will be added automatically.

@babel/runtime

@babel/runtime with corejs: 3 option simplifies work with the core-js-pure. It automatically replaces the usage of modern features from the JS standard library to imports from the version of core-js without global namespace pollution, so instead of:

import from from 'core-js-pure/stable/array/from';
import flat from 'core-js-pure/stable/array/flat';
import Set from 'core-js-pure/stable/set';
import Promise from 'core-js-pure/stable/promise';

from(new Set([1, 2, 3, 2, 1]));
flat([1, [2, 3], [4, [5]]], 2);
Promise.resolve(32).then(x => console.log(x));

you can write just:

Array.from(new Set([1, 2, 3, 2, 1]));
[1, [2, 3], [4, [5]]].flat(2);
Promise.resolve(32).then(x => console.log(x));

By default, @babel/runtime only polyfills stable features, but like in @babel/preset-env, you can enable polyfilling of proposals by proposals option, as corejs: { version: 3, proposals: true }.

Warning

If you use @babel/preset-env and @babel/runtime together, use corejs option only in one place since it's duplicate functionality and will cause conflicts.

babel-plugin-polyfill-corejs3

babel-plugin-polyfill-corejs3 is a babel plugin for injection of core-js polyfills. In Babel 8, useBuiltIns and corejs options were removed from @babel/preset-env and @babel/plugin-transform-runtime in favor of this plugin; it also works with Babel 7. It has 3 methods: entry-global (like useBuiltIns: 'entry'), usage-global (like useBuiltIns: 'usage') and usage-pure (like @babel/runtime with corejs: 3 option). Like with corejs option, it's recommended to specify the used minor core-js version by version option, and polyfilling of proposals can be enabled by proposals: true option. Example of configuration in babel.config.json:

{
  "plugins": [["polyfill-corejs3", { "method": "usage-global", "version": "3.51" }]]
}

swc

Fast JavaScript transpiler swc contains integration with core-js, that optimizes work with the global version of core-js. Like @babel/preset-env, it has 2 modes: usage and entry, but usage mode still works not so well as in babel. Example of configuration in .swcrc:

{
  "env": {
    "targets": "> 0.25%, not dead",
    "mode": "entry",
    "coreJs": "3.51"
  }
}

Configurable level of aggressiveness

By default, core-js sets polyfills only when they are required. That means that core-js checks if a feature is available and works correctly or not and if it has no problems, core-js uses native implementation.

But sometimes core-js feature detection could be too strict for your case. For example, Promise constructor requires support for unhandled rejection tracking and @@species.

Sometimes we could have an inverse problem - a knowingly broken environment with problems not covered by core-js feature detection.

For those cases, we could redefine this behavior for certain polyfills:

const configurator = require('core-js/configurator');

configurator({
  useNative: ['Promise'],                                 // polyfills will be used only if natives are completely unavailable
  usePolyfill: ['Array.from', 'String.prototype.padEnd'], // polyfills will be used anyway
  useFeatureDetection: ['Map', 'Set'],                    // default behavior
});

require('core-js/actual');

It does not work with some features. Also, if you change the default behavior, even core-js internals may not work correctly.

Custom build

In some cases, it could be useful to exclude some core-js features or to generate a polyfill for target engines. You can use the core-js-builder package for that.

postinstall message

The core-js project needs your help, so the package shows a message about it after installation. If it causes problems for you, you can disable it:

ADBLOCK=true npm install
# or
DISABLE_OPENCOLLECTIVE=true npm install
# or
npm install --loglevel silent