首页 > 其他分享 >babel 基础概念 & 从零到一写一个 babel 插件

babel 基础概念 & 从零到一写一个 babel 插件

时间:2024-02-20 23:00:11浏览次数:18  
标签:插件 AST babel 零到 path Identifier 节点

babel 基础概念

简单来说,做语法转换兼容的,
复杂一点的说,babel可以将我们写的 ES6+ 的Javascript语法转换为向后兼容的语法,以便能够在旧版本的浏览器或者其他环境运行。

babel 生成代码的三个阶段

  • 解析(parse)
    • 输入:源码
    • 输出:AST
  • 转换(transform)
    • 输入:AST
    • 输出:AST(此AST非彼AST,是被不同babel插件处理过的AST)
  • 生成(generate)
    • 输入:AST
    • 输出:转换后的代码

我们平常使用的babel插件是在转换这个阶段生效的,在该阶段babel会去遍历AST的每个节点,我们可以对特定的节点做处理。那这里AST节点是什么呢,请看下面的解释和举例。

AST:抽象语法树

在开始编写插件之前,你需要了解什么是AST。AST是源代码的抽象语法结构的树状表示,它将代码中的结构表示为树中的节点。每个节点代表代码的一部分,例如变量声明、函数调用等。

假设下面这个函数是我们的源码

function square(n) {
  return n * n;
}

当我们使用babel进行解析后,会生成如下的AST:

- FunctionDeclaration:
  - id:
    - Identifier:
      - name: square
  - params [1]
    - Identifier
      - name: n
  - body:
    - BlockStatement
      - body [1]
        - ReturnStatement
          - argument
            - BinaryExpression
              - operator: *
              - left
                - Identifier
                  - name: n
              - right
                - Identifier
                  - name: n

我们可以看到,第一个节点是FunctionDeclaration,表示我们当前输入的是一个函数的声明,这个节点下是它的标识符(id),参数(params),函数体(body)。
在params和body下,又有下一层级的节点,这个大家可以对照源码看一下

遍历处理AST

从上面的例子我们可以了解到,如果希望对AST进行处理,也就是babel的第二阶段(转换),我们需要递归的对AST这个树结构进行遍历
将上方的AST用js对象表示就是这样

{
  type: "FunctionDeclaration",
  id: {
    type: "Identifier",
    name: "square"
  },
  params: [{
    type: "Identifier",
    name: "n"
  }],
  body: {
    type: "BlockStatement",
    body: [{
      type: "ReturnStatement",
      argument: {
        type: "BinaryExpression",
        operator: "*",
        left: {
          type: "Identifier",
          name: "n"
        },
        right: {
          type: "Identifier",
          name: "n"
        }
      }
    }]
  }
}

Visitors

Babel 使用 Visitors 来定义对 AST 节点的具体操作,比如检测特定的节点类型、对节点进行修改、添加新节点等。

Visitors 定义了插件在 AST 上执行的具体操作。一个 Visitor 对象通常包含一组方法,每个方法对应一个特定类型的 AST 节点。这些方法被称为 Visitor 方法,通常以要访问的节点类型名作为属性名。例如:

const visitor = {
  Identifier(path) {
    // 处理 Identifier 节点
  },
  BlockStatement(path) {
    // 处理 BlockStatement 节点
  },
  // 其他 Visitor 方法
};

Paths

在 Babel 中,paths 是一个对象,用于在插件中访问和操作 AST 中的节点。每个节点都有一个相应的路径(path),可以通过这个路径对象来访问节点的各种属性和方法。

你可以把 paths 想象成是一条通往 AST 中某个节点的路径,通过这条路径,你可以获取到节点的信息,比如节点的类型、属性、子节点等。这样,你就可以在插件中根据节点的具体情况来进行各种操作,比如修改节点、添加新节点、删除节点等。

比如,你可以在Visitors中使用path打印节点的名称:

const MyVisitor = {
  Identifier(path) {
    console.log("Visiting: " + path.node.name);
  }
};

State

在 Babel 插件开发中,state 是一个用于存储插件状态和数据的对象。它可以传递给 Babel 插件中的访问者(Visitors),允许插件在不同的访问者方法之间共享信息和状态。

我们在使用插件的时候,可能会给这个插件传递配置项,这个也可以通过state.opts读取到

// 假设我们在初始化一个插件,并传递了配置项
  plugins: [
    [myPlugin, { prefix: 'my_' }]
  ]

// 
const MyVisitor = {
  Identifier(path, state) {
    console.log(state.opts); // 打印出来:{ prefix: 'my_' }
  }
};

Scope

在 Babel 中,Scope(作用域)是指在 JavaScript 代码中的变量可访问的范围,Babel 中的 Scope 对象用于表示和管理这些作用域。

Scope 在 Babel 中的主要作用是帮助插件进行变量名的解析和处理。Babel 在遍历 AST(抽象语法树)时会构建一个作用域链,每个节点都会有一个对应的 Scope 对象,这个 Scope 对象包含了当前节点所在作用域的信息,比如变量、函数等。

