美文网首页程序员
一文说尽 Babel 的前世今生

一文说尽 Babel 的前世今生

作者: LightiSnow | 来源:发表于2020-11-30 18:05 被阅读0次

作者: 多巴胺

一、Babel 是什么

Babel 是一个可以将 使用ES2015+语法的代码 编译成 向后兼容 的代码的工具。当我们使用 EcmaScript 较高版本的 Javascript 语法特性的时候,将所写代码转换成兼容 ES5 的代码,目的支持尽可能多的平台。对于转换的规则,主要有分为以下两类:

  • Sytanx类型。例如箭头函数、const/let 等语法特性,babel 可以通过各种插件实现兼容。
  • 运行时api。例如数组的静态方法Array.from()、实例方法 arr.includes() 等,需要引入 corejs 作为 polyfill(垫片),从而能够在运行时提供支持。

二、功能模块构成

  • 核心库——@babel/core

@babel/core 模块是一个可以完成代码字符串转换的库,babel所有的插件都是通过核心库来进行开发和加载的,如下是官方给的使用示例:

const babel = require("@babel/core");

babel.transform("code", optionsObject);
  • 命令行工具——@babel/cli

当我们使用核心库的时候,一般不直接再代码中调用@babel/core提供的api,而是使用bable提供的命令行工具来进行源代码的转换。一般我们在使用的时候,将其作为 package.json 文件的一个 scripts 脚本进行配置,用于对指定文件夹的 js 语言做转换。例如以下示例,当我们运行 npm run babel,即可将根目录的 src 目录下所有的 js 文件进行转换,完成后放置于根目录 dist 下。

  "scripts": {
    "babel": "babel src --out-dir dist"
  },

babel 的语法转换功能依赖于各种插件。比如当我们使用箭头函数转换的插件 @babel/plugin-transform-arrow-functions ,当我们配置此插件后,源代码中的箭头函数将会被转换成普通的 Javascript 函数。

// 源代码
const print = (a) => console.log(a)

// 目标代码
var print = function print(a) {
  return console.log(a);
};
  • 插件集合——Presets

顾名思义,preset(预装置)就是多个插件的集合。例如,当我们的开发场景中需要使用箭头函数和可选操作符,那么我们可以将 @babel/plugin-transform-arrow-functions 和 @babel/plugin-proposal-optional-chaining 进行组合形成一个preset,当我们再次遇到需要使用箭头函数和可选操作符的转换场景的时候,直接使用此 preset,不必要在单个配置 Plugin。
官方提供了四个Presets,其中 @babel/preset-env 是我们常用的 preset,它提供了最新的 Javascript 语法转换,使用它,可以做到 Makes your life easier!

  • 配置文件——推荐以 js 的形式

上文的介绍中,有很多的具体配置,那我们在什么地方进行 Plugin/Presets 的配置呢?官方给了多个文件类型和多个不同的文件,此处推荐使用 babel.config.js——即在根目录下创建 babel.config.js 并在其中导出 presets 和 plugins 对象。
当我们使用 Javascript 进行配置的时候,拥有更多的控制能力。可以以代码的方式控制在不同目标环境下应用不同的语法转换规则。

// 根目录下的 babel.config.js 文件中的内容

const plugins = [
    '@babel/plugin-transform-arrow-functions',
    '@babel/plugin-proposal-optional-chaining'
]

const presets = [
    ['@babel/env', {
        useBuiltIns: 'usage',
        corejs: 3
    }]
]

module.exports = { plugins, presets }

三、Babel 的具体配置规则

在使用 babel 之前,我们首先安装 @babel/core, @babel/cli,命令如下:

npm install --save-dev @babel/cli @babel/core

在你项目的编译脚本中,添加如下脚本配置:

  "scripts": {
    "babel": "babel src --out-dir dist"
  },

1. 仅做 Syntax 转换

当我们仅仅只想尝试某一个新的 Javascript 语法特性的时候,可以直接安装对应语法特性的 Plugin,例如当我们使用可选操作符 ( ?. ) 的时候,我们就可以安装 @babel/plugin-proposal-optional-chaining。

npm install --save-dev @babel/plugin-proposal-optional-chaining

之后,再更目录下创建 .babel.js 文件,写入此 Plugin 的配置并导出。

const plugins = [
    '@babel/plugin-transform-arrow-functions',
]

module.exports = { plugins }

那么,我们尝试使用会发现,转换成功了。

// 源代码
const baz = obj?.foo?.bar?.baz;

// 转换后
var baz = obj === null || obj === void 0 ? void 0 : (_obj$foo = obj.foo) === null || _obj$foo === void 0 ? void 0 : (_obj$foo$bar = _obj$foo.bar) === null || _obj$foo$bar === void 0 ? void 0 : _obj$foo$bar.baz;

2. 推荐用法

为了尽量少的关心插件,我们可以使用官方提供的 @babel/preset-env。当我们配置此 Preset 时,让 babel 同时支持 Syntax 层面和 built-ins 层面的转化。为了支持 built-ins 转换,我们需要添加 useBuiltIns 的配置,具体步骤如下:

// 安装 @babel/preset-env
npm install --save-dev @babel/preset-env
// 安装 @core-js@3
// 由于 built-in 是运行时环境的依赖,所以要使用 --save
npm install --save core-js@3

// .babel.js 配置
const presets = [
    ['@babel/env', {
        // 此配置项的值可以配置为 entry/usage
        // entry: 注入目标环境不支持的所有 built-in 类型语法
        // usage: 注入目标环境不支持的所有被用到的 built-in 类型语法
        useBuiltIns: 'usage',
              // built-in 需要 corejs 的支持。corejs3 支持对象的实例方法
        corejs: 3
    }]
]

module.exports = { presets }

3. @babel/plugin-transform-runtime

使用此插件的原因主要有两个:

  • 默认情况下,babel 再做 built-in 类型的转换时,会在源代码每个文件里面引入 core-js 的 helper 函数,有时这是没有必要的。当使用 @babel/plugin-transform-runtime 时,所有的 helpers 都只会引 @babel/runtime。
  • 此插件可以提供一个运行的沙箱环境。如果直接使用 core-js,那对于 Promise、Set 等对象,都会污染全局作用域。如果你现在开发的是一个工具包,你使用了 core-js 提供了 Promise、Set 的语法转换。当别人在他的项目里引入了你的工具包,恰恰他的项目中已经实现了 Promise、Set 等函数,这就会导致复杂的冲突问题。

配置如下所示:

// 安装 @babel/plugin-transform-runtime
npm install --save-dev @babel/plugin-transform-runtime

// 安装生产环境依赖
// 此处和是否使用 core-js 及 core-js 版本有关
// corejs: false
npm install --save @babel/runtime
// corejs: 3 以下配置示例中的 corejs 版本
npm install --save @babel/runtime-corejs3
// corejs: 2
npm install --save @babel/runtime-corejs2

// .babel.js 配置详情
// 这是在 nodejs 配置中推荐的使用方式
const plugins = [
    ['@babel/plugin-transform-runtime', {
        corejs: 3
    }]
]

// 此处需要注意,当我们使用了 @babel/runtime-corejs2,原先的 corejs@3 便不需要使用了
const presets = [
    ['@babel/env']
]

module.exports = { plugins, presets }

相关文章

网友评论

    本文标题:一文说尽 Babel 的前世今生

    本文链接:https://www.haomeiwen.com/subject/qwhdwktx.html