babel的使用和原理

Babel是一个流行的用于将新版本ES6+代码转换为向后兼容版本(ES5)代码的JavaScript编译器。它还为JSX语法提供了编译支持,还有一些其他插件可用于转换特定类型的代码。下面是一些关于Babel的介绍和原理:

Babel的使用

  1. 安装Babel命令行工具:npm install -g babel-cli

  2. 安装Babel的Loader和Preset,这些用于解析和转换代码并生成新的代码:npm install -g babel-loader @babel/core @babel/preset-env

  3. 创建一个 .babelrc 文件,在其中指定您要使用哪些转换器和编译选项。例如:

{
  "presets": [
    "@babel/preset-env"
  ]
}
  1. 运行 Babel 编译器:babel input.js -o output.js

Babel插件

Babel常常使用插件去实现转换操作。请注意,Babel将在插件执行转换之前将代码解析为AST。这使得可以在AST上进行操作转换。以下是一些常用的Babel插件:

  1. @babel/plugin-transform-arrow-functions 将箭头函数转换为函数表达式以实现向后兼容性。

  2. @babel/plugin-proposal-class-properties 将ES6中添加的类属性转换为向后兼容版本。

  3. @babel/plugin-proposal-object-rest-spread 将对象展开操作符转换为ES5代码。

总结

Babel是一个非常强大的JavaScript编译器,它可以将新版本的ES6+代码转换为向后兼容版本(ES5)代码,以及提供支持JSX语法的编译支持。它使用抽象语法树(AST)来表示代码,插件通过操作AST节点实现代码转换。

Babel 是一个 JavaScript 编译器,用于将最新的 JavaScript 语法转换为向后兼容的版本并处理浏览器兼容性问题。它使用了一种称为抽象语法树(AST)的数据结构,将源代码转换为一个可操作的表示形式并进行处理。

Babel 的工作原理:三类功能

解析

当 Babel 接收到源代码时,将会调用一个叫做解析器的工具,用于将源代码转换为抽象语法树(AST)。在这个过程中,解析器会识别代码中的语法结构,并将其转换为对应的节点类型。
例如,当解析器遇到一个变量声明语句时,它将会创建一个 “VariableDeclaration” 节点,并将该节点的信息存储在 AST 中。AST 是一个以节点为基础组成的树形结构,每个节点都有相应的类型、属性和子节点等信息。

转换

一旦 AST 被创建,Babel 将遍历整个树形结构,对每个节点进行转换。这些转换可以是插件、预设或手动创建的。转换器会检查 AST 中的每个节点,然后对其进行相应的修改或替换,以将新语法转换为旧语法。
例如,如果 Babel 遇到一个包含箭头函数的节点,而你已经启用了转换插件,该插件将会将箭头函数转换为其等效的体函数。代码转换后,Babel 将会生成一个新的 AST。

生成

最后,Babel 将基于转换后的 AST 生成代码文本。在这个步骤中,Babel 将遍历转换后的 AST,并创建对应的代码字符串,并将这些字符串组合成一个完整的 JavaScript 文件。如果启用了代码压缩,Babel 还可以将生成的代码进行压缩。
总结来说,Babel 的原理就是将 JavaScript 源代码转换为抽象语法树(AST),然后对 AST 进行转换,生成与源代码功能相同但向后兼容的代码。Babel 提供了一个强大的生态系统,使得开发者可以轻松扩展并自定义转换器,实现自己的功能需求。

babel解析过程发生了什么

输入:Babel 接收到待处理的源代码字符串作为输入。

词法分析(Lexical Analysis):在词法分析阶段,Babel 的解析器将源代码字符串分解成一个个称为 “令牌”(Tokens) 的单位。令牌代表源代码中的基本元素,如标识符、关键字、运算符等。词法分析器(Lexer)根据一系列的词法规则来识别和生成令牌。

例如,对于源代码中的语句 const x = 10;,词法分析器会依次生成令牌 “const”、“x”、“=”、“10” 和 “;”。

语法分析(Parsing):在语法分析阶段,Babel 使用解析器(Parser)以及词法分析得到的令牌序列构建抽象语法树(AST)。解析器根据语法规则和文法定义来识别语法结构,并将其表示为节点。

