一、Babel 是什么

Bebal 可以帮助我们将新 JS 语法编译为可执行且兼容旧浏览器版本的一款编译工具。
举个例子,ES6(编译前):

const fn = () => {};

ES5(编译后):

var fn = function() {}

二、Babel 的应用场景

想体验新 JS 语法带来的便捷和可读性,又希望能够向下兼容?Babel 可以帮你做到。
不仅如此,Babel 还支持解析 TSJSX 等多种语法,给 ES6/7/8/9 Typescript、React / Vue3 JSX 等"语法糖"带来无限的可能。

三、Babel 的基本使用

3.1 准备工作

  1. 新建项目:babel-demo
  2. 初始化 npm
  3. 安装 Babel 相关依赖包

命令流程如下:

mkdir babel-demo && cd babel-demo && touch app.js
yarn init -y
yarn add @babel/core @babel/cli @babel/preset-env --dev

依赖包解释:

  • @babel/core 是 Babel 的编译核心工具。
  • @babel/cli 是 Babel 提供的脚手架,后面会用到并解释。
  • @babel/preset-env 集成了各种 plugin 插件,后面会用到并解释。

项目结构如下:
请添加图片描述

3.2 编译 JS

  1. 打开 app.js,添加如下代码:
const app = () => {
  const greeting = 'World' ?? 'Tony'
  console.log(`Hello,${greeting}`)
}
  1. babel-demo 终端执行 @babel/cli 提供的编译命令:
node_modules/.bin/babel app.js --out-dir lib

解释:–out-dir 表示编译的产物将会放到 lib 目录下。
如图:
. 请添加图片描述
代码与原来没有任何变化,这是因为我们还未配置任何 Babel 插件,所以 Babel 将原封不动输出。

  1. 指定 Babel 插件:
node_modules/.bin/babel app.js --out-dir lib --plugins=@babel/plugin-transform-arrow-functions

解释: --plugins 参数指定了 @babel/plugin-transform-arrow-functions 插件,该插件表示将 ES6 箭头函数转为 ES5。

结果:
请添加图片描述

你可能注意到 ?? 这个语法没有被转换,这是 ES2020 的语法,得借助另外一个插件来完成编译,这里就不演示了,留给大家一个小作业。

你可能好奇,@babel/plugin-transform-arrow-functions 插件不安装便能引用?这块后面会作解释。

3.3 编译 Vue 中的 JSX 语法

背景:Vue3 新增了 JSX 语法, 问题来了,Vue 怎样识别 JSX 语法?这还得得益于 Babel 提供的 @babel/plugin-syntax-jsx 插件,它可以分析 JSX 语法并导出 AST 树,但不负责 标签 转换工作,于是 Vue 在 @babel/plugin-syntax-jsx 的基础上新增了支持标签转换的 @vue/babel-preset-jsx 插件。

使用:

  1. 安装依赖:
yarn add @vue/babel-preset-jsx
  1. 调整 app.js 代码,改为 Vue JSX 写法:
const app = () => {
  const greeting = 'World' ?? 'Tony'
  return <div>
    {`Hello,${greeting}`}
  </div>
}
  1. 执行编译:
node_modules/.bin/babel app.js --out-dir lib --presets=@vue/babel-preset-jsx

解释:@vue/babel-preset-jsx 属于 presets ,得用 --presets 参数引入,可以临时理解为它也是 plugin,只是引用方式变了而已。

结果:
请添加图片描述
可以看到,成功将 <div> 标签转成 Vue 提供的 h 函数并传参(h = render )。

3.4 编译 React 中的 JSX 语法

背景:React 最大的特点就是提供了 JSX 写法,同时也是饱受争议的一个特点,这里不过多阐述。 React 也是基于 @babel/plugin-syntax-jsx 新增了 @babel/plugin-transform-react-jsx 插件,和 Vue 一样用来兼容标签的转换。

使用:

  1. 安装依赖:
yarn add @babel/plugin-transform-react-jsx --dev
  1. 调整 app.js 语法,改为 React JSX 语法:
const app = () => {
  const greeting = 'World' ?? 'Tony'
  return <div>
    {`Hello,${greeting}`}
  </div>
}

提示:写法跟 Vue JSX 没啥区别,只有编译结果有区别。

  1. 执行编译:
node_modules/.bin/babel app.js --out-dir lib --plugins=@babel/plugin-transform-react-jsx

