iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 24
2
Modern Web

平時沒注意的 JavaScript - JS 生態系及週邊工具整理系列 第 25

Babel - 走向 JavaScript 的嶄新未來

Hello,大家好

「不只是瀏覽器!JavaScript 征服世界的第一步 - Node.js」 這邊文章後

我們終於又要介紹到另一個讓我十分興奮的專案 - 「Babel」

就如同 Node.js,嘗試把 JavaScript 語法應用在任何 runtime 的一樣

如果你記得我們上次提到的「程式語言標準化」

就可以知道,標準化的代價其中之一

就是你會有許多不同版本的 runtime,讓開發者們為了支援性而痛苦

但是,Babel 這個專案

使得在 JavaScript 標準發展的同時

我們又可以寫出相容幾乎所有瀏覽器的 code

他是怎麼做到的,背後有什麼故事?

就在接下來介紹!

Babel

前面提到過,JavaScript 有許多不同的 runtime

像是在 ES6 新增的 arrow function 這個功能(2015年的標準)

如果我們上 Can I Use 搜尋

你可以看到,IE 以及少數手機瀏覽器

至今都還沒有完全支援

或是現在最新的 async await 語法

是在 2016 年才推出的標準

對於瀏覽器開發商來說

要馬上支援,不會是一件簡單的事情

但是,就算有了標準,也要有人實作,有人用才有意義

這也就是 Babel 解決的問題

Babel 的由來

Babel 專案最早的開發者叫做 Sebastian

基本上,在 ES6 剛出來,還沒有任何瀏覽器支援的時候

有幾個 Google 的工程師寫個一個套件,叫做「Traceur」

基本上就是 ES6 -> ES5 的程式碼轉換器

他的概念很簡單,就是把像是 const let 這些還沒支援的語法

編譯成瀏覽器看的懂的版本

他最早在高中維護的專案叫做 6to5

基本上就是把 ES6 轉成 ES5

Sebastian 的故事滿激勵人心的,基本上是講一個 17 歲高中生

因為開源專案的力量走出原本澳洲家鄉的故事

基本上就是這樣

基本上這就是 Babel 這個專案本身在做的事情了

他會把 ES6, ES7, ES8, ES100 的語法都編譯成你要的版本

babel - presets

Babel 的功用基本上就是轉換 JavaScript 的程式碼

基本上身為一個編譯器,你很直接地可以想到他有三個轉換的階段

  1. parsing 跟一般編譯器一樣
    編譯的第一步,就是把程式碼編譯成 abstract syntax tree
  2. transforming
    將 abstract syntax tree,根據你想要的特性做轉換
    (Ex. 將所有的 for loop 都換成 while)
  3. generation
    重新產生符合 1. 2. 的程式碼

預設 Babel 其實是沒有任何功能的,他只會產生 abstract syntax tree,接下來編譯出一模一漾的 code

他會需要安裝各種「套件」,才能就影響第二步,transform 這個階段

Presets

當然,你可以自幹一套編譯規則來用

不過,在 Babel 裡,Preset 代表著已經被人定義好的 config

像是我今天可以自己出版 babel-preset-alxtz

我會把 for 迴圈全部編譯成 goto

Babel 本身官方有維護一些 Official Presets

像是 es2015 es2016 es2017

這些是代表把當年 ECMAScript 定稿的功能實作出來

像是這是 es2015 這個 preset 使用的所有轉換規則

他把當年定稿的 arrow function for of spread 都盡可能轉換成可通用的 JavaScript 語法

(不過這邊有個小問題,我很好奇能不能讓 Babel 不要轉換成最簡單的版本,可不可以 ES7 轉 ES6 就好)

而像是 env 這個 preset

則是根據環境變數來設定要編譯到哪個程度

像是跟我們前幾天介紹的 browserlist 搭配

或是指定 node 的版本

不帶任何參數的話,會使用 babel-preset-latest 的設定

也就是 babel 現在實作到所有最新的功能都編譯

而像是 preset-react preset-flow

就是拿來專門編譯 jsxflow 程式碼的

(雖然我不確定跟 jsx-loader 比起來會用哪種)

stages

有些 preset 我們會叫他 stage

這代表著,這些 preset 太新了

甚至還不在 ESXXX 之內

因為像是 ECMAScript 的提案,決定過程中

他們會有不同階段的提案

從 stage 0 開始

stage - 0 還沒被開會時討論過,以及只被部分拒絕的提案
stage - 1 已經討論過,並且有如何實作的提案
stage - 2 有精確定義的語法了,並且有實驗性的實作出來
stage - 3 API 跟實作詳細,等待使用者的回應
stage - 4 代表該功能/提案完全被接受,會加進當年度的 ES 裡

Babel 會盡量去更新現在有哪些提案

並且去實作他,放進相對應的 stage 裡

Transform plugin

相較於 preset 這一整包

transform plugin 就是詳細定義的轉換規則了

像是 const -> var
() => {} -> function(){}

前面我們提到的 preset ,主要都是包含一些比較通用

瀏覽器不同標準的轉譯

但是,你當然也可以有各種情境,來轉換各種規則的程式碼

這些就是最基本的 Plugin

明天

這就是 Babel 基本的故事了

https://babeljs.io/blog/2016/12/07/the-state-of-babel

想加入 babeljs 的 slack 討論可以發 issue 申請加入

https://github.com/babel/notes/issues/38

對了,babel 的英文意思是巴別塔

本身帶著「想解決語言不合」這個問題的用意


上一篇
設定 webpack.config.js 來編譯 Sass !
下一篇
設定 babel-loader 來編譯 ES6, ES7, ES8, ES-Next 的程式碼!
系列文
平時沒注意的 JavaScript - JS 生態系及週邊工具整理33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Chris
iT邦新手 4 級 ‧ 2018-02-16 10:55:14

巴別塔: 原意是上帝製造語言不合的問題,導致巴別塔無法繼續蓋下去。
「babel」專案,則是逆天行為(誤)

我要留言

立即登入留言