Babel 是一个转译器,将 ES6+ 的语法转译成浏览器支持更好的 ES3/ES5 语法的代码。它的运行有三个阶段:
parse(解析)=> transforming(转码)=> printing(输出)
不经过配置的 Babel 实质上什么都不会做,解析你的代码,转码后输出相同的代码。只有通过增加 plugin(插件)来告诉 babel 应该如何转译代码。而我们熟悉的 preset(预设),只是一系列 plugin 的集合,免去了一个个的配置插件这个步骤。
Babel 的 是一个 monorepo,其中包含 babel 的模块、helper,以及 plugin。
babel 模块
简要介绍 babel 中几个模块的作用。
babel-parser
babel 中使用的解析器。默认支持解析:
- 最新的 ECMAScript 语法
- 附加注释
- JSX, Flow, Typescript 语法
- 实验阶段的语法提案(支持至少达到 stage-0 阶段的 PR)
babel-core
babel 的核心模块,核心 api 都在这个模块里实现,比如,将字符串转译得到 AST 的方法 babel.transform
,其它的 api 如 babel.transformFile
, babel.transformFileSync
, babel.transformFromAst
,从这些 api 的命名大概能猜到它们的作用。
babel-cli
babel 的命令行工具,支持通过命令行对文件进行转译。
babel-node
会随 babel-cli 一起安装,安装后在命令行输入 babel-node
,会启动一个 REPL ,还可以通过 babel-node
命令执行 js
文件,和 node
命令类似。
babel-register
引入该模块后,会给 node
的 require
函数绑定一个钩子,当使用 node 的 require
方法时,会自动转译 .es6
, .es
, jsx
, .mjs
, .js
格式的文件(除了 node_modules 目录下的文件)。
babel-plugin-*
Babel 默认不会转译代码,需要通过配置插件来增加对语法的转译能力(注:可以通过配置 preset 来启用一系列插件)。 Babel 的插件分为两类,一类是 Transform Plugins,直译就是“转译插件”,这些插件会转译代码;另一类是 Syntax Plugins,直译就是“语法插件”,这类插件只做一件事,就是告诉 babel 要对特定类型的代码进行解析。 举例:一些需要被 polyfill 的代码,显然我们需要用到 Transform Plugins 这类插件,来把新的语法转译成兼容性更好的旧语法;而如果我们需要解析 vue 的单文件组件的语法,则首先需要用到 Syntax Plugins 这类插件来告诉 babel 如何解析这类语法。
注:Transform Plugins 会自动启用相应的 Syntax Plugins,不用特地去声明。其次,plugin 插件的引入和引入顺序是相关的,具体可以查看文档的。
babel-preset-*
文章开始已经提到,preset(预设)只是一系列 plugin 的集合。Babel 的官方仓库中也提供了一些预设,如 babel-preset-env
, babel-preset-stage-[0~3]
是对 ECMAScript 最新语法和 api 的支持, babel-preset-flow
是对 flow 语法检查工具的支持, babel-preset-react
是对 react 的支持,以及 babel-preset-typescript
是对 typescript 语法的支持。
babel-helper-*
helper 是一些供 babel 内部使用的工具库。我们常会使用 babel-plugin-external-helpers
插件,把一个文件中重复的 helper 代码(通常是 polyfill 的代码)移到文件顶部。
babel-polyfill
polyfill 直译过来就是“填充工具”,作用简单来说,就是给不支持某些 api 的旧浏览器打补丁,这样一来,开发的时候就可以始终使用新的语法、api,而不用考虑旧浏览器的兼容问题。 Babel 支持对部分新语法进行转译,如箭头函数,class
, let
, const
关键字等。但对于一些新的内置对象 Promise
,全局对象的静态方法 Array.from
,内置对象的示例方法 Array.prototype.includes
,以及 generator 函数,这些浏览器支持度不全的语法,需要增加一些 polyfill,才能确保代码能在旧的浏览器中正常运行。
注:通常是完整引入,会对全局对象做修改,官方建议在开发应用时使用,会明显增加打包后文件的体积。
babel-runtime
与 babel-polyfill 的作用类似,官方建议在开发库或插件时使用。通常, babel-runtime 会和 babel-plugin-transform-runtime
插件一起使用,达到按需引入 polyfill 的效果。
其它
还有其它几个模块,如 babel-generator
, babel-code-frame
, babel-template
, babel-traverse
, babel-types
,一般可能很少会和它们打交道,暂时先不讨论。