一文搞懂 core-js@3、@babel/polyfill、@babel/runtime、@babel/runtime-corejs3 的作用与区别

6,626 阅读3分钟

前言

之前没有自己搭建过前端项目,在熟悉已有项目的过程中看到 package.json里关于 babel 的依赖就有这么多,他们分别都是干嘛的呢?每次搭建项目都需要这些依赖吗?

image.png

文末会列出各种配置所需要安装的库和配置文件。如有不对,希望指正。

babel 的作用

babel 为了解决 js 在不同浏览器的兼容问题,主要是语法和 API 这两个兼容问题。

plugin 与 preset

babel 将很多的语法转换交给了一个个 plugin 处理,例如 @babel/plugin-transform-arrow-functions 这个插件可以转换箭头函数语法,但是为了不需要手动一个个添加,所以提供了@babel/preset-env,可以理解成 preset 包含了很多 plugin 。所以只需要配置一个 preset 就可以转换成浏览器支持的语法了。

core-js + regenerator-runtime = @babel/polyfill

要使用浏览器不支持的 API 可以自己写一些模拟函数,这些模拟函数叫做 polyfill。要使用Promise 或 WeakMap 等新内置函数、Array.from 或 Object.assign 等静态方法、Array.prototype.includes 等实例方法需要 core-js@3 这个库。要使用生成器函数(function* )需要 regenerator-runtime 这个库。

为了使用这些函数,需要在 babel 的配置文件(见文末)配置 @babel/preset-env。其中有一个参数是 useBuiltIns ,它有三个值:1,默认是 falsefalse 的作用是不使用 polyfill;2,uasge 的作用是自动且按需引入用到的 polyfill;3,entry 的作用是全量引入 polyfill,需要要入口文件手动引入 import "core-js";import 'regenerator-runtime/runtime';

@babel/polyfill 这个库已经不推荐使用了,简单提一下。它实际上就是 core-js@2 + regenerator-runtimecore-js@2 也不推荐使用,现在单独安装和引用 core-js@3regenerator-runtime 就行。

@babel/runtime 抽离公共辅助函数

babel 生成的代码会有一些辅助函数,例如 _createClass 函数,这些函数在每个文件里面都会重复生成,所以可以把重复函数抽取出来,然后每个文件引用即可,这样就可以减少生成的代码体积。这些函数被抽取到 @babel/runtime 这个库里。为了自动使用 @babel/runtime 里的函数,还需要 @babel/plugin-transform-runtime 插件。

抽取前如下: image.png

抽取后如下: image.png

可以看到 regenerator 使用的是 @babel/runtime/regenerator,所以如果用了 @babel/runtime 应该就不需要自己手动单独安装 regenerator-runtime

@babel/runtime-corejs3 避免污染全局环境。

使用 core-js@3 来 polyfill,会全局引入缺少的 API,例如 require("core-js/modules/es.promise.js")。有时候开发工具库,希望避免 polyfill 污染全局变量。这时候可以不使用 core-js@3 来 polyfill,转而使用 @babel/runtime-corejs3@babel/runtime-corejs3 相当于 @babel/runtime + 不污染环境的 core-js@3

使用 @babel/runtime-corejs3 后如下,可以看到 _promise 不是一个全局变量:

image.png

总结

根据以上的理解,其实一般有两种配置,一种是 @babel/preset-env + @babel/runtime + core-js@3,普通的项目不怕污染全局环境可以用这个配置;另外一种是 @babel/preset-env + @babel/runtime-corejs3,开发工具类库为了不污染全局环境可以用这个配置。

配置一: @babel/preset-env + @babel/runtime + core-js@3

安装脚本:

npm install --save-dev @babel/cli @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm install --save @babel/runtime core-js@3

babel.config.json 配置文件

{
    "presets": [
      [
        "@babel/preset-env", {
          "useBuiltIns": "usage",
          "corejs": 3
        }
      ]
    ],
    "plugins": [
      ["@babel/plugin-transform-runtime"]
    ]
}

配置二: @babel/preset-env + @babel/runtime-corejs3

安装脚本:

npm install --save-dev @babel/cli @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm install --save @babel/runtime-corejs3

babel.config.json 配置文件

{
  "presets": [
    [
      "@babel/preset-env"
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime", {
        "corejs": 3
      }
    ]
  ]
}

vue-cli 如何配置 babel?

先来看看依赖文件 @vue/babel-preset-app/package.json

image.png

babel 的配置是通过代码生成的 @vue/babel-preset-app/index.js

image.png

可以看到 vue-cli 生成的项目是类似于配置一的。