从零到一写一个 babel 插件

项目初始化

mkdir first-babel-plugin
cd first-babel-plugin
npm init -y
npm install --save-dev @babel/core @babel/cli

插件编写

创建 index.js 文件

module.exports = function(babel) {
  const { types: t } = babel;

  return {
    visitor: {
      CallExpression(path) {
        if (
          path.node.callee.object &&
          path.node.callee.object.name === 'console' &&
          path.node.callee.property.name === 'log'
        ) {
          path.remove();
        }
      }
    }
  };
};

这个插件定义了一个访问者(visitor),它会遍历AST中的所有调用表达式(CallExpression)。如果这个调用表达式是console.log,它就会被移除。

使用插件

要使用这个插件,你可以在命令行中使用babel命令,并通过--plugins参数指定你的插件。首先,创建一个包含console.log的测试文件,比如test.js:

console.log("Hello, Babel Plugin!");

然后运行:

npx babel test.js --plugins=./index.js

你会看到,输出的代码中不再包含console.log语句。

标签:插件,AST,babel,零到,path,Identifier,节点
From: https://www.cnblogs.com/azoux/p/18024232

相关文章

  • IDEA插件推荐:免费好用!
    IDEA是一款功能强大的集成开发环境(IDE),它可以帮助开发人员更加高效地编写、调试和部署软件应用程序。我们在编写完接口代码后需要进行接口调试等操作,一般需要打开额外的调试工具。今天给大家介绍一款IDEA插件:Apipost-Helper-2.0。代码写完直接编辑器内调试、还支持生成接口文档、......
  • SpringBoot中使用PageHelper插件实现Mybatis分页
    场景SpringBoot中整合Mybatis时一般添加的依赖为       <dependency>           <groupId>org.mybatis.spring.boot</groupId>           <artifactId>mybatis-spring-boot-starter</artifactId>           <version>2.2.1</vers......
  • 使用油猴插件,修改和简化美化博客园的随笔编辑界面
    包含内容开局自动打开实时预览编辑区域高度放大左侧菜单栏区域缩小下方菜单栏隐藏,点击恢复可再现待续//==UserScript==//@name博客园修改//@namespacehttp://tampermonkey.net///@version2024-02-20//@descriptiontrytotakeover......
  • 从0到1设计开发Chrome插件
    TNTWeb-全称腾讯新闻中台前端团队,组内小伙伴在Web前端、NodeJS开发、UI设计、移动APP等大前端领域都有所实践和积累。目前团队主要支持腾讯新闻各业务的前端开发,业务开发之余也积累沉淀了一些前端基础设施,赋能业务提效和产品创新。团队倡导开源共建,拥有各种技术大牛,团队Githu......
  • 云服务器怎么搭建:从零到运行的基础指南
    本文分享自天翼云开发者社区《云服务器怎么搭建:从零到运行的基础指南》,作者:每日知识小分享随着云计算技术的快速发展,云服务器已经成为企业和个人首选的计算服务。云服务器具有高性能、高可用性、安全可靠、灵活扩展等优势,能够满足各种大规模数据处理、存储、应用部署和管理等需求......
  • Babel 插件种类
    Babel插件种类:语法插件(SyntaxPlugins):语法插件负责扩展Babel的解析器,使其能够理解和解析新的或实验性的JavaScript语法特性。它们并不直接对代码进行转换,只是开启对应语法的解析功能。这意味着,如果没有相应的语法插件,Babel将无法正确解析某些新的或实验性的JavaScri......
  • 磐维2.0 之pg_stat_statements插件
    目录一、概念描述二、安装插件三、pg_stat_statements视图四、pg_stat_statements相关参数五、测试验证一、概念描述pg_stat_statements是pg的一个扩展插件,通常用于统计数据库的资源开销,分析TOPSQL,找出慢查询。二、安装插件testdb=#testdb=#createextensionpg_stat_sta......
  • postman也不行!IDEA接口调试插件
    Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:ApipostHelper,写完代码就可以调试接口并一键生成接口文档!而且还可以根据已有的方法帮助您快速生成url和params。更重要的是他完全免费!Apipos......
  • 旁门左道:借助 HttpClientHandler 拦截请求,体验 Semantic Kernel 插件
    前天尝试通过one-api+dashscope(阿里云灵积)+qwen(通义千问)运行SemanticKernel插件(Plugin),结果尝试失败,详见前天的博文。今天换一种方式尝试,选择了一个旁门左道走走看,看能不能在不使用大模型的情况下让SemanticKernel插件运行起来,这个旁门左道就是从StephenToub那......
  • 最新Burp Suite插件详解
    Burp Suite中的插件BurpSuite中存在多个插件,通过这些插件可以更方便地进行安全测试。插件可以在“BAppStore”(“Extender”→“BAppStore”)中安装,如图3-46所示。   图3-46   下面列举一些常见的BurpSuite插件。 1.Active Scan++ActiveScan++在BurpSuite......