例如,对于语句 const x = 10;,解析器会创建一个 “VariableDeclaration” 节点,并将其子节点设置为一个 “Identifier” 节点(表示变量名 “x”)和一个 “NumericLiteral” 节点(表示数值 “10”)。

AST 构建:在这一阶段,Babel 将解析器生成的节点组合成一个抽象语法树(AST)。AST 是一个以节点为基础组成的树形结构,其中树的每个节点都包含有关语法结构的信息。

语义分析(Semantic Analysis):在语义分析阶段,Babel 分析 AST 中的节点,确定其语义和上下文信息。这个过程可能涉及到变量引用、作用域和类型等语义相关的问题。

输出:最后,Babel 将根据 AST 生成转换后的代码文本,可以是源代码的等效形式(例如,将最新的 JavaScript 语法转换为旧版本的语法),也可以是其他需要的格式。

命令行使用

  1. @babel/core:babel的核心代码,必须安装;
  2. @babel/cli:可以让我们在命令行使用babel;
  3. yarn add @babel/cli @babel/core
  4. npx babel src --out-dir dist
  5. 预设yarn add @babel/preset-env -D
  6. npx babel src --out-dir dist --presets = @babel/preset-env
  7. 单独处理箭头函数yarn add @babel/plugin-transform-arrow-functions
    1. 针对单个文件,对应命令行输入:npx babel index.js --out-file dist.js --plugins=@babel/plugin-transform-arrow-functions
    2. 针对文件夹,对应命令行输入:npx babel src --out-dir dist --plugins=@babel/plugin-transform-arrow-functions
  8. 单独处理let 转换为 var
    1. yarn add @babel/plugin-transform-block-scoping
    2. npx babel src --out-dir dist --plugins = @babel/plugin-transform-block-scoping,@babel/plugin-transform-arrow-functions

webpack中使用babel

在这里插入图片描述

设置目标浏览器

  1. 为了让postcss使用同一套设置,于是就统一设置在.browserslistrc
  2. 优先级:
    1. @babel/preset-env 里的 targets
    2. package.json 里的 browserslist 字段
    3. .browserslistrc 配置文件
  3. 下面是设置在预设内:
    在这里插入图片描述

多预设

在这里插入图片描述

预设preset的stage-x

  1. 要了解Stage-X,我们需要先了解一下TC39的组织:

    1. TC39是指技术委员会(Technical Committee)第 39 号;
    2. 它是 ECMA 的一部分,ECMA 是 “ECMAScript” 规范下的 JavaScript 语言标准化的机构;
    3. ECMAScript 规范定义了 JavaScript 如何一步一步的进化、发展;
  2. TC39 遵循的原则是:分阶段加入不同的语言特性,新流程涉及四个不同的 Stage

    1. Stage 0:strawman(稻草人),任何尚未提交作为正式提案的讨论、想法变更或者补充都被认为是第 0 阶段的"稻草人";
    2. Stage 1:proposal(提议),提案已经被正式化,并期望解决此问题,还需要观察与其他提案的相互影响;
    3. Stage 2:draft(草稿),Stage 2 的提案应提供规范初稿、草稿。此时,语言的实现者开始观察 runtime 的具体实现是否合理;
    4. Stage 3:candidate(候补),Stage 3 提案是建议的候选提案。在这个高级阶段,规范的编辑人员和评审人员必须在最终规范上签字。Stage 3 的提案不会有太大的改变,在对外发布之前只是修正一些问题;
    5. Stage 4:finished(完成),进入 Stage 4 的提案将包含在 ECMAScript 的下一个修订版中;
  3. 在babel7之前(比如babel6中),我们会经常看到这种设置方式:

  4. 它表达的含义是使用对应的 babel-preset-stage-x 预设;

  5. 但是从babel7开始,已经不建议使用了,建议使用preset-env来设置;

  6. 在这里插入图片描述

  7. 在这里插入图片描述

