Stop Shipping the Whole core-js Library: Use Modular Polyfill Imports
Stop shipping every core-js polyfill. Import only the ECMAScript features your app uses and verify the savings in your production bundle.
25 Jan 2026, 02:38 UTC

Your bundle is probably carrying polyfills you never use
Your production JavaScript bundle may include polyfills your code never calls. If you import the top-level `core-js` package, the library loads the full set of ECMAScript polyfills and attaches them to global objects such as `Array`, `Promise`, and `Object`. That convenience comes at a cost: every unused method still occupies space in the file your users download.
The practical takeaway is to import only the features you actually use, from paths like `core-js/es/array/flat`, and then verify with a bundle analyzer that the rest stayed out. This works with core-js v3; core-js v2 is end-of-life and does not receive patches.
Swap the full import for targeted modules
A statement such as `import 'core-js'` tells your bundler to include everything. A bundler is a tool that combines your source files and dependencies into files the browser can load. Because core-js modifies built-in prototypes globally, the package is designed to be imported once, often at the top of your entry file. That single import can add hundreds of kilobytes before minification and compression, much of it for features like `Array.prototype.flatMap` or `Promise.allSettled` that your application may never invoke.
Targeted imports look like this:
// Before: everything
import 'core-js';
// After: only the features this application uses
import 'core-js/es/array/flat';
import 'core-js/es/promise/all-settled';
Each path pulls in one polyfill and its immediate dependencies, not the whole library. Modern bundlers can then leave out the modules you do not reference, a process often called tree-shaking.
Check the installed major version first
Before you rewrite imports, confirm you are on core-js v3. The modular paths described here belong to v3, and they can change between minor versions.
Run this command in your project’s root directory:
$ npm ls core-js
You do not need administrative permissions for this read-only command. Expected output includes a line such as `core-js@3.x.x`. If the command returns version 2.x or nothing at all, do not use the `core-js/es/` paths yet; upgrade to v3 and review its migration notes first. Changing the dependency version modifies `package.json` and the lock file, so revert those files if the upgrade causes failures.
Polyfills do not transpile syntax
A common misunderstanding is that core-js makes new JavaScript syntax run in old browsers. It does not. A polyfill adds a runtime method or object that is missing from the environment, such as `Object.fromEntries`. It cannot teach an old browser to understand optional chaining (`?.`) or nullish coalescing (`??`). You still need a compiler such as Babel or SWC to transform new syntax into older equivalents. Use core-js for missing APIs and a compiler for new syntax.
Verify the bundle, not just the imports
Changing an import statement does not guarantee a smaller bundle. Inspect the production build with a source-map viewer or bundle analyzer. Look for modules under `core-js/es/` and confirm that the full `core-js` entry point is absent. Then load the built application in the oldest browser you support and check that the polyfilled feature works—for example, that `[1, 2].flat()` returns a flattened array even where the browser lacks native support.
Limitation: proposals can drift
core-js separates finished standards from Stage 3 proposals. Proposal imports live under paths such as `core-js/es/proposal/...`. These can change or be removed as the specification evolves, and a proposal polyfill may behave differently from the final standard. Avoid proposal imports in long-lived application code, or gate them behind a feature flag and remove them once the feature ships natively in your target browsers.
Global polyfills also alter built-in behavior. In a dependency-heavy project, another library might assume a native implementation and behave unexpectedly after a polyfill redefines a method. Test after adding any new core-js import.
Closing
Start with one import. Replace `import 'core-js'` with the specific modules your code uses, pin core-js to a v3 minor version, and review the changelog before upgrading. Verify with your bundle analyzer and your oldest supported browser. If the bundle does not shrink, the analyzer will show you which module is still pulling in the rest.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.