Adopting core-js-pure in a Shared Library Without Global Side Effects
A task guide for replacing global core-js polyfills with core-js-pure named imports in a JavaScript library, including setup, validation, and rollback.
28 May 2026, 22:30 UTC

The global-polyfill collision problem
When a shared library imports the standard core-js package, it rewrites globalThis and built-in prototypes such as Array.prototype and Map. In a host application that already polyfills those features, or in a micro-frontend where two libraries ship different patch versions, the result is duplicate implementations, prototype conflicts, and hard-to-trace bugs. core-js-pure avoids this by exporting the same standard-library polyfills as named module bindings that never touch global scope.
Desired outcome: local bindings, untouched globals
Ship a library that runs on older runtimes without mutating the consumer's environment. The library should import only the polyfills it needs, keep them tree-shakeable—meaning the bundler can drop unused exports—and leave globalThis.Map, Array.prototype.flat, and similar globals exactly as the consumer left them.
Prerequisites
- Node.js and a package manager installed in the library workspace.
- A source tree that uses ES modules or a transpiler that can rewrite them.
- A bundler that understands ES module tree-shaking (webpack, Rollup, esbuild, or similar).
core-js-pure@3as a project dependency.
Install and import without global side effects
Run the following in the library root:
npm install core-js-pure@3
Expected check: node_modules/core-js-pure/es/ should exist and contain directories such as array, map, and set.
Import polyfills by their leaf path, not the package root. In core-js@3, stable ECMAScript features live under es/; proposals live under features/. Both directories in core-js-pure are side-effect free.
import { Map as PureMap } from 'core-js-pure/es/map';
import { ArrayFrom } from 'core-js-pure/es/array/from';
Importing the root core-js-pure index defeats tree-shaking and can pull the entire standard library into the bundle.
Rewire library code to use explicit bindings
Because globals are not patched, every reference to a polyfilled feature inside the library must use the imported binding. Relying on Array.prototype.flat or globalThis.Map after importing core-js-pure will fail on runtimes that lack native support.
Before:
export function dedupe(items) {
return Array.from(new Set(items));
}
After:
import { ArrayFrom } from 'core-js-pure/es/array/from';
import { Set as PureSet } from 'core-js-pure/es/set';
export function dedupe(items) {
return ArrayFrom(new PureSet(items));
}
Adjust Babel and bundler configuration
@babel/preset-env with useBuiltIns set to 'usage' or 'entry' injects imports from the global core-js package by default. It does not rewrite those specifiers to core-js-pure paths. If your build currently relies on Babel to inject polyfills, you must either disable useBuiltIns and manage core-js-pure imports manually, or write a custom Babel plugin that rewrites core-js specifiers to their core-js-pure equivalents.
Do not combine global core-js and core-js-pure in the same bundle. Duplicate polyfills increase size and can cause prototype conflicts.
Verify isolation and bundle size
Run a smoke test that proves the polyfill works locally while globalThis stays untouched. Execute this in a terminal or CI shell:
node -e "const {Map}=require('core-js-pure/es/map'); const m=new Map(); m.set('k',1); console.log(m.get('k'), typeof globalThis.Map)"
On a runtime without a native Map, this prints 1 undefined, confirming the local binding works and the global was not created. On modern Node.js, where globalThis.Map already exists, verify identity instead: globalThis.Map !== Map should be true.
Next, inspect the bundle with a size analyzer. Confirm that only the targeted core-js-pure modules appear and that the root index was not accidentally imported.
Finally, execute the library's unit tests in an older Node.js runtime that lacks the native features you polyfilled. This confirms the imports activate where native support is missing.
Recovery and rollback
If the migration introduces regressions, remove the dependency and revert the source changes:
npm uninstall core-js-pure
Then restore the previous import statements from version control. If you accidentally mixed global core-js with core-js-pure, remove one of the two packages rather than trying to reconcile them at runtime.
Limitations to communicate to consumers
| Limitation | Practical impact |
|---|---|
| Consumer code must use explicit bindings | Application code that calls new Map() directly will not see the library's polyfills. |
| Server-side rendering and isomorphic code | Code that runs on both server and client must have polyfilled constructors passed explicitly to modules that expect globals. |
| Import paths are version-sensitive | core-js@3 uses es/ and features/; core-js@2 used library/ and fn/. Mixing majors causes resolution errors. |
Document these constraints in your library's README so consumers understand that core-js-pure provides scoped polyfills, not environment-wide patches.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.