core-js@3 一文读懂:拆出 3 个包的 polyfill 大重构,与 Babel 的深度联动
【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js
core-js@3 完成了一次彻底的重构:从单个大包拆成 3 个独立 npm 包,稳定功能与在途提案各归其位,并配合 Babel 7.4 让 polyfill 的注入变得更精准、体积更小。
先看它到底解决了什么问题
core-js 是 JavaScript 标准库的"模块化 polyfill":当目标引擎缺少新版标准库能力(Promise、Set 的新方法、字符串填充等)时,它只在缺失或实现有缺陷的地方补位,其余情况直接用原生实现。它的两个关键卖点是粒度可控——按模块加载而非整包引入,以及一个不污染全局命名空间的 pure 版本可选。也正因如此,它成了事实上的标准库 polyfill 基座:大量项目其实是通过 Babel 间接在使用它,只是很多人没意识到。
本版更新全景:四类你能直接感知的变化
1️⃣ 语言标准补齐:新增 4 项稳定能力
core-js@3 最直观的增量,是稳定 ECMAScript 标准库的补齐。
- 为所有用到
@@isConcatSpreadable和@@species的方法补上了这两个 ES2015 已定义、此前未覆盖的符号支持(它们控制 concat 的展开行为和 map/slice 等派生结果的构造方式)。 - 收录 ES2018 的
Array.prototype.flat/flatMap,取代 core-js@2 里旧版提案形态的flatten。 - 收录 ES2019 的
Object.fromEntries。 - 收录 ES2019 的
Symbol.prototype.description访问器。 - 顺带修复了一批浏览器实现缺陷,例如 Safari 12.0 的
Array.prototype.reversebug。
2️⃣ 在途提案落地:一部分已经晋级为正式标准
此前还在"讨论中"的一批提案在本版大量落地,其中若干如今已经走到 stage 4(正式进入标准)。
globalThis:统一的全局对象引用(现 stage 4)。Promise.allSettled:等待一组 Promise 全部完成并收集各自结果(现 stage 4)。- 新 Set 方法(union、intersection、difference 等,stage 2)。
- 一批集合新方法(如
Map.groupBy,stage 1)。 String.prototype.replaceAll(现 stage 3)与String.prototype.codePoints(stage 1)。Array.prototype.lastItem/lastIndex(stage 1)。Promise.any(含配套的AggregateError,现 stage 3)。
3️⃣ 拆成 3 个包 + 模块命名规范化
包拆分是本版最影响使用方式的结构变化,动机是旧包约 2MB 且内部文件大量重复。
core-js:定义全局 polyfill 的主包,约 500KB。core-js-pure:不污染全局环境的版本,相当于 core-js@2 时代的core-js/library。core-js-bundle:打包后的全局版,便于浏览器直接引入。
命名规则也换了:2014 年沿用的es6./es7.前缀退役,稳定 ECMAScript 功能统一为es.前缀,在途提案统一为esnext.前缀。同时 CommonJS 入口点数量大幅增加,粒度更细,可以只引入某个构造器甚至某个方法。
4️⃣ 配套工具链与行为调整
除功能外,这一版还调整了 core-js 的"使用方式"与"维护方式",详见 使用文档。
- 新增 polyfill 侵入等级配置:默认只在功能缺失或有缺陷时补位,但你可以按功能改写策略——某些场景下特性检测过于严格(例如 Promise 的 polyfill 要求未处理拒绝追踪和
@@species均可用),或环境存在检测覆盖不到的已知缺陷,都可以显式指定强制用 polyfill 或仅原生完全缺失时才补。 - 移除过时与非标准内容:
Reflect.enumerate、System.global、asap、Array.prototype.flatten等被移除,分别由globalThis、queueMicrotask、flat接替;此前残留的非标准工具功能也全部清除,从这一版起 core-js 才算得上"纯粹的 polyfill"。 - 彻底告别 LiveScript:core-js@2 的测试与工具链还在用这种 CoffeeScript 风格的语言,是劝退贡献者的门槛之一;@3 全部改用现代 ES 语法重写。
- 新增
core-js-compat数据工具:为 Babel 等工具提供"目标引擎需要哪些模块"的判断数据,后面会展开。 - Web 标准侧:完整实现
URL与URLSearchParams(长期呼声最高的需求,也是 @3 开发中难度最高的部分之一);新增标准微任务 APIqueueMicrotask(取代旧版的asap);为 DOM 集合补上.forEach。
与 Babel 的协作:三个集成点要理清
@babel/polyfill的替代写法
最直接的破坏性变化:@babel/polyfill已弃用——它本质上只是"stable core-js + regenerator-runtime"的转发壳,且为向后兼容仍基于 core-js@2,无法平滑过渡到 @3。等价的替代是两行直接引入:
import "core-js/stable"; import "regenerator-runtime/runtime";记得把这两个依赖直接装进项目。
@babel/preset-env的corejs选项与数据源
useBuiltIns生效的前提是显式声明版本:corejs选项指定项目使用的 core-js 版本,不设置时默认按 2 处理并给出警告,新项目应设为 3。
数据源是另一个重要变化:过去 preset-env 依赖 compat-table,它只覆盖 ES 特性、缺少 Web 平台功能(如setImmediate、DOM 集合迭代器)和引擎 bug 信息,结果是目标环境明明支持也会照加。现在改用core-js-compat提供的数据,判断更贴近真实支持情况。同时 7.4 修复了历史注入顺序问题:只在确定需要时注入,且按推荐顺序添加。
entry 与 usage 两种模式的取舍
两者的分工可以一句话概括:entry 改写你已有的导入,usage 按文件自动补导入。
useBuiltIns: 'entry':把你写的所有 core-js 入口替换为目标环境真正需要的最小模块集。例如:
import "core-js/es"; import "core-js/proposals/set-methods";以 chrome 71 为目标时,会被收敛为 flat/flatMap 的 unscopables、es.object.from-entries、web.immediate等寥寥数条模块导入。
useBuiltIns: 'usage':扫描每个文件实际用到的特性,只在目标环境不支持时于文件头部自动插入对应模块。Babel 7.4 让这一模式变得可靠:属性访问、解构、in操作符等场景的检测更准确,且能识别语法特性并注入配套 polyfill(如for-of注入迭代器、动态import注入 Promise)。默认不注入提案,可用corejs: { version: 3, proposals: true }开启。注意 usage 模式下不要自己再手写 core-js 导入。
@babel/runtime:不污染全局的路线
如果项目要求零全局污染,用corejs: 3选项让@babel/runtime走@babel/runtime-corejs3(即基于 core-js-pure)。它在本版补齐了短板:
- 支持实例方法 polyfill,过去
array.includes(x)这类调用无法被正确编译,现在可以。 - 通过
corejs: { version: 3, proposals: true }开启提案 polyfill。 - 修复了一批历史问题,典型如手动给对象挂载
Symbol.iterator的写法在 corejs2 下不被识别,corejs3 已支持。 - 提醒:preset-env 与 runtime 同时使用时,
corejs选项只在一处声明,重复声明会产生冲突。
分场景行动清单
- 要不要升级:core-js@2 已功能冻结一年半,
flat、Object.fromEntries、Set 新方法等只能从 @3 获得;只要项目还在用@babel/polyfill,迁移就是必选项。 - 如何控体积:entry 模式配合精确的 browserslist 目标最稳妥——你写入口、工具算最小集;usage 模式更省但依赖静态分析。
corejs建议显式写小版本号(如'3.50')而不是笼统的 3,否则小版本新增的模块不会注入。 - 老项目迁移注意:把
@babel/polyfill换成两行引入;modules/路径是内部 API,仅供自定义构建,不要在业务代码里直接引用;若走全局扩展路线,把 core-js 模块统一放在入口顶部,避免与第三方库自带实现(如某些地图 SDK 自管的Symbol.iterator)互相覆盖;浏览器场景务必经打包器引入,模块粒度太细,逐文件裸载会产生海量请求。 - 何时动 configurator:默认特性检测能满足绝大多数场景,只有"检测太严"或"环境有未覆盖的坑"时才按功能改写
useNative/usePolyfill,改动过大会让 core-js 内部机制也不可靠。
写在最后
core-js@3 的意义不止于多了一批 polyfill:三包拆分、es./esnext.命名规范、core-js-compat数据源与 Babel 7.4 的组合,让"按目标环境决定加载什么"第一次有了完整的工具链支撑,这也成为后来各类转译工具对接 polyfill 能力的基础。对普通前端项目,可执行的结论只有三句:把corejs设为 3、按团队习惯选 entry 或 usage、用目标环境配置把体积交给工具去算。
【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考