Stop importing all of core-js: targeted polyfills with feature detection
Blanket core-js imports bloat bundles and risk overriding natives. Targeted modular imports with runtime feature detection give smaller builds and safer polyfills for web and Node apps.
30 Jun 2026, 23:12 UTC

The bundle bloat you didn't ask for
A web app targets modern browsers but still ships a blanket import 'core-js/stable'. The build grows, and Node 20 services end up with polyfills that overwrite correct native behavior for Array.from and Promise.any. The useful takeaway is to import only the features you actually use and let core-js run its runtime feature detection instead of forcing globals.
Feature detection is built into core-js
core-js defines a polyfill only when the native implementation is missing or behaves incorrectly. That guard reduces risk of overwriting a correct native. The library ships modular code by ECMAScript feature and proposal stage, so you can address a single capability instead of the whole stable set.
core-js-pure exposes the same implementations as pure functions without mutating globals. That is a practical choice for libraries that must not change the host environment.
Modular imports give intent and size control
Core-js 3 modularizes polyfills under core-js/es and core-js/stable. A blanket import pulls in many modules, some of which duplicate what the runtime or bundler already provides. Targeted imports trade convenience for smaller bundles and clearer dependency intent.
Side-effect imports mutate globals, while pure imports do not. Mixing the two styles in the same project can lead to inconsistent expectations about feature availability.
Worked example: polyfill Array.from only where needed
In an application entry point you can import a specific feature and rely on the internal detection guard.
// project root, e.g. src/main.js
// No elevated permissions required
import 'core-js/es/array/from';
import 'core-js/es/promise/any';
// Use the feature normally
const items = Array.from(document.querySelectorAll('li'));
For a library that must avoid global mutation, use the pure build:
// library source, e.g. src/utils.js
import { from } from 'core-js-pure/es/array/from';
export function toArray(iterable) {
return from(iterable);
}
The pure import gives you a local function that falls back to the polyfill implementation only when the native is absent or broken, without touching Array.from on the global object.
Trade-off and limitation
Targeted imports require you to know which features your code and dependencies need. Version skew between core-js and actual target environments can cause subtle behavioral differences for edge-case spec compliance. Blanket imports are easier to start with but increase bundle size and maintenance surface.
Check it in your project
Inspect the installed version and imports.
# run in project root
npm list core-js --depth=0
Expected check: the version matches your browserslist or Node targets. Risk: an old version may lack detection for newer native fixes.
Compare module graphs before and after switching from a blanket import to targeted imports using your build tool's stats. Create a minimal test that imports a specific core-js module and verifies the native is used when present and the polyfill is applied when absent.
Run feature detection checks in the intended target runtimes to verify polyfills activate only when needed and do not override correct natives. If you change imports, remove the blanket import to avoid duplicate side effects.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.