公众号

前言

或者你可能不晓得core-js仓库,不过肯定在我的项目中间接或间接地应用过它

core-js仓库 是一个 JavaScript 规范库,它蕴含了 ECMAScript 2021 在内的多项个性的 polyfill,以及 ECMAScript 在 proposals 阶段的个性、WHATWG/W3C 新个性等。

core-js仓库和 Babel有一些关联,把握了core-js,能帮忙你更好地了解 babel 生态。同时,通过对 core-js 的解析,能够更好的深刻理解polyfill(垫片/补丁)

core-js仓库目前最新的版本是core-js@3.x.x

官网不举荐持续应用core-js@2.x.x,core-js@3.x.x有更丰盛的polyfill,和Babel联合会有更好的将来。上面介绍的内容都是指的core-js@3的版本。

指标

带着一下问题去找答案

  • core-js仓库是什么?
  • core-js仓库外面三个不同版本的区别是什么?

core-js 仓库

core-js 是一个由 Lerna 搭建的 Monorepo 格调的我的项目,在它的 packages 文件夹中有五个包:

  • package/core-js
  • package/core-js-pure
  • package/core-js-bundle
  • package/core-js-compact :保护了依照browserslist标准的垫片需要数据,来帮忙咱们找到“合乎指标环境”的 polyfills 需要汇合
  • package/core-js-builder :能够联合 core-js-compact 以及 core-js,并利用 webpack 能力,依据需要打包出 core-js 代码
    上面具体介绍一下 core-js,core-js-pure,core-js-bundle区别。上面是官网文档中的例子:
// global versionnpm install --save core-js@3.13.0// version without global namespace pollutionnpm install --save core-js-pure@3.13.0// bundled global versionnpm install --save core-js-bundle@3.13.0

global version

翻译:全局版本。package/core-js中polyfill的代码会间接批改全局变量,净化全局变量。咱们看一个Promise的例子:

import 'core-js/features/promise'Promise.resolve(32).then(x => console.log(x));

core-js/features/promise是对浏览器的全局window对象进行了从新赋值,重写了window的Promise及其原型链。

全局版本有两种应用形式:

第一种形式:只在我的项目入口文件中,手动引入core-js。例如:

import 'core-js'; // <- at the top of your entry pointArray.from(new Set([1, 2, 3, 2, 1]));          // => [1, 2, 3][1, [2, 3], [4, [5]]].flat(2);                 // => [1, 2, 3, 4, 5]Promise.resolve(32).then(x => console.log(x)); // => 32

第二种形式在入口文件手动按需引入须要的polyfill

import 'core-js/features/array/from'; // <- at the top of your entry pointimport 'core-js/features/array/flat'; // <- at the top of your entry pointimport 'core-js/features/set';        // <- at the top of your entry pointimport 'core-js/features/promise';    // <- at the top of your entry pointArray.from(new Set([1, 2, 3, 2, 1]));          // => [1, 2, 3][1, [2, 3], [4, [5]]].flat(2);                 // => [1, 2, 3, 4, 5]Promise.resolve(32).then(x => console.log(x)); // => 32

version without global namespace pollution

翻译:不净化全局变量的版本。 package/core-js-pure 提供了不净化全局变量的垫片能力,然而在应用的时候,不能一次性引入所有的polyfill,必须依据每个文件的须要,独自引入须要的modules。例如:

import from from 'core-js-pure/features/array/from';import flat from 'core-js-pure/features/array/flat';import Set from 'core-js-pure/features/set';import Promise from 'core-js-pure/features/promise';// 留神这里必须是form()这种形式调用,而不是[].from形式。这是和package/core-js 的区别from(new Set([1, 2, 3, 2, 1]));                // => [1, 2, 3]flat([1, [2, 3], [4, [5]]], 2);                // => [1, 2, 3, 4, 5]Promise.resolve(32).then(x => console.log(x)); // => 32

相似Array.from,Array.prototype这种在内置对象或内置类上扩大出的新的实例办法或静态方法,都不能依照实例办法或静态方法间接调用,必须像from(new Set([1, 2, 3, 2, 1]));这种形式应用。

bundled global version

翻译:打包好的全局版本package/core-js-bundle是曾经编译打包好的版本,蕴含全副的polyfill,能够在浏览器外面通过script形式间接加载。

CommonJS API

官网文档有一个上面的例子。列举了很多应用polyfill的形式。

// polyfill all `core-js` features:import "core-js";// polyfill only stable `core-js` features - ES and web standards:import "core-js/stable";// polyfill only stable ES features:import "core-js/es";// if you want to polyfill `Set`:// all `Set`-related features, with ES proposals:import "core-js/features/set";// stable required for `Set` ES features and features from web standards// (DOM collections iterator in this case):import "core-js/stable/set";// only stable ES features required for `Set`:import "core-js/es/set";// the same without global namespace pollution:import Set from "core-js-pure/features/set";import Set from "core-js-pure/stable/set";import Set from "core-js-pure/es/set";// if you want to polyfill just required methods:import "core-js/features/set/intersection";import "core-js/stable/queue-microtask";import "core-js/es/array/from";// polyfill reflect metadata proposal:import "core-js/proposals/reflect-metadata";// polyfill all stage 2+ proposals:import "core-js/stage/2";

第一次看下面代码,一脸懵逼,core-js/es,core-js/web,core-js/proposals,core-js/stable,core-js/features,core-js/stage这些都是啥玩意?为什么还有等价关系?。

于是看了一下core-js仓库文件夹构造,如下:

因为文件目录太长,这里只列出1级目录构造
tree -L 1# 输入后果├── LICENSE├── README.md├── configurator.js├── es├── features├── index.js├── internals├── modules├── package.json├── postinstall.js├── proposals├── stable├── stage└── web

core-js仓库的源码构造,展现了命名空间对应的文件夹。并且每个namespace上面都有一个index.js

  • core-js/index.js 等同于 import 'core-js'
  • core-js/es 等同于 core-js/es
    .....
    ....

咱们看一下 core-js/index.js的源码

module.exports = require('./features');

./features文件夹上面的index.js

//require('../modules/es.*require('../modules/es.symbol');require('../modules/es.symbol.description');........//require('../modules/esnext.*');require('../modules/esnext.aggregate-error');require('../modules/esnext.array.at');........//require('../modules/web.*');require('../modules/web.dom-collections.for-each');require('../modules/web.dom-collections.iterator');........module.exports = require('../internals/path');

通过查看源码,得悉了 import "core-js"等价于

import "core-js/es";import "core-js/web";import "core-js/proposals";

其它的等价关系,都能够从源码里看的一清二楚。

package/core-js的polyfill,底层的机制都是由internalsmodules外部的module来实现的。官网不举荐间接我的项目中间接应用这两个文件夹的module,因为它们是外部实现,很可能在版本迭代中发生变化

package/core-js-pure的源码与package/core-js仅仅只有internals和modules两个文件夹有区别,其它的都是一样的。关上下面的源码库看到core-js-pure外面只有一个overrides文件夹,蕴含了internals和modules两个文件夹。很容易就能猜到,core-js-pure这个包是在复制了core-js的包根底上,而后笼罩了internals和modules之后失去的。

与Babel配合应用

官网文档中列举了

  • @babel/polyfill
  • @babel/preset-env
  • @babel/runtime

这里先不介绍一下,前面两个章节《如何Babel的配置文件,设计一个“最完满”的 Polyfill 计划》分享中具体形容。

参考文献

  • core-js官网
  • core-js 及垫片理念(这篇文章为拉钩付费文章,无奈分享链接)