babel的配置文件

  1. 像之前一样,我们可以将babel的配置信息放到一个独立的文件中,babel给我们提供了两种配置文件的编写:
  2. babel.config.json(或者.js,.cjs,.mjs)文件;
  3. .babelrc.json(或者.babelrc,.js,.cjs,.mjs)文件;
  4. 它们两个有什么区别呢?目前很多的项目都采用了多包管理的方式(babel本身、element-plus、umi等);
  5. .babelrc.json:早期使用较多的配置方式,但是对于配置Monorepos项目是比较麻烦的;
  6. babel.config.json(babel7):可以直接作用于Monorepos项目的子包,更加推荐;
  7. 在这里插入图片描述
  8. MonoreposMultirepos 项目架构

认识polyfill

  1. babel7.4.0之前,可以使用 @babel/polyfill的包,但是该包现在已经不推荐使用了

  2. babel7.4.0之后,yarn add core-js regenerator-runtime

  3. babel.config.js内配置在这里插入图片描述

    1. useBuiltIns:false,不使用polyfill,且不需要设置corejs;
    2. useBuiltIns:"usage",哪里用到了,那么就在哪里引入,需要设置corejs版本。
    3. useBuiltIns:"entry",如果依赖某个库已经使用了自己的polyfill特性,如果我们使用usage就会报错,用entry就解决了问题,使用 entry需要在入口文件中添加 import 'core-js/stable'; import 'regenerator-runtime/runtime,这样会根据 browserslist 目标导入所有的polyfill,但是对应的包也会变大;在这里插入图片描述
  4. 禁止掉exclude:/node_modules/,否则会和包文件内的polyfill冲突在这里插入图片描述

@babel/plugin-transform-runtime

  1. 在前面我们使用的polyfill,默认情况是添加的所有特性都是全局的

  2. 如果我们正在编写一个工具库,这个工具库需要使用polyfill;

  3. 别人在使用我们工具时,工具库通过polyfill添加的特性,可能会污染它们的代码;

  4. 所以,当编写工具时,yarn add @babel/plugin-transform-runtime

  5. 使用plugins来配置babel.config.js:在这里插入图片描述

  6. 配置插件了,就需要把预设的额外配置给注释掉

  7. 注意:因为我们使用了corejs3,所以我们需要安装对应的库:在这里插入图片描述

  8. 安装对应的库yarn add @babel/runtime-corejs3

React的jsx支持

  1. 在我们编写react代码时,react使用的语法是jsx,jsx是可以直接使用babel来转换的。
  2. 对react jsx代码进行处理需要如下的插件:
  3. yarn add @babel/plugin-syntax-jsx
  4. yarn add @babel/plugin-transform-react-jsx
  5. yarn add @babel/plugin-transform-react-display-name
  6. 但是开发中,我们并不需要一个个去安装这些插件,我们依然可以使用preset来配置
  7. yarn add @babel/preset-react
  8. 修改babel.config.js预设配置在这里插入图片描述
  9. 在代码中使用到的包yarn add react react-dom
  10. zanlan.config.js在这里插入图片描述
  11. index.js在这里插入图片描述
  12. 打包后的index.html,添加在这里插入图片描述
  13. 打开预览在这里插入图片描述

TypeScript的编译

  1. 在项目开发中,我们会使用TypeScript来开发,那么TypeScript代码是需要转换成JavaScript代码。
  2. 可以通过TypeScript的compiler来转换成JavaScript:yarn add typescript
  3. 另外TypeScript的编译配置信息我们通常会编写一个tsconfig.json文件:tsc --init
  4. 生成配置文件如下:在这里插入图片描述
  5. 之后我们可以运行 npx tsc来编译自己的ts代码:npx tsc

使用ts-loader处理ts文件

  1. 如果我们希望在webpack中使用TypeScript,那么我们可以使用ts-loader来处理ts文件:yarn add ts-loader,默认会安装typescript的了,所以我们自己没有安装typescript,也可以使用ts-loader
  2. 配置ts-loader:在这里插入图片描述
  3. 之后,我们通过npm run build打包即可。

使用babel-loader来处理ts代码

  1. 除了可以使用TypeScript Compiler来编译TypeScript之外,我们也可以使用Babel:
  2. Babel是有对TypeScript进行支持;
  3. 我们可以使用插件: @babel/tranform-typescript;
  4. 但是更推荐使用preset:@babel/preset-typescript;
  5. 我们来安装@babel/preset-typescript:yarn add @babel/preset-typescript
  6. 在这里插入图片描述

