Babel介绍

什么是Babel?

Babel是一套主要用来将使用ECMAScript2015+语法编写的代码转换成纯ES5的Javascript代码的工具,以兼容任何老式浏览器与运行环境。

Babel可以做什么?

Babel可以用来编译ES6+的语法,它使所有ES6+规范新增的语法糖都可用,包括:类(class),箭头函数(arrow function),多行字符串等等。它的功能包括但不限于:

1.Javascript语法转换;

2.使用ployfill特性使你的浏览器兼容各类全局web api(例如:promise,async await);

3.源代码转换;

Babel代码转换流程

@babel/core作为Babel的核心包,主要负责代码的转换工作。其内部使用了@babel/parser,@babel/traverse,@babel/generator三个工具来负责代码的转译过程。

parser:内部依赖acorn和acorn-jsx,将js代码解析为抽象语法树;

traverse:修改parser解析后的抽象语法树;

generator:解析traverse编辑后的抽象语法树,生成对应的es5语法;

Babel的代码转换其实是一个线性的流程,依次经历解析,转换,生成三个阶段。

Babel介绍

Plugins和Presets

Plugin是Babel提供的用来帮助代码转换的工具,它主要在抽象语法树的转换阶段发挥作用,也就是traverse阶段。如果我们不使用任何plugins,源代码经过babel编译后会原样输出(不会保留原有代码格式)。Plugin则会告知babel如何转换我们的代码。

Babel提供了很多的plugins用来转换代码,其细粒度精确到每一种ECMAScript2015+语法,例如@babel/plugin-transform-arrow-functions负责转换箭头函数,@babel/plugin-proposal-object-rest-spread用来转换对象扩展运算符。同时babel的plugin还做了对框架语法的兼容,比如对react的jsx的转换。我们可以根据项目需求自行选定不同的插件。

上面提到了babel的plugins,plugins虽然功能丰富,但是es5+新出的语法还是比较多的,如果一个一个安装的话未免太麻烦,幸好babel提供了另外一种工具——presets。

如果把一个plugin比作一种工具,则presets则是工具箱。Presets是一组plugins的集合,用来转换一类语法。在实际项目中最常用preset便是@babel/preset-env了,它非常聪明可以帮助我们转换所有最新的Ecmascirpt标准语法。因此再也不需要去根据项目中使用到的语法而一个一个的安装插件,非常方便并且可以减小打包体积。

Polyfill

笔者曾经在开发的时候遇到过一个问题,webpack和babel都已经配置好,并且项目也可以在chrome中正常运行,但是在ie浏览器中却一直报错。找了一圈后来发现是项目中使用promise和async await的问题。于是我回头看了项目内babel配置,该用的插件也都用了,那么问题到底出在哪里呢?后来回顾了一个babel文档,才发现promise和async并不属于ES规范语法,而是全局api。

Polyfill就是babel提供的可以帮助我们兼容这些内建api的工具。这意味着您可以使用新的内置函数(例如Promise或WeakMap),静态方法(例如Array.from或Object.assign),实例方法(例如Array.prototype.includes)和生成器函数(前提是您使用了regenerator插件)。 为了做到这一点,polyfill将诸如String之类的本地原型添加到了全局范围。

Babel常用配置

Babel的配置可以说是非常简单了。Babel官方提供了两种配置文件以供选择:

babel.config.js: 使用编程的方式来进行配置;

module.exports = function (api) {
  api.cache(true);


  const presets = [ ... ];
  const plugins = [ ... ];


  return {
    presets,
    plugins
  };

.babelrc:静态配置,仅适用于单个程序包;

{
  "presets": [...],
  "plugins": [...]
}

如果项目中使用了webpack,则需要在webpack配置文件内配置babel-loader以启用babel配置

//webpack.config.js  
module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: ‘babel-loader‘,
      }
    ]
  },
//.babelrc
{
  "presets": [
    ["@babel/preset-env"],
    ["@babel/preset-react"]
  ]
}

或者

//webpack.config.js  
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: ‘babel-loader‘,
        options: {
          presets: [‘@babel/preset-env‘, "@babel/preset-react"],
        }
      }
    }
  ]
},
(此种配置方式无需配置babel配置文件)

如果项目中需要用到polyfill,可以将其在项目入口文件顶部引入或者加入到webpack配置文件的入口配置:

//index.js
require(‘@babel/polyfill‘);
  or
import ‘@babel/poltfill‘;
//webpack.config.js
entry: [‘@babel/polyfill‘, ‘./index.js‘],

注意在babel7.4.0之后的版本polyfill将会被弃用,建议您直接使用polyfill包含的core-js/stable和regenerator-runtime/runtime。

//index.js
import "core-js/stable";
import "regenerator-runtime/runtime";

如果您觉得直接引入core-js会增大打包体积,也可以使用按需引入的方式:

//index.js
import ‘core-js/features/promise‘;
import ‘core-js/features/array/from‘;

相关推荐