babel的一些經常使用知識點整理

關於bable的一些知識點整理node

babel-polyfill 的做用 和 runtime react

babel-cli babel-corewebpack

babel-preset-env babel-preset-preset-stage-2es6

babel-loaderweb

babel使用方法:json

  1. 使用單體文件
  2. 使用命令行
  3. 構建工具的插件

運行方式和插件

babel總共分爲3個階段: 解析,轉換和生成數組

babel自己不具備任何轉換功能, 若是沒有plugin,那麼通過babel的代碼和輸入的是相同的。瀏覽器

babel插件分爲兩種babel

  1. 語法插件:在解析的過程當中,能使babel可以解析更多的語法
  2. 轉譯插件: 在轉換的過程當中將代碼輸出。好比將箭頭函數轉譯成正常的函數

用了轉譯插件後,就不須要用語法插件了,由於同一語法可能同時存在語法插件和轉譯插件。async

經常使用的一些插件問題

preset

preset是一套規範, 裏面包含了幾十個轉譯插件。這是一組插件的集合

preset能夠分爲下面幾種:

  1. 按官方內容: env, react, flow, minify
  2. stage-x, 包含當年最新規範的草案,每一年更新
    每一個stage是不同的,能夠分爲如下幾點

    • Stage 0 - 稻草人: 只是一個想法,通過 TC39 成員提出便可。
    • Stage 1 - 提案: 初步嘗試。
    • Stage 2 - 初稿: 完成初步規範。
    • Stage 3 - 候選: 完成規範和瀏覽器初步實現。
    • Stage 4 - 完成: 將被添加到下一年度發佈。
低一級的stage會包含全部高級stage的內容,stage-1包含stage-2,stage-3的全部內容。

stage-4 在下一年更新會直接放到env中,因此沒有單獨的stage-4可供使用。
    
env是一個每一年更新的preset.

執行順序

  1. plugin會運行在Preset以前
  2. plugin從前到後順序執行
  3. preset的順序是從後向前

插件和 preset 只要列出字符串格式的名字便可。但若是某個 preset 或者插件須要一些配置項(或者說參數),就須要把本身先變成數組。第一個元素依然是字符串,表示本身的名字;第二個元素是一個對象,即配置對象。

"presets": [
    // 帶了配置項,本身變成數組
    [
        // 第一個元素依然是名字
        "env",
        // 第二個元素是對象,列出配置項
        {
          "module": false
        }
    ],

    // 不帶配置項,直接列出名字
    "stage-2"
]

babel-cli

cli是命令工具,安裝了以後,就可以在命令行中使用babel命令來編譯文件

因此babel-cli 安裝爲 devDependencies

### babel-node

babel-node是babel-cli的一部分,不須要獨立安裝

他使得可以在node環境中,直接運行es2015的代碼,不須要額外進行轉碼。

babel-node = babel-polyfill + babel-register

### babel-register

babel-register 改寫require命令, 爲它加上一個鉤子。每當使用require加載.js、.jsx、.es 和 .es6 後綴名的文件, 就會先用babel進行轉碼。

使用時,必須先加載require('babel-register')。可是babel-register只會對加載的文件轉碼,對當前文件是不會騎左右的。

並且他屬於實時轉碼,只適用於開發環境使用

### babel-polyfill

babel只轉換js語法,不轉換API,如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局對象,以及一些定義在全局對象上的方法(好比 Object.assign)都不會轉碼。

可是能夠用babel-polyfill進行轉碼。

使用時,在全部代碼運行以前增長 require('babel-polyfill')。或者更常規的操做是在 webpack.config.js 中將 babel-polyfill 做爲第一個 entry。所以必須把 babel-polyfill 做爲 dependencies 而不是 devDependencies

可是他的缺點是:

  1. 使用babel-polyfill 會致使打出來的包很是大。babel-polyfill 是一個總體,把全部的方法都加到原型鏈上。若是咱們只使用了Array.from,可是他會把Object.defineProperty也給加上。
  2. babel-polyfill會污染全局變量,給不少類的原型鏈上都做了修改。

因此在實際過程當中,一般傾向於用babel-plugin-transform-runtime

可是若是代碼中有高版本的js中類型的實例方法([1,2,3].includes(1)),就只能用polyfill了。這個至關因而墊片。

babel-runtime 和 babel-plugin-transform-runtime

bable 會轉譯js語法,舉個async/await例子

// babel 添加一個方法,把 async 轉化爲 generator
function _asyncToGenerator(fn) { return function () {....}} // 很長很長一段

// 具體使用處
var _ref = _asyncToGenerator(function* (arg1, arg2) {
  yield (0, something)(arg1, arg2);
});

這裏_asyncToGenerator在當前文件被定義的,而後被使用了。若是每一個文件都有用async/await方法,那麼每一個文件都會有_asyncToGenerator 這段,會致使重複和浪費。

用了babel-plugin-transform-runtime以後,轉換的代碼就變成

// 從直接定義改成引用,這樣就不會重複定義了。
var _asyncToGenerator2 = require('babel-runtime/helpers/asyncToGenerator');
var _asyncToGenerator3 = _interopRequireDefault(_asyncToGenerator2);

// 具體使用處是同樣的
var _ref = _asyncToGenerator3(function* (arg1, arg2) {
  yield (0, something)(arg1, arg2);
});

這裏就至關於引用了一個模塊代碼,就不存在重複的問題了。

因此這就是用babel-plugin-transform-runtime的好處,而babel-runtime就是爲這些方法提供了集合。因此在使用babel-plugin-transform-runtime的時候,須要babel-runtime作依賴

babel-runtime

babel-runtime 內部集成了

  1. core-js: 轉換一些內置類(Promise, Symbol)和靜態方法(Array.from等)。絕大部分的引用都是這裏作的,自動引入。
  2. regenerator: 是做爲core-js的拾遺補漏,主要是generator/yieldasync/await兩組作支持。當代碼中有generators/async時會自動引入。
  3. helpers

babel-plugin-transform-runtime 不支持 實例方法 (例如 [1,2,3].includes(1))

babel-loader

主要使用在構建工具中。babel-loader和babel-cli同樣,會讀取.babelrc或者package.json中的babel段做爲本身的配置,可是babel-loader必需要和webpack作交互。

名稱 做用 備註
babel-cli 容許命令行使用 babel 命令轉譯文件
babel-node 容許命令行使用 babel-node 直接轉譯+執行 node 文件 隨 babel-cli 一同安裝.babel-node = babel-polyfill + babel-register
babel-register 改寫 require 命令,爲其加載的文件進行轉碼,不對當前文件轉碼 只適用於開發環境
babel-polyfill 爲全部 API 增長兼容方法 須要在全部代碼以前 require,且體積比較大
babel-plugin-transform-runtime & babel-runtime 把幫助類方法從每次使用前定義改成統一 require,精簡代碼 babel-runtime 須要安裝爲依賴,而不是開發依賴
babel-loader 使用 webpack 時做爲一個 loader 在代碼混淆以前進行代碼轉換

一口(很長的)氣了解 babel

相關文章
相關標籤/搜索