Babel 是一個轉譯器,將 ES6+ 的語法轉譯成瀏覽器支援更好的 ES3/ES5 語法的程式碼。它的執行有三個階段:
parse(解析)=> transforming(轉碼)=> printing(輸出)
不經過配置的 Babel 實質上什麼都不會做,解析你的程式碼,轉碼後輸出相同的程式碼。只有通過增加 plugin(外掛)來告訴 babel 應該如何轉譯程式碼。而我們熟悉的 preset(預設),只是一系列 plugin 的集合,免去了一個個的配置外掛這個步驟。
Babel 的 git 倉庫是一個 monorepo,其中包含 babel 的模組、helper,以及 plugin。
babel 模組
簡要介紹 babel 中幾個模組的作用。
babel-parser
babel 中使用的解析器。預設支援解析:
- 最新的 ECMAScript 語法
- 附加註釋
- JSX, Flow, Typescript 語法
- 實驗階段的語法提案(支援至少達到 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
引入該模組後,會給 node
的 require
函式繫結一個鉤子,當使用 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
,一般可能很少會和它們打交道,暫時先不討論。