通过babel操作AST精准插入配置代码全流程

目录
  • babel修改js配置文件实现原理
  • 操作AST三大阶段
    • 解析(parser)
    • 转换(traverse)
    • 生成(generator)

babel修改js配置文件实现原理

像那些js配置文件,里面可能有很多的非配置代码,而且一次可能要修改好几个文件

比如我们在前端项目,要插入一个页面,需要修改router、menus等配置文件,还要手动拷贝页面模板等等

这些高重复机械化操作,人工修改非常容易出错

我们可以直接用babel来操作AST抽象语法树,通过工程化去精准修改。让babel去帮我们找到指定位置,并正确插入配置代码。我们在做工程化开发的时候,经常会用到babel去操作AST。

首先我们了解一下什么是AST

AST,抽象语法树(Abstract Syntax Tree)它是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构。

我们使用babel来转化和操作AST,主要分为三个步骤:解析(parser)、转换(traverse)、生成(generator)

操作AST三大阶段

如下图,如果我们想通过babel,在配置文件里面插入一段配置代码,应该怎么实现呢

解析(parser)

第一步:读取配置文件代码,并生成AST抽象语法树

let configJsData = fs.readFileSync(configJsPath, "utf8");

然后将配置文件代码生成AST抽象语法树

const parser = require("@babel/parser");
 
let configJsTree = parser.parse(`${configJsData}`,{
    sourceType: "module",
    plugins: [
      "jsx",
      "flow",
    ],
  });

configJsTree就是我们的AST了

加上sourceType: "module"这个配置属性,是为了让babel支持解析export和import

转换(traverse)

转换(traverse)阶段,就是要遍历整个AST抽象语法树,找到指定的位置,然后插入对应的配置代码。

代码如下:

const traverse = require("@babel/traverse").default;

traverse(configJsTree, {
    ObjectProperty(path) {
      // 插入配置文件代码
    },
  });

我们使用@babel/traverse的traverse方法进行遍历整个AST

其中ObjectProperty的作用是在遍历AST过程中,识别出所有的Object对象,因为我们是要将配置代码插入一个Object对象,所以使用的是ObjectProperty。如果要将配置插入数组中,就使用ArrayExpression

然后我们开始进行配置代码的插入,将代码

{
  key: "testPath",
  icon: HomeOutlined,
  exact: true,
}

插入如下的位置

我们需要在traverseObjectProperty进行位置的查找和代码插入

首先我们要找到key: 'home'的位置

代码如下:

traverse(configJsTree, {
    ObjectProperty(path) {
      if ( path.node.key.name === "key" && path.node.value.value === "home" ) {
        // 这就是 key: 'home'的位置
      }
    },
  });

通过path.node.key.namepath.node.value.value找到对象属性为key并且对象值为home的Object对象

找到位置后开始插入代码

traverse(configJsTree, {
    ObjectProperty(path) {
      // 搜索并识别出配置文件里key: "home" 这个object对象位置
      if ( path.node.key.name === "key" && path.node.value.value === "home" ) {
        path.parent.properties.forEach(e=>{
          if ( e.key.name === "children" ) {
           // 找到children属性
          }
        })
      }
    },
  });

通过path.parent.properties找到对象的父级,然后遍历父级下的所有属性,找到children这个属性。这就是我们要插入的位置。

接下来我们要构造要插入的数据

{
   key: "testPath",
   icon: HomeOutlined,
   exact: true,
}

构造数据的代码如下:

const t = require("@babel/types");
const newObj = t.objectExpression([
    t.objectProperty(
      t.identifier("key"),
      t.stringLiteral("testPath")
    ),
    t.objectProperty(
      t.identifier("icon"),
      t.identifier("HomeOutlined")
    ),
    t.objectProperty(
      t.identifier("exact"),
      t.booleanLiteral(true)
    ),
  ]);

可以看到用dentifier来标识对象的属性,用stringLiteral标识字符串数据,booleanLiteral标识boolean值,这些类型都可以在@babel/types查询到。

最后一步,将构造好的数据插入:

e.value.elements.push(newObj)

完成~!

将所有 traverse 阶段代码汇总起来如下:

const traverse = require("@babel/traverse").default;
const t = require("@babel/types");

