Babel 手記

zhangsh發表於2018-08-22

Babel 是一個轉譯器,將 ES6+ 的語法轉譯成瀏覽器支援更好的 ES3/ES5 語法的程式碼。它的執行有三個階段:

parse(解析)=> transforming(轉碼)=> printing(輸出)

不經過配置的 Babel 實質上什麼都不會做,解析你的程式碼,轉碼後輸出相同的程式碼。只有通過增加 plugin(外掛)來告訴 babel 應該如何轉譯程式碼。而我們熟悉的 preset(預設),只是一系列 plugin 的集合,免去了一個個的配置外掛這個步驟。

Babel 的 git 倉庫是一個 monorepo,其中包含 babel 的模組、helper,以及 plugin。

babel 模組

簡要介紹 babel 中幾個模組的作用。

babel-parser

babel 中使用的解析器。預設支援解析:

  1. 最新的 ECMAScript 語法
  2. 附加註釋
  3. JSX, Flow, Typescript 語法
  4. 實驗階段的語法提案(支援至少達到 stage-0 階段的 PR)

babel-core

babel 的核心模組,核心 api 都在這個模組裡實現,比如,將字串轉譯得到 AST 的方法 babel.transform,其它的 api 如 babel.transformFile, babel.transformFileSync, babel.transformFromAst,從這些 api 的命名大概能猜到它們的作用。

babel-cli

babel 的命令列工具,支援通過命令列對檔案進行轉譯。

babel-node

會隨 babel-cli 一起安裝,安裝後在命令列輸入 babel-node,會啟動一個 REPL ,還可以通過 babel-node 命令執行 js 檔案,和 node 命令類似。

babel-register

引入該模組後,會給 noderequire 函式繫結一個鉤子,當使用 node 的 require 方法時,會自動轉譯 .es6, .es, jsx, .mjs, .js 格式的檔案(除了 node_modules 目錄下的檔案)。

babel-plugin-*

Babel 預設不會轉譯程式碼,需要通過配置外掛來增加對語法的轉譯能力(注:可以通過配置 preset 來啟用一系列外掛)。 Babel 的外掛分為兩類,一類是 Transform Plugins,直譯就是“轉譯外掛”,這些外掛會轉譯程式碼;另一類是 Syntax Plugins,直譯就是“語法外掛”,這類外掛只做一件事,就是告訴 babel 要對特定型別的程式碼進行解析。 舉例:一些需要被 polyfill 的程式碼,顯然我們需要用到 Transform Plugins 這類外掛,來把新的語法轉譯成相容性更好的舊語法;而如果我們需要解析 vue 的單檔案元件的語法,則首先需要用到 Syntax Plugins 這類外掛來告訴 babel 如何解析這類語法。

注:Transform Plugins 會自動啟用相應的 Syntax Plugins,不用特地去宣告。其次,plugin 外掛的引入和引入順序是相關的,具體可以檢視文件的對應章節

babel-preset-*

文章開始已經提到,preset(預設)只是一系列 plugin 的集合。Babel 的官方倉庫中也提供了一些預設,如 babel-preset-env, babel-preset-stage-[0~3] 是對 ECMAScript 最新語法和 api 的支援, babel-preset-flow 是對 flow 語法檢查工具的支援, babel-preset-react 是對 react 的支援,以及 babel-preset-typescript 是對 typescript 語法的支援。

babel-helper-*

helper 是一些供 babel 內部使用的工具庫。我們常會使用 babel-plugin-external-helpers 外掛,把一個檔案中重複的 helper 程式碼(通常是 polyfill 的程式碼)移到檔案頂部。

babel-polyfill

polyfill 直譯過來就是“填充工具”,作用簡單來說,就是給不支援某些 api 的舊瀏覽器打補丁,這樣一來,開發的時候就可以始終使用新的語法、api,而不用考慮舊瀏覽器的相容問題。 Babel 支援對部分新語法進行轉譯,如箭頭函式,class, let, const 關鍵字等。但對於一些新的內建物件 Promise,全域性物件的靜態方法 Array.from,內建物件的示例方法 Array.prototype.includes,以及 generator 函式,這些瀏覽器支援度不全的語法,需要增加一些 polyfill,才能確保程式碼能在舊的瀏覽器中正常執行。

注:通常是完整引入,會對全域性物件做修改,官方建議在開發應用時使用,會明顯增加打包後檔案的體積。

babel-runtime

與 babel-polyfill 的作用類似,官方建議在開發庫或外掛時使用。通常, babel-runtime 會和 babel-plugin-transform-runtime 外掛一起使用,達到按需引入 polyfill 的效果。

其它

還有其它幾個模組,如 babel-generator, babel-code-frame, babel-template, babel-traverse, babel-types,一般可能很少會和它們打交道,暫時先不討論。

相關文章