1. babel简介
Babel 的前身是 6to5,6to5 是 2014 年 发布的,主要功能是 就是 ES6 转成 ES5。后改名babel。
2. Babel用途
- 转译 esnext、typescript 等到目标环境支持的 js
高级语言到到低级语言叫编译,高级语言到高级语言叫转译 - 代码转换
taro就是用babel做语法转译的。 - 代码分析
模块分析、tree-shaking 、 代码压缩、linter等
3. Babel怎么转译代码的?
对源码字符串进行 parse,生成 AST,把对代码的修改转为对 AST 的增删改,转换完 AST 之后再打印成目标代码字符串。
-
parse 阶段使用@babel/parser,作用是把源码转成 AST
require('@babel/parser').parse(source, { sourceType: 'module', plugins: ['jsx', 'flow', 'classProperties', 'decorator', 'decorators-legacy'], });
plugins: 指定jsx、typescript、flow 等插件来解析对应的语法。
sourceType: module、script、unambiguous 3个取值,module 是解析 es module 语法。 -
transform 阶段使用
@babel/traverse
,可以遍历AST
,并调用 visitor 函数修改 AST,修改 AST 涉及到 AST 的判断、创建、修改等,这时候就需要@babel/types
了,当需要批量创建 AST 的时候可以使用@babel/template
来简化 AST 创建逻辑。require('@babel/traverse').default function traverse(ast,vistor) //vistor可以是函数可以是对象,函数就是enter节点时调用的函数vistor名字为节点名称,对象就是enter和exit调用的函数。tips多个节点可以'FunctionDeclaration|VariableDeclaration' require('@babel/traverse').default(ast, { Program(path,state) { } }) // path api { "parent": {...}, "node": {...}, "hub": {...}, "contexts": [], "data": {}, "shouldSkip": false, "shouldStop": false, "removed": false, "state": null, "opts": null, "skipKeys": null, "parentPath": null, "context": null, "container": null, "listKey": null, "inList": false, "parentKey": null, "key": null, "scope": null, "type": null, "typeAnnotation": null, get(key) set(key, node) inList() getSibling(key) getNextSibling() getPrevSibling() getAllPrevSiblings() getAllNextSiblings() isXxx(opts) assertXxx(opts) find(callback) findParent(callback) insertBefore(nodes) insertAfter(nodes) replaceWith(replacement) replaceWithMultiple(nodes) replaceWithSourceString(replacement) remove() traverse(visitor, state) skip() stop() }
@babel/types 用于创建、判断 AST 节点,提供了 xxx、isXxx、assertXxx 的 api
-
generate
阶段会把 AST 打印为目标代码字符串,同时生成sourcemap
,需要@babel/generate
包,中途遇到错误想打印代码位置的时候,使用@babel/code-frame
包const { code,map } = generator(ast, { sourceMaps: true }); //设置sourceMaps为true才有sourceMaps