traverse(configJsTree, {
    ObjectProperty(path) {
      // 搜索并识别出配置文件里key: "home" 这个object对象位置
      if ( path.node.key.name === "key" && path.node.value.value === "home" ) {
        path.parent.properties.forEach(e=>{
          if ( e.key.name === "children" ) {
            const newObj = t.objectExpression([
              t.objectProperty(
                t.identifier("key"),
                t.stringLiteral("testPath")
              ),
              t.objectProperty(
                t.identifier("icon"),
                t.identifier("HomeOutlined")
              ),
              t.objectProperty(
                t.identifier("exact"),
                t.booleanLiteral(true)
              ),
            ]);
            e.value.elements.push(newObj)
          }
        })
      }
    },
  });

生成(generator)

这个阶段就是把AST抽象语法树反解,生成我们常规的代码

const generate = require("@babel/generator").default;
const result = generate(configJsTree, { jsescOption: { minimal: true } }, "").code;
fs.writeFileSync(resultPath, result);

通过@babel/generator将AST抽象代码语法树反解回原代码,jsescOption: { minimal: true }配置是为了解决中文为unicode乱码的问题。

至此咱们就完成了对js配置文件插入代码,最终结果如下:

以上就是通过babel操作AST,然后精准插入配置代码的全流程。

更多关于babel操作AST插入配置的资料请关注我们其它相关文章!

(0)