结果:
请添加图片描述
还是那股熟悉的的配方,熟悉的味道~

四、Bebel 配置

每次编译都要用 --plugins--presets 指定插件太麻烦了,就像 Eslint/Typescript 那样,Babel 同样支持以配置文件的方式,只需在根目录下新建 babel.config.json 即可。

注意:如果你使用的 Babel 版本低于 v7.8.0,请用 babel.config.js 格式。

4.1 将上面的插件引入配置中

  1. @babel/plugin-transform-arrow-functions
// babel.config.json
{
	"plugins": [
    	["@babel/plugin-transform-arrow-functions"]
  	]
}
  1. @vue/babel-preset-jsx
// babel.config.json
{
  "presets": [
    ["@vue/babel-preset-jsx"]
  ],
  "plugins": [
    ["@babel/plugin-transform-arrow-functions"]
  ]
}
  1. 执行编译:
node_modules/.bin/babel app.js --out-dir lib

Babel 会自动寻找babel.config.json 文件,并引入里面的 presetsplugins

4.2 Presets vs Plugins

4.2.1 Presets

Presets 其实就是 内置了许多 plugins,仅此而已,比如一开始安装的 @babel/preset-env ,里面就集成了许多插件,其中包括我们上面提到的 @babel/plugin-transform-arrow-functions

这也是为什么我们一开始要先安装 @babel/preset-env 的原因,后续可直接通过 --plugins 引用 @babel/plugin-transform-arrow-functions

类似的,React 和 Vue 也封装了自己的一套 presets,比如 @vue/babel-preset-app,里面内置了许多插件,其中就包括上面的 @babel/plugin-transform-arrow-functions/ @babel/plugin-transform-arrow-functions / @babel/preset-env 等等。我们没有直接用它的原因是为了让案例更易于理解,避免被 presets 名词给混淆了。

明白了 presets 的作用后,我们便可直接安装 @vue/babel-preset-app,并配置在 babel.config.json 中,像往常一样执行编译命令便可。

4.2.2 Plugins

说完 presets,再来聊聊 plugins,它实际上就是一个存放单个的 plugin 的集合,
也就是说,如果你想单独用某个插件而不用整套 preset,就可以通过 plugins 来单独地引入这个插件。

五、扩展知识

5.1 babel-loader 是什么?

如果想在 webapck 使用 babel,就得借助 babel-loader 来完成与 webpack 配合完成。
一个负责打包,一个负责编译。

5.2 Vue-cli 也能配置 babel ?

vue-cli 脚手架是基于 webpack 改造的,并提供了 vue-config.js 配置文件,里面就有一个transpileDependencies 属性可以改变 babel 的编译范围,让 babel 是否编译 node_modules/ 的代码。一般情况下,vue-config.js 能够配置 babel 的属性非常少,基本都是新建一个 babel.config.json 来维护,vue-cli 在执行时会读取这份配置并合并。

六、Bebel 部分插件说明

  • @babel/core Babel 的编译核心逻辑。

  • @babel/cli Babel 的执行脚手架。

  • @babel/plugin-syntax-jsx 识别 JSX 并提供 AST 分析语法树,但不会做转换工作。

  • @babel/preset-env 集成了大量的 plugins ,其中包括但不限于:

    • @babel/plugin-transform-optional-chaining 链式语法。
    • @babel/plugin-transform-arrow-functions ES6 箭头语法转换 ES5 。
    • @babel/plugin-transform-block-scoping let/const 语法转换 var 。
    • @babel/plugin-transform-classes class 语法转换。
    • @babel/plugin-transform-destructuring 解构对象转换。
    • 等等
  • @babel/preset-react 集成了有关 React 的 plugins,以下包括:

    • @babel/plugin-transform-react-jsx 支持 JSX & 标签转换。
    • 内嵌了 Babel 自带的如:@babel/preset-env / @babel/plugin-syntax-jsx 等。
  • @vue/babel-preset-app 集成了有关 Vue 的 plugins,以下包括:

    • @vue/babel-preset-jsx 支持 JSX & 标签转换。
    • 内嵌了 Babel 自带的如:@babel/preset-env / @babel/plugin-syntax-jsx 等。
  • @babel/preset-typescript 集成了关于 TS 的 plugins,以下包括:

    • @babel/plugin-transform-typescript 识别 TS 语法。

更多插件可参考:https://babeljs.io/docs/presets

完!

Logo

前往低代码交流专区

更多推荐