ts-loader和babel-loader选择

  1. 那么我们在开发中应该选择ts-loader还是babel-loader呢?
  2. 使用ts-loader(TypeScript Compiler)
    1. 来直接编译TypeScript,那么只能将ts转换成js,可以检测代码;在这里插入图片描述

    2. 如果我们还希望在这个过程中添加对应的polyfill,那么ts-loader是无能为力的;

    3. 我们需要借助于babel来完成polyfill的填充功能;

  3. 使用babel-loader(Babel)
    1. 来直接编译TypeScript,也可以将ts转换成js,并且可以实现polyfill的功能;
    2. 但是babel-loader在编译的过程中,不会对类型错误进行检测;即使在代码中有类型错误,照样可以打包成功
  4. 那么在开发中,我们如何可以同时保证两个情况都没有问题呢?

编译TypeScript最佳实践

  1. 事实上TypeScript官方文档有对其进行说明:在这里插入图片描述
  2. 也就是说我们使用Babel来完成代码的转换,使用tsc来进行类型的检查
  3. 但是,如何可以使用tsc来进行类型的检查呢?在这里插入图片描述
    1. 我们执行 npm run type-check可以对ts代码的类型进行检测;
    2. 我们执行 npm run type-check-watch可以实时的检测类型错误;
    3. 我们执行 npm run build2 ,只有 tsc --noEmit不报错时候,才会执行第二命令

babel原理

Babel 是一个 JavaScript 编译器。他把最新版的 javascript 编译成当下可以执行的版本,简言之,利用 babel 就可以让我们在当前的项目中随意的使用这些新最新的 es6,甚至 es7 的语法

ES6、7代码输入 -> babylon进行解析 -> 得到AST(抽象语法树)-> plugin用babel-traverseAST树进行遍历转译 ->得到新的AST树->用babel-generator通过AST树生成ES5代码

它的工作流程包括解析(parse)、转换(transform)和生成(generate)三个主要步骤

  1. 解析(parse) :Babel 使用解析器(如 Babylon)将输入的 JavaScript 代码解析成抽象语法树(AST)。解析器将代码分析成语法结构,并生成对应的 AST,表示代码的抽象语法结构。这个阶段包括词法分析和语法分析。词法分析将源代码转换为一个个标记(tokens)的流,而语法分析则将这个标记流转换为 AST 的形式。
  2. 转换(transform) :在转换阶段,Babel 使用插件(plugins)对 AST 进行遍历和转换。插件可以对 AST 进行增删改查的操作,可以根据需求对语法进行转换、代码优化等。Babel 的插件系统非常灵活,可以根据需要自定义插件或使用现有插件来进行代码转换。
  3. 生成(generate) :在生成阶段,Babel 使用生成器(如 babel-generator)将经过转换的 AST 转换回字符串形式的 JavaScript 代码。生成器会深度优先遍历 AST,并根据 AST 的节点类型生成对应的代码字符串,最终将代码字符串输出。

通过以上三个步骤,Babel 实现了将最新版本的 JavaScript 代码转换为向后兼容的代码,使得开发者可以在当前环境中使用较新的 JavaScript 特性和语法。同时,Babel 还提供了一些常用的插件和预设(presets),以便开发者快速配置和使用常见的转换规则,如转换 ES6、ES7 语法、处理模块化、转换 JSX 等。

总的来说,Babel 的原理是通过解析、转换和生成的过程,将新版本的 JavaScript 代码转换为兼容旧环境的代码,使开发者能够在当前环境中使用较新的 JavaScript 特性和语法。

babel编译器原理

  1. babel编译器原理:在这里插入图片描述

  2. 代码结构在这里插入图片描述

  3. tokens.js在这里插入图片描述

  4. old_ast.json在这里插入图片描述

  5. new_ast.json在这里插入图片描述

官方babel原理

官网提供的简易版babel原理案例

  1. node自带的包assertconst assert = require('assert');
  2. assert.deepStrictEqual({ a: 1 }, { a: '1' });
  3. 只有两个对象,有一个子节点不一样,就报错,否则,不作出反应,代表就是值结构一样对象
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值