成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為啥套娃?聊聊 Babel、Jscodeshift 和阿里媽媽的 Gogocode

開發 前端
path 是節點之間的關系,每個 path關聯父節點和當前節點,path 對象構成一條從當前節點到根結點的路徑。state 是遍歷過程中的共享數據的機制。

[[407446]]

首先,我是《babel 插件通關秘籍》 掘金小冊的作者,對 babel 有源碼級的掌握,算是有資格討論這個話題。

本來會探討以下話題:

  • babel 是怎么轉換代碼的
  • jscodeshift 是怎么轉換代碼的
  • babel 和 jscodeshift 的區別
  • 為什么不推薦 gogocode

babel 是怎么轉換代碼的

babel 編譯流程分為 3 步:parse、transform、generate

  • parse:把源碼轉成 AST,babel parser(babylon) 支持 esnext 語法,可通過插件支持 typescript、jsx、flow 等語法
  • transform:對 AST 進行轉換,通過 visitor 對不同的 AST 進行處理
  • generate:打印轉換后的 AST 為目標代碼,并生成 sourcemap

轉換插件這樣寫(小冊中的一個 linter 的案例):

  1. const { declare } = require('@babel/helper-plugin-utils'); 
  2.  
  3. const noFuncAssignLint = declare((api, options, dirname) => { 
  4.     api.assertVersion(7); 
  5.  
  6.     return { 
  7.         pre(file) { 
  8.             file.set('errors', []); 
  9.         }, 
  10.         visitor: { 
  11.             AssignmentExpression(path, state) { 
  12.                 const errors = state.file.get('errors'); 
  13.                 const assignTarget = path.get('left').toString() 
  14.                 const binding = path.scope.getBinding(assignTarget); 
  15.                 if (binding) { 
  16.                     if (binding.path.isFunctionDeclaration() || binding.path.isFunctionExpression()) { 
  17.                         const tmp = Error.stackTraceLimit; 
  18.                         Error.stackTraceLimit = 0; 
  19.                         errors.push(path.buildCodeFrameError('can not reassign to function', Error)); 
  20.                         Error.stackTraceLimit = tmp; 
  21.                     } 
  22.                 } 
  23.             } 
  24.         }, 
  25.         post(file) { 
  26.             console.log(file.get('errors')); 
  27.         } 
  28.     } 
  29. }); 
  30.  
  31. module.exports = noFuncAssignLint; 

聲明 visitor 函數,然后在遍歷的過程中會被調用,其中可以拿到 path 和 state 的 api:

path 是節點之間的關系,每個 path關聯父節點和當前節點,path 對象構成一條從當前節點到根結點的路徑。state 是遍歷過程中的共享數據的機制。

通過 path 的一系列增刪改查 AST 的 api 來完成 transform。

比如下列 api:

  1. getSibling(key)  
  2. getNextSibling() 
  3. getPrevSibling() 
  4. getAllPrevSiblings() 
  5. getAllNextSiblings() 
  6. isXxx(opts) 
  7. assertXxx(opts) 
  8.  
  9. insertBefore(nodes) 
  10. insertAfter(nodes) 
  11. replaceWith(replacement) 
  12. replaceWithMultiple(nodes) 
  13. replaceWithSourceString(replacement) 
  14. remove() 

jscodeshift 是怎么轉換代碼的

