Avoiding Global Pollution with core-js@3 Pure Mode
Stop bloating your bundles and polluting the global scope. Learn how to use core-js/pure to implement tree-shakable polyfills for modern JavaScript environments.
12 Mar 2026, 09:28 UTC

The problem: Global pollution and bundle bloat
Most polyfill strategies work by modifying the global prototype. For example, if you polyfill Array.prototype.flat, the library adds that method to the global Array object. While convenient for applications, this is dangerous for library authors because it forces a specific behavior on every user of the library, potentially causing collisions or unexpected bugs in the consumer's environment.
Furthermore, importing a monolithic polyfill bundle often includes code for features you never use, increasing the time it takes for a user's browser to download and parse your JavaScript.
The solution: core-js/pure
The core-js/pure export provides a "non-global" version of polyfills. Instead of modifying Array.prototype, it provides a helper function that implements the logic. When your code is compiled, the modern method call is replaced with a call to this helper.
This approach enables tree-shaking—the process where a bundler removes unused code. Because each polyfill is a separate module, your final bundle only contains the specific logic for the ES2020+ features you actually invoked in your source code.
How the transformation pipeline works
- Detection: A compiler like Babel scans your code for modern features (e.g.,
Object.fromEntries). - Mapping: Based on your target environment (e.g., Chrome 60), Babel determines if a polyfill is required.
- Injection: Instead of adding a global import, Babel transforms the code to import a specific module from
core-js/pure. - Pruning: The bundler (Webpack or Rollup) sees which
core-js/puremodules are referenced and discards the rest of the library.
Worked Example: Babel and Webpack Configuration
To implement this, you need @babel/preset-env and core-js@3. The following configuration demonstrates how to trigger the "pure" transformation. This example illustrates the required pattern; it has not been live-tested in a specific environment.
// babel.config.json
{
"presets": [
[
"@babel/preset-env",
{
"targets": "> 0.25%, not dead",
"useBuiltIns": "usage",
"corejs": 3
}
]
]
}
// webpack.config.js
module.exports = {
mode: 'production',
entry: './src/index.js',
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: { loader: 'babel-loader' }
}
]
}
};
Key configuration details:
useBuiltIns: 'usage': This is the critical setting. It tells Babel to add imports for polyfills only where they are used in the code, rather than importing the entire library at the entry point.corejs: 3: Specifies the version of core-js to use, ensuring compatibility with ES2020+ features.
Limitations and Trade-offs
Pure mode is not a silver bullet. Some runtime features, such as Atomics or SharedArrayBuffer, cannot be polyfilled as pure functions because they rely on low-level engine capabilities. In these cases, you may need to manually register symbols or accept that certain environments simply cannot support the feature.
Additionally, because pure mode avoids global modification, it cannot polyfill features that are required by third-party dependencies that expect those features to exist globally. If a dependency relies on Promise.allSettled being on the global Promise object, core-js/pure will not satisfy that requirement.
Verification and Diagnostics
To ensure your polyfills are actually being tree-shaken and not globally injected, follow these steps:
- Bundle Analysis: Run your build with a tool like
webpack-bundle-analyzer. Search the output forcore-js. You should see individual files (e.g.,core-js/modules/es.array.flat.js) rather than one massivecore-js.jsfile. - Runtime Check: Load your application in an older browser (e.g., an older version of Firefox or IE11). Open the developer console and check if the global object was modified. For example, if you used
Array.prototype.flat, typingArray.prototype.flatin the console should returnundefined, while your application code still functions correctly. - Version Alignment: Check your
package.jsonto ensurecore-jsis at version 3.x. Version 2.x does not support this modular pure mode and will result in global pollution.
Actionable Closing
If you are building a library or a performance-critical application, switch to core-js/pure via @babel/preset-env. Set useBuiltIns to 'usage' and corejs to 3. This ensures your users only download the code they need and prevents your library from interfering with the global environment of the applications that consume it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.