Global Build vs. Ponyfill: Choosing core-js for Libraries
0 reputation · 25 Mar 2022, 12:09 UTC
0 reputation · 25 Mar 2022, 12:09 UTC
When integrating core-js into a reusable library, the goal is to provide modern JavaScript features without altering the consumer’s runtime. The library must avoid polluting global prototypes while still offering a stable API for downstream projects. The main uncertainty lies in selecting between the global build (core-js) that patches built‑ins and the ponyfill build (core-js-pure) that exports features as plain modules.
Constraints include:
Unresolved questions:
For a library that must not alter the consumer’s runtime, the core-js-pure ponyfill is the recommended build. It exports features as plain modules, guarantees no prototype mutation, and still allows granular imports for tree‑shaking.
core-js patches built‑ins (e.g., Promise.prototype.then), which can clash with other polyfills or native implementations.core-js-pure never touches global objects, so the consumer’s environment remains unchanged.core-js-pure/es/array/map), enabling bundlers to drop unused polyfills.core-js-pure mirrors that of core-js, so upgrading to newer releases does not introduce new side‑effects.core-js multiple times can overwrite earlier polyfill definitions, leading to unpredictable behavior.Both builds expose every feature as a separate module. Example imports:
// core‑js‑pure (ponyfill)
import { map } from 'core-js-pure/es/array/map';
// core‑js (global)
import 'core-js/es/array/map'; // mutates Array.prototype
When bundling with Rollup or Webpack, the pure import will appear as a direct dependency, while the global import will be treated as a side‑effectful script that may be included even if unused.
Both packages maintain the same feature set. Switching from core-js to core-js-pure (or vice versa) requires only a change in import paths; no API differences exist for the exported modules.
const nativeMap = Array.prototype.map;
import { map } from 'core-js-pure/es/array/map';
console.assert(Array.prototype.map === nativeMap, 'Prototype was mutated');
For the global build, the same test should reveal a change in the prototype, confirming the mutation.
If the library’s public API requires that consumers have a certain polyfilled built‑in (e.g., Array.flat must exist for internal logic), you must either document this requirement or provide a global polyfill yourself. In that case, keep the global build isolated and ensure it is the only source of prototype mutation.
Does your library need to expose any polyfilled built‑ins (e.g., Array.flat) to consumers? If yes, a global build or a consumer‑side polyfill may be required; otherwise, stick with core-js-pure.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.