jscodeshift 也是代碼轉換的工具,但是 api 風格不同,是主動查找 AST,然后修改成新的 AST,最后生成代碼的形式:

  1. module.exports = function(fileInfo, api) { 
  2.   return api.jscodeshift(fileInfo.source) 
  3.     .findVariableDeclarators('foo'
  4.     .renameTo('bar'
  5.     .toSource(); 

jscodeshift 的優勢是更簡潔。

但是 jscodeshift 能代替 babel 么?可以看下大牛給出的答案:

babel 和 jscodeshift 的不同

jscodeshift 的 parser 是 recast,曾經有 babel 的維護者想結合這兩者:

https://github.com/facebook/jscodeshift/issues/168

利用 recast 做 parse,然后基于 babel parser 做轉換。

下面有一個很精彩的回復,明確了 babel 和 jscodeshift 的不同:

我來梳理一下:

babel 的 transform api 是visitor 風格,也就是聲明對什么 ast 做什么處理,然后在遍歷過程中被調用,這種不和具體遍歷方式耦合的寫法是一種設計模式(訪問者模式),處理再復雜的場景也能應對。就是處理簡單場景顯得稍微啰嗦點。

jscodeshift 是 collection 風格,類似 jquery,主動查找 ast,放到集合中操作,適合處理簡單場景,要知道每種 ast 是怎么查找到的,然后做轉換,要處理很多很多 case,萬一查找路徑不對,那可能就漏掉了一些情況,比起 babel 來,很難在復雜場景下沒有 bug。

就像 jquery 和 mvvm 的區別一樣,復雜場景還是 mvvm 的方式(babel)靠譜,不會漏掉一些 dom 沒處理。(只是一個類比)

所以,簡單場景可以用 jscodeshift,而所有場景都可以用 babel。

babel 的 visitor 的優點就是設計模式中訪問者模式的優點,不和具體遍歷方式耦合易于復用。

為什么不推薦 gogocode

gogocode 是這兩天阿里媽媽出的 ast 修改工具,基于 babel 做了一層封裝,說是簡化了 ast 操作。

api 類似這樣:

  1. $(code) 
  2.   .find('var a = 1'
  3.   .attr('declarations.0.id.name''c'
  4.   .root() 
  5.   .generate(); 

沒錯,基于 babel 的 visitor 風格的 api 封裝出了 jscodeshift 的 collection 風格的 api。

本來 babel 的 visitor 雖然寫起來麻煩一些,但是所有路徑都能夠處理到,而改成 collection 風格之后,一旦落掉了某條路徑沒錯里,就會 bug。處理的 case 特別多,不適合復雜場景。

babel 本來的 visitor 模式是一種優點,結果又在上層封裝出了 collection api。。如果想這么封裝,為啥不直接基于 jscodeshift 呢。。。我沒看懂這波操作。

我不看好這個 babel 套娃,我沒有自信保證復雜場景下能夠處理所有路徑而不遺漏 case,復雜場景我選擇直接用 babel 的 api。

總結

babel 是訪問者設計模式的實現,分離了遍歷方式和對 AST 的操作,使得操作可以復用,jscodeshift 是 collection 風格,類似 jquery,復雜場景容易落掉 case。

gogocode 基于babel 實現了 collection 風格,不看好,容易落下 case。

一句話總結:簡單場景可以用 jscodeshift,所有場景都可以用 babel,不怎么推薦 gogocode。

責任編輯:武曉燕 來源: 神光的編程秘籍
相關推薦

2021-08-31 06:51:18

Babel前端開發

2023-04-24 20:47:08

2023-08-29 22:41:02

2023-10-25 14:16:00

訓練模型

2022-03-30 09:43:19

jscodeshif自動化重構開發

2022-10-19 09:05:45

編譯程序員后端

2012-05-11 10:54:16

Qcon淘寶Fourinone

2015-05-13 19:30:21

2024-06-17 09:08:55

Linuxloop設備

2020-07-27 11:33:33

操作系統Windows游戲

2023-08-01 09:10:46

阿里媽媽

2020-09-07 06:38:54

HA高可用協議

2021-09-02 16:15:29

開發技能代碼

2021-09-11 19:46:14

配置

2015-10-23 17:35:23

LG

2021-09-17 06:28:20

JOIN阿里Java

2021-09-02 13:38:48

Eslint Babel 插件

2019-11-26 17:41:59

AI 數據人工智能

2025-05-06 07:45:12

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 天天曰天天干 | 欧美精品福利视频 | 性网址| 91久久北条麻妃一区二区三区 | 午夜精品久久久久久久99黑人 | 日韩综合色 | 日本特黄特色aaa大片免费 | 欧美黄色网络 | 精品久久久久久亚洲精品 | 青青草网 | 1级毛片 | 在线一区二区三区 | 国产激情视频在线观看 | 一区二区不卡高清 | 日韩中文一区二区三区 | 国产综合在线视频 | 日韩精品中文字幕在线 | 狠狠爱视频| 久久精品色欧美aⅴ一区二区 | 蜜桃av一区二区三区 | 欧美精品久久 | 国家aaa的一级看片 h片在线看 | 久久国色 | 久草青青草 | 香蕉国产在线视频 | 在线免费观看黄色av | 一级片子 | 国产一级视频在线播放 | 国内精品视频 | 欧美一二三区 | 欧美在线观看免费观看视频 | 久久久久久免费精品一区二区三区 | 久久精品一级 | 国产在线一区观看 | 亚洲欧美一区二区三区情侣bbw | 欧美国产精品 | 夜久久 | 成人水多啪啪片 | 欧美日韩国产综合在线 | 成年人在线视频 | 亚洲免费观看 |