欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

通過babel操作AST精準(zhǔn)插入配置代碼全流程

 更新時間:2022年02月08日 09:42:32   作者:廈門在乎科技  
這篇文章主要為大家介紹了通過babel操作AST精準(zhǔn)插入配置代碼的全流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

babel修改js配置文件實現(xiàn)原理

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

比如我們在前端項目,要插入一個頁面,需要修改router、menus等配置文件,還要手動拷貝頁面模板等等

這些高重復(fù)機(jī)械化操作,人工修改非常容易出錯

我們可以直接用babel來操作AST抽象語法樹,通過工程化去精準(zhǔn)修改。讓babel去幫我們找到指定位置,并正確插入配置代碼。我們在做工程化開發(fā)的時候,經(jīng)常會用到babel去操作AST。

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

AST,抽象語法樹(Abstract Syntax Tree)它是源代碼語法結(jié)構(gòu)的一種抽象表示。它以樹狀的形式表現(xiàn)編程語言的語法結(jié)構(gòu)。

我們使用babel來轉(zhuǎn)化和操作AST,主要分為三個步驟:解析(parser)、轉(zhuǎn)換(traverse)、生成(generator)

操作AST三大階段

如下圖,如果我們想通過babel,在配置文件里面插入一段配置代碼,應(yīng)該怎么實現(xiàn)呢

解析(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

轉(zhuǎn)換(traverse)

轉(zhuǎn)換(traverse)階段,就是要遍歷整個AST抽象語法樹,找到指定的位置,然后插入對應(yīng)的配置代碼。

代碼如下:

const traverse = require("@babel/traverse").default;
 
traverse(configJsTree, {
    ObjectProperty(path) {
      // 插入配置文件代碼
    },
  });

我們使用@babel/traverse的traverse方法進(jìn)行遍歷整個AST

其中ObjectProperty的作用是在遍歷AST過程中,識別出所有的Object對象,因為我們是要將配置代碼插入一個Object對象,所以使用的是ObjectProperty。如果要將配置插入數(shù)組中,就使用ArrayExpression。

然后我們開始進(jìn)行配置代碼的插入,將代碼

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

插入如下的位置

我們需要在traverseObjectProperty進(jìn)行位置的查找和代碼插入

首先我們要找到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這個屬性。這就是我們要插入的位置。

接下來我們要構(gòu)造要插入的數(shù)據(jù)

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

構(gòu)造數(shù)據(jù)的代碼如下:

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來標(biāo)識對象的屬性,用stringLiteral標(biāo)識字符串?dāng)?shù)據(jù),booleanLiteral標(biāo)識boolean值,這些類型都可以在@babel/types查詢到。

最后一步,將構(gòu)造好的數(shù)據(jù)插入:

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抽象語法樹反解,生成我們常規(guī)的代碼

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配置文件插入代碼,最終結(jié)果如下:

以上就是通過babel操作AST,然后精準(zhǔn)插入配置代碼的全流程。

更多關(guān)于babel操作AST插入配置的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論