Preventing Global Pollution: Choosing Between Core-js Entry and Pure Polyfills
Learn the critical difference between core-js 'entry' and 'pure' polyfilling strategies to avoid global namespace pollution in JavaScript libraries.
26 May 2026, 09:37 UTC

The Global Namespace Conflict
When you add a polyfill to a JavaScript project, you are essentially filling a gap in the browser's capabilities. However, most polyfills work by modifying global prototypes—for example, adding Array.prototype.includes if it doesn't exist. While this is convenient for application developers, it creates a critical problem for library authors: Global Pollution.
If your npm package modifies Array.prototype, every other library in the consumer's project now inherits that change. If the consumer is using a different version of the same polyfill, or a custom implementation, your library can cause unpredictable crashes or subtle bugs in code you don't even own. The technical challenge is providing modern JS functionality without touching the global environment.
The 'Entry' Approach: Global Modification
The standard core-js entry method is designed for final applications. It assumes the application owns the entire environment. By importing core-js/stable, you ensure that every single piece of code running in the browser—including third-party scripts—has access to the same standardized APIs.
This is typically managed via @babel/preset-env using the useBuiltIns: 'entry' setting. Babel replaces a single import with a list of specific polyfills required by your target browser list. This ensures compatibility but risks conflicts if multiple versions of the library are bundled into the same page.
The 'Pure' Approach: Non-Polluting Polyfills
For library authors, core-js-pure (or the @babel/plugin-transform-runtime with corejs: 3) is the correct choice. Instead of modifying Array.prototype.includes, it provides a version of the function that you import and call explicitly.
In a pure implementation, the polyfill does not touch the global object. It creates a local alias for the feature. This means your library remains isolated, and the consumer's environment remains untouched.
Implementation Comparison
Consider the difference in how you would implement a simple array check in a library versus a standalone application.
Application Style (Global Pollution)
// In your main entry file
import 'core-js/stable';
// Anywhere else in the app
const hasItem = [1, 2, 3].includes(2); // Works because the prototype was modified globally
Library Style (Pure/Non-Polluting)
// Import the specific feature from the pure version
import includes from 'core-js-pure/features/array/includes';
const items = [1, 2, 3];
// We pass the object as the first argument instead of calling it as a method
const hasItem = includes(items, 2);
The Trade-off: Ergonomics vs. Safety
The primary limitation of the pure approach is ergonomics. You cannot use the natural dot-notation (e.g., array.includes()) because that requires the prototype to be modified. You must wrap every call in a helper function.
| Feature | Entry (Global) | Pure (Non-Polluting) |
|---|---|---|
| Target User | App Developers | Library/Package Authors |
| Syntax | obj.method() | method(obj) |
| Global Scope | Modified | Untouched |
| Bundle Size | Potentially larger (global) | Modular (only what you import) |
Verifying Your Bundle
To ensure your library isn't accidentally polluting the global scope, you can run a simple check in your test environment or a browser console after loading your bundle:
- Load your library in a clean browser tab.
- Check a prototype that your library uses, such as
Array.prototype.includes. - If the function exists in a browser that natively doesn't support it (or if you've manually deleted it for the test), and your library didn't explicitly intend to polyfill the global scope, you have a pollution leak.
If you are using Babel, check your .babelrc or babel.config.js. If you see @babel/plugin-transform-runtime with corejs: 3, Babel is automatically replacing global references with pure imports during the transpilation process.
Final Decision Logic
If you are building a website or a standalone app, use the entry method via preset-env to keep your code clean and readable. If you are building a package for others to install, use core-js-pure to ensure your library is a good citizen in the consumer's ecosystem.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.