相关推荐

  • babel之配置文件.babelrc入门详解

    介绍 es6特性浏览器还没有全部支持,但是使用es6是大势所趋,所以babel应运而生,用来将es6代码转换成浏览器能够识别的代码 babel有提供专门的命令行工具方便转码,可以自行去了解 什么是Babel 官方解释,是下一代JavaScript 语法的编译器. 既然是下一代Javascript的标准,浏览器因版本的不同对此会有兼容性问题,JavaScript的新的方法都不能使用,但是目前我们在项目开发一直提倡使用最新的语法糖编写,不但能减少代码量,而且async,await等新特性还解决了回调

  • 详解如何用babel转换es6的class语法

    babel是一个转码器,目前开发react.vue项目都要使用到它.它可以把es6+的语法转换为es5,也可以转换JSX等语法. 我们在项目中都是通过配置插件和预设(多个插件的集合)来转换特定代码,例如env.stage-0等. 实际上babel可以通过自定义插件的方式实现任何代码的转换,接下来我们通过一个"把es6的 class 转换为es5"的例子来了解一下babel. 内容如下: webpack环境配置 大家应该都配置过babel-core这个loader,它的作用是提供babe

  • 利用babel将es6语法转es5的简单示例

    前言 Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码,从而在现有环境执行. 这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持. 本文讲解需预装node和npm.大家可以参考这篇文章:http://www.jb51.net/article/90518.htm,这里介绍的非常详细. 文件目录结构 生成包管理配置文件package.json npm init -y 安装转换工具 npm i -g babel-cli npm i --save-dev babel-pr

  • 详解如何使用babel进行es6文件的编译

    1.babel babel官方网址 2. 安装 npm i babel-cli -g 通过上面命令进行babel的安装,其中i表示安装install的意思, -g表示安装到全局 3.使用 创建文件es6.js let num = [1,2,3,4]; let plusDouble = num.map(item => item * 2); console.log(plusDouble); 然后使用命令进行编译: babel es6.js -o compiled.js 然后就会在当前目录下出现编译之

  • babel基本使用详解

    什么是babel? babel是一个强大的多用途js编译器 点击进入官网 安装babel npm install -g babel-cli npm install --save-dev babel-cli babel配置文件 通过.babelrc来表示 { "presets" : [ ], "plugins" : [ ] } presets用来存放一些预设 plugins用来存放一些插件 命令行的简单使用 我们可以通过 -o (--out-file) 参数来编译一个

  • 通过babel操作AST精准插入配置代码全流程

    目录 babel修改js配置文件实现原理 操作AST三大阶段 解析(parser) 转换(traverse) 生成(generator) babel修改js配置文件实现原理 像那些js配置文件,里面可能有很多的非配置代码,而且一次可能要修改好几个文件 比如我们在前端项目,要插入一个页面,需要修改router.menus等配置文件,还要手动拷贝页面模板等等 这些高重复机械化操作,人工修改非常容易出错 我们可以直接用babel来操作AST抽象语法树,通过工程化去精准修改.让babel去帮我们找到指定

  • spring注解 @PropertySource配置数据源全流程

    目录 @PropertySource数据源配置 使用xml配置数据源 使用javaBean配置数据源 @value注解读取配置 @PropertySource注解读取配置 注解的spring多数据源配置及使用 先看一下spring获取数据源的源码 第一步:创建一个DynamicDataSource的类 第二步:创建DynamicDataSourceHolder 第三步:配置多个数据源 @PropertySource数据源配置 一般在配置数据源是都会使用xml的方式注入,key-value在pro

  • vue2项目增加eslint配置代码规范示例

    目录 正文 1.安装以下eslint插件 1.1 .eslintrc.js文件配置 1.2 .eslintignore文件的配置 2. 安装prettier 3. package.json相关代码 4. vscode的配置 5. 启动项目 正文 eslint用于代码检查,prettier用于代码格式化,具体操作如下 1.安装以下eslint插件 安装以下eslint插件,并增加.eslintrc.js配置文件,.eslintignore配置忽略检查的文件 (1)eslint 用于检查和标示出EC

  • C#操作字符串方法总结实例代码

    废话不多说了,具体代码如下所述: staticvoid Main(string[] args) { string s =""; //(1)字符访问(下标访问s[i]) s ="ABCD"; Console.WriteLine(s[0]); // 输出"A"; Console.WriteLine(s.Length); // 输出4 Console.WriteLine(); //(2)打散为字符数组(ToCharArray) s ="ABC

  • babel的使用及安装配置教程

    简介 babel是一个广泛使用的转码器,可以将ES6代码转化为ES5代码,从而在现有环境执行,这意味着,你可以现在就用ES6编写程序,而不用担心现有环境是否支持. 安装及配置 npm install babel-cli --save-dev 或者 cnpm install babel-cli --save-dev使用淘宝镜像安装会更快. 步骤:进入项目 ==>cnpm install babel-cli --save-dev 为什么不安装在全局 如果安装在全局,那意味着项目要运行,全局环境必须有

  • 在golang中操作mysql数据库的实现代码

    前言 Golang 提供了database/sql包用于对SQL数据库的访问, 作为操作数据库的入口对象sql.DB, 主要为我们提供了两个重要的功能: •sql.DB 通过数据库驱动为我们提供管理底层数据库连接的打开和关闭操作. •sql.DB 为我们管理数据库连接池 需要注意的是,sql.DB表示操作数据库的抽象访问接口,而非一个数据库连接对象;它可以根据driver打开关闭数据库连接,管理连接池.正在使用的连接被标记为繁忙,用完后回到连接池等待下次使用.所以,如果你没有把连接释放回连接池,

  • Java操作MongoDB数据库的示例代码

    mongodb-driver是mongo官方推出的java连接mongoDB的驱动包,相当于JDBC驱动. 环境准备 step1:创建工程 , 引入依赖 <dependencies> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongodb‐driver</artifactId> <version>3.6.3</version> </d

  • VS Code 常用自定义配置代码规范保存自动格式化

    目录 自动保存格式化 用户自定义代码片段 必装插件 不装活不了那种 完整json 自动保存格式化 介绍一下我的vscode配置,记录为主,每个人的习惯不一样可以按需调整 必装插件 Prettier - Code formatter 链接: marketplace.visualstudio.com/items?itemN… 其实这一个插件就够了 配置保存自动格式化 "editor.formatOnSave": true 参考官方文档,可以配置哪些文件使用此插件配置 "[java

  • ASP.NET操作MySql数据库的实例代码讲解

    一.把MySql.Data.dll放到BIN目录下. 二.这是aspx.cs的全部源码,修改参数直接运行即可!   using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; publ

  • CentOS7服务器中apache、php7以及mysql5.7的安装配置代码

    CentOS7服务器中apache.php7以及mysql5.7的配置代码如下所示: yum upgrade yum install net-tools 安装apache 关闭SELinux 编辑器打开 etc/selinux/config 文件,找到 SELINUX=enforcing 字段,将其改成 SELINUX=disabled ,并重启设备. yum -y install httpd mod_ssl 配置防火墙 firewall-cmd --permanent --add-port=8

随机推荐