昨天談完 TypeScript,了解到因為瀏覽器不支援 TypeScript,所以需要一個編譯器來轉換。
於是今天我們來談談另一個編譯器,扮演的角色比 TypeScript 更加舉足輕重 - Babel
隨著 ECMAScript 不斷更新版本,從 ES6 到 ES11,開發者不斷推出更易讀、好用的語法。
然而 ECMAScript 只是「規範」,從草案到定案,再到瀏覽器完成「實作」,中間的過程實在太久。
也就是說,知道有新語法,卻要等好一陣子才能使用,更何況即便瀏覽器好不容易支援新語法了,也要使用者有更新才行,如果要支援老舊瀏覽器,不就沒辦法了嗎?
Babel 是一個 JavaScript 編譯器,專門用來將 ECMAScript 2015 以上(即 ES6 以上) 的程式碼,轉成可以向下相容的版本,讓較舊的瀏覽器也能夠解讀:
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
整體來說有三個步驟:

其中最神秘的這個 AST(Abstract Syntax Tree),抽象語法樹,可以用這個網站來玩玩看,在左邊輸入一般的程式碼,就可以在右邊看到解析成 AST 的樣子。
比如輸入
console.log('hello world');
它的 AST 就會是:
{
  "type": "Program",
  "start": 0,
  "end": 27,
  "body": [
    {
      "type": "ExpressionStatement",
      "start": 0,
      "end": 27,
      "expression": {
        "type": "CallExpression",
        "start": 0,
        "end": 26,
        "callee": {
          "type": "MemberExpression",
          "start": 0,
          "end": 11,
          "object": {
            "type": "Identifier",
            "start": 0,
            "end": 7,
            "name": "console"
          },
          "property": {
            "type": "Identifier",
            "start": 8,
            "end": 11,
            "name": "log"
          },
          "computed": false,
          "optional": false
        },
        "arguments": [
          {
            "type": "Literal",
            "start": 12,
            "end": 25,
            "value": "hello world",
            "raw": "'hello world'"
          }
        ],
        "optional": false
      }
    }
  ],
  "sourceType": "module"
}
(汗顏
看不懂也沒關係,但看一下關鍵字可以大概猜一下:
console 跟 log)hello world)也就是說,AST 比較像是,用樹狀的結構來表示這行程式碼在做什麼事。有了這個樹狀結構(其實就是個 JSON),各個 plugin 就可以各自處理對應的程式碼,轉換成瀏覽器可以讀懂的樣子。
babel 除了支援 ES6 外,也有支援 JSX 與 TypeScript,而這些都是透過 plugins 與 presets (preset 其實就是一組的 plugins):
甚至,你也可以自己寫一個 plugin 來轉換程式碼,AST 的原理是互通的,只要你寫的 plugin 可以讀取 AST,並轉換成相對應的格式,完全是可以的。
背後原理難度高,要搞懂 AST 很難,要自己寫 plugin 更難,不過如果只是要使用基本的功能,倒是不用擔心
基本上 Babel 可以說是標配了,但不是因為大家說他標配就是標配,而是因為如開頭說到的,ECMAScript 規範走在前面,而瀏覽器實作往往需要一段時間,而且使用者的瀏覽器版本不是我們可以控制的,在這個前提下,Babel 幾乎是必需品。
如果是純 ES5 以下的 JavaScript code,其實是不需要 Babel 的。(但這應該都是舊專案了)

Babel 真的堪稱是最默默做事的一個工具,因為我以前都用 ES5 以下的寫法,長大之後(?)跳到 React 框架,CRA 跟 Webpack 都幫我處理妥妥的,導致我根本不知道 Babel 到底做了什麼XD
今天研究之後才發現,Babel 背後的原理真的有夠難,看到那個 AST 差點暈倒,不過這也是這種 compiler 工具非常有價值的地方,正是因為一般人處理不來,所以將背後邏輯封裝成黑箱,裡面在做什麼不清楚,但我只要程式碼丟進去,出來就是所有瀏覽器暢通無阻。
必須感謝這些前人的努力啊~