Javascript-Babel

本文最后更新于:2020年12月21日 晚上

Babel是什么

Javascript标准ECMA

百度百科:https://baike.baidu.com/item/ECMAScript/1889420?fr=aladdin
ES6支持表格:https://kangax.github.io/compat-table/es6

Babel的作用
如果你的浏览器不支持ES6,Babel可以将将代码转换ES4或者其它版本,让你的浏览器支持

什么是Babel

官网描述:Babel 是一个工具链,主要用于将 ECMAScript 2015+ (EC6)版本的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

例子: 实现语法转换

1
2
3
4
5
6
7
// Babel 输入: ES6 箭头函数
[1, 2, 3].map((n) => n + 1);

// Babel 输出: ES5 语法实现的同等功能
[1, 2, 3].map(function(n) {
return n + 1;
});

插件化

Babel构建在插件之上
使用现有的或者自己编写的插件可以组成一个转换管道
通过使用或创建一个 preset 即可轻松使用一组插件

1
2
3
4
5
6
7
8
9
10
11
12
// 一个插件就是一个函数
export default function ({types: t}) {
return {
visitor: {
Identifier(path) {
// 翻转name: JavaScript -> tpircSavaJ
let name = path.node.name;
path.node.name = name.split('').reverse().join('');
}
}
};
}

使用

https://www.babeljs.cn/docs/usage

安装

  1. 安装packages

    1
    2
    npm install --save-dev @babel/core @babel/cli @babel/preset-env
    npm install --save @babel/polyfill
  2. 根目录下创建一个文件babel.config.json写入

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    {
    "presets": [
    [
    "@babel/env",
    {
    "targets": {
    "edge": "17",
    "firefox": "60",
    "chrome": "67",
    "safari": "11.1",
    },
    "useBuiltIns": "usage",
    }
    ]
    ]
    }

    上面所列明的浏览器版本只是用于展示的示例(标明可以用什么版本以后的),你可以根据需要调整

  3. 测试编译代码

    1
    ./node_modules/.bin/babel src --out-dir lib
  • src
    输入js文件 目录/路径

  • lib
    输出js文件目录/路径

    如果填入文件路径,那么就编译单个文件
    如果填入目录的话,里面所有的js文件都会被编译

在命令执行完毕后,输出目录会有对应代码出现

帮助

1
./node_modules/.bin/babel --help

核心库基本使用

Babel的核心功能位于@babel/core模块中
你可以这样子在js代码里引入

1
2
const babel = require("@babel/core");
babel.transform("code", optionsObject);

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const babel = require("@babel/core");

const code = `
const sayHello = ()=>{
console.log('Hello Babel')
}
sayHello()
`
const optionsObject = {}
const result = babel.transform("code", optionsObject);
console.log(result)
>>>{
metadata: {},
options: {
cloneInputAst: true,
babelrc: false,
configFile: false,
passPerPreset: false,
envName: 'development',
cwd: 'F:\\Environment\\Node_js',
root: 'F:\\Environment\\Node_js',
plugins: [],
presets: [],
parserOpts: { sourceType: 'module', sourceFileName: undefined, plugins: [] },
generatorOpts: {
filename: undefined,
auxiliaryCommentBefore: undefined,
auxiliaryCommentAfter: undefined,
retainLines: undefined,
comments: true,
shouldPrintComment: undefined,
compact: 'auto',
minified: undefined,
sourceMaps: false,
sourceRoot: undefined,
sourceFileName: 'unknown'
}
},
ast: null,
code: "const sayHello = () => {\n console.log('Hello Babel');\n};\n\nsayHello();",
map: null,
sourceType: 'module'
}

因为没有指定需要适应什么东西,所以ES6的代码并没有转换

@babel/parser

Babel parser是一个BabelJavaScript分析模块

  • 默认启用的最新ECMAScript版本
  • 支持 JSX, Flow, Typescript

这个模块是基于 acornacorn-jsx ,感谢@RReverser and @marijnh

安装

1
npm install @babel/parser -g

要装在哪里,是否全局安装,按照自己的情况来

API

解析函数

  • babelParser.parse(code, [options])
    parse()将提供的代码作为一个完整的ECMAScript程序进行解析

  • babelParser.parseExpression(code, [options])
    parseExpression() 用于解析单个Expression,当你性能比parse()要高

Options参数

  • allowImportExportEverywhere
    默认情况下,importexport 声明语句只能出现在程序的最顶层
    把这个设置为true,可以使得语句在任何地方都可以声明

  • allowAwaitOutsideFunction
    默认情况下,仅在 异步函数内部 或 启用topLevelAwait插件时 在模块的顶层内允许使用await
    把这个设置为true,可以使得语句在任何地方都可以声明

  • allowReturnOutsideFunction
    默认情况下,如果在顶层中使用return语句会引起错误
    把这个设置为true,就不会报错

  • allowSuperOutsideMethod
    默认情况下,在类和对象方法之外不允许使用super
    把这个设置为true就可以声明

  • allowUndeclaredExports
    默认情况下,export一个在当前作用域下未声明的内容会报错
    把这个设置为true就可以防止解析器过早地抛出未声明的错误

  • createParenthesizedExpressions
    默认情况下,parser会在expression节点设置extra.parenthesized
    把这个设置为true,则会设置ParenthesizedExpressionAST节点

  • errorRecovery
    默认情况下,如果Babel发现一些 不正常的代码 就会抛出错误
    把这个设置为true,则会在保存解析错误的同时继续解析代码,错误的记录将被保存在 最终生成的AST的errors属性中
    注意,那些严重的错误依然会终止解析

  • plugins
    记录希望启动的插件的数组

  • sourceType
    代码的解析方式,你可以填入"script"(默认),"module""unambiguous"
    如果设置为”unambiguous”,那么系统会根据ES6语法中的importsexport来判断是"module"还是"script"

  • sourceFilename
    将输出的AST节点与其源文件名相关联
    在你处理多个文件时,这个功能会很有用

  • startLine
    默认情况下,第一行代码就是line 1。你可以传入一个数字,作为起始行数
    这个功能在你整合其他插件的时候会很有用

  • strictMode
    默认情况下,只有在声明了”use strict”条件下,ECMAScript代码才会被严格解析
    将此选项设置为true则始终以严格模式解析文件

  • ranges
    添加ranges属性到每一个节点中

    ranges: [node.start, node.end]

  • tokens
    将所有已经解析的tokens保存到File节点的tokens属性中

输出 Output

Babel parser是根据 Babel AST format 创建AST的
Babel AST format是基于 ESTree 规范 建立的

ESTree 代码生成对应节点文档
Babel parser 代码生成对应节点文档

Babel parser与ESTree的不同之处

Semver

大多数情况下Babel Parser会遵循Semver规定

1
2
3
4
5
6
7
8
9
10
require("@babel/parser").parse("code", {
// parse in strict mode and allow module declarations
sourceType: "module",

plugins: [
// enable jsx and flow syntax
"jsx",
"flow"
]
});

剩余请看:https://www.babeljs.cn/docs/babel-parser

@babel/traverse

此库通常用于修改节点

安装

1
npm install @babel/traverse -g

要装在哪里,是否全局安装,按照自己的情况来

信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import * as parser from "@babel/parser";
import traverse from "@babel/traverse";

const code = `function square(n) {
return n * n;
}`;

const ast = parser.parse(code);

traverse(ast, {
enter(path) {
if (path.isIdentifier({ name: "n" })) {
path.node.name = "x";
}
}
});

安装

1
npm install --save @babel/traverse

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!