通過babel操作AST精準(zhǔ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, }
插入如下的位置
我們需要在traverse
的ObjectProperty
進(jìn)行位置的查找和代碼插入
首先我們要找到key: 'home'
的位置
代碼如下:
traverse(configJsTree, { ObjectProperty(path) { if ( path.node.key.name === "key" && path.node.value.value === "home" ) { // 這就是 key: 'home'的位置 } }, });
通過path.node.key.name
和path.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)文章
javascript實現(xiàn)漂亮的拖動層,窗口拖拽特效
一個可關(guān)閉、可隨意拖動位置的網(wǎng)頁彈出層代碼,美化的相當(dāng)漂亮,簡潔實用,還可拖動改變大小,通過八個方向改變大小,學(xué)習(xí)這類特效編寫的網(wǎng)頁設(shè)計者可參閱一下2015-04-04JS操作XML實例總結(jié)(加載與解析XML文件、字符串)
這篇文章主要介紹了JS操作XML的方法,結(jié)合實例形式總結(jié)分析了JavaScript加載與解析XML文件及字符串的相關(guān)技巧,需要的朋友可以參考下2015-12-12詳解小程序中h5頁面onShow實現(xiàn)及跨頁面通信方案
這篇文章主要介紹了小程序中h5頁面onShow實現(xiàn)及跨頁面通信方案,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05