【工程】你所要知道的Babel

316 阅读2分钟

原理浅析

处理流程

babel 是一个编译器

  • 解析:将原始代码解析为抽象语法树AST
    • 词法分析:原始代码拆分成一个个的Token
    • 语法分析:递归遍历Tokens数组,构建AST
  • 转换:转换得到的AST,生成新的AST
  • 生成:遍历新AST,生成目标代码

参考

核心概念

插件

babel 初始情况不会对代码做任何转换

借助babel-traverse,插件可以遍历AST并进行增删改操作,进而实现代码转换功能

预设preset

插件本身可能每一个语法都会有独立的插件来做转换

babel 抽象出了preset来管理一系列插件

核心包

@babel-core

包括:

  • @babel/parser:负责将源代码解析成AST
  • @babel/traverse:向外提供遍历AST节点的能力
  • @babel/generator:负责根据变换后的AST生成目标代码

@babel/cli

提供在命令行中调用@babel/core的能力

// 依赖安装
npm i --save-dev @babel/core @babel/cli
// 没有配置任何插件,编译前后的代码完全一样
npx babel src --out-dir dist

@babel/preset

// 依赖安装
npm i --save-dev @babel/preset
// .babelrc
{
  "presets": ["@babel/preset-env"]
}

@babel/polyfill

V7.4.0 版本开始,@babel/polyfill已经被废弃,单独安装core-jsregenerator-runtime模块

  • core-js提供了polyfill的核心实现
  • regenerator-runtime是generator以及async/await的运行时依赖

core-js是一套模块化的JS标准库

// .babelrc
{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "usage",
      "corejs": 3
    }]
  ]
}

@babel/runtime & @babel/plugin-transform-runtime

babel 在转换代码的过程中会在模块顶部插入一些帮助函数

class A {}

编译之后

'use strict';

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

var A = function A() {
  _classCallCheck(this, A);
};
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime

_classCallCheck2已经变成从@babel/runtime中引入

@babel/plugin-transform-runtime将所有使用到帮助方法的地方,从各自维护一份改为从@babel/runtime中引入

参考