iT邦幫忙

2022 iThome 鐵人賽

DAY 18
1
Modern Web

前端技能樹的十萬個為什麼系列 第 18

Day 18 - 為什麼要用 Babel

  • 分享至 

  • xImage
  •  

前言

昨天談完 TypeScript,了解到因為瀏覽器不支援 TypeScript,所以需要一個編譯器來轉換。

於是今天我們來談談另一個編譯器,扮演的角色比 TypeScript 更加舉足輕重 - Babel

先想一下

  • Babel 是在什麼樣的時代誕生的?
  • Babel 怎麼解決問題?
  • Babel 的優缺點是什麼?
  • Babel 適合什麼情境?

Babel 是在什麼樣的時代誕生的?

隨著 ECMAScript 不斷更新版本,從 ES6 到 ES11,開發者不斷推出更易讀、好用的語法。

然而 ECMAScript 只是「規範」,從草案到定案,再到瀏覽器完成「實作」,中間的過程實在太久

也就是說,知道有新語法,卻要等好一陣子才能使用,更何況即便瀏覽器好不容易支援新語法了,也要使用者有更新才行,如果要支援老舊瀏覽器,不就沒辦法了嗎?

Babel 怎麼解決問題?

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.

Babel 的原理

整體來說有三個步驟:

  1. 解析:將原始程式碼 parse 成 AST 語法
  2. 轉換:透過各種 plugin 或 presets 來轉換 AST 語法
  3. 生成:將轉換後的程式碼,生成目標程式碼

AST

AST 淺談

其中最神秘的這個 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"
}

(汗顏

看不懂也沒關係,但看一下關鍵字可以大概猜一下:

  • CallExpression:代表「呼叫函式」這個動作
  • callee:代表被呼叫的函式 (可以找到 consolelog)
  • arguments:代表呼叫函式的參數(可以找到 hello world)

也就是說,AST 比較像是,用樹狀的結構來表示這行程式碼在做什麼事。有了這個樹狀結構(其實就是個 JSON),各個 plugin 就可以各自處理對應的程式碼,轉換成瀏覽器可以讀懂的樣子。

Plugin and Presets

babel 除了支援 ES6 外,也有支援 JSX 與 TypeScript,而這些都是透過 plugins 與 presets (preset 其實就是一組的 plugins):

甚至,你也可以自己寫一個 plugin 來轉換程式碼,AST 的原理是互通的,只要你寫的 plugin 可以讀取 AST,並轉換成相對應的格式,完全是可以的。

Babel 的優缺點是什麼?

優點

  • 使用較新的程式語法,透過 Babel 轉換,相容舊瀏覽器
  • 即便不是版本問題,依然可以透過 Babel,將一些自定義的語法(如 JSX)轉換成瀏覽器看得懂的樣子

缺點

背後原理難度高,要搞懂 AST 很難,要自己寫 plugin 更難,不過如果只是要使用基本的功能,倒是不用擔心

Babel 適合什麼情境?

基本上 Babel 可以說是標配了,但不是因為大家說他標配就是標配,而是因為如開頭說到的,ECMAScript 規範走在前面,而瀏覽器實作往往需要一段時間,而且使用者的瀏覽器版本不是我們可以控制的,在這個前提下,Babel 幾乎是必需品。

如果是純 ES5 以下的 JavaScript code,其實是不需要 Babel 的。(但這應該都是舊專案了)

結語

心智圖放大版

Babel 真的堪稱是最默默做事的一個工具,因為我以前都用 ES5 以下的寫法,長大之後(?)跳到 React 框架,CRA 跟 Webpack 都幫我處理妥妥的,導致我根本不知道 Babel 到底做了什麼XD

今天研究之後才發現,Babel 背後的原理真的有夠難,看到那個 AST 差點暈倒,不過這也是這種 compiler 工具非常有價值的地方,正是因為一般人處理不來,所以將背後邏輯封裝成黑箱,裡面在做什麼不清楚,但我只要程式碼丟進去,出來就是所有瀏覽器暢通無阻

必須感謝這些前人的努力啊~

參考資料

Babel
Introduction to Babel


上一篇
Day 17 - 為什麼要用 TypeScript
下一篇
Day 19 - 為什麼要用 ES Module
系列文
前端技能樹的十萬個為什麼30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Dylan
iT邦新手 1 級 ‧ 2022-10-30 18:04:58

發現今天心智圖的「適用情境」與昨天一樣 XD

ycchiuuuu iT邦新手 4 級 ‧ 2022-11-01 18:38:43 檢舉

謝謝你!我一定是累了QQ 已經修正囉!

我要留言

立即登入留言