【工具向】我所知道的babel總結

這兩天研究了一下babel這個工具,由於平時項目基本都是腳手架生成的babel配置文件,真正本身想寫點東西的時候,親自去配倒是一臉懵逼,寫下這篇博客記錄一下個人認知範圍內的babel總結。
首先,先看幾個平時常見的babel配置
圖片描述
圖片描述
圖片描述
圖一:vue的webpack-template生成的babel配置
圖二:react的create-react-app腳手架eject模式生成的babel配置
圖三:一個常見的普通配置,有presets和plugins
這三張圖看完文章應該均可以理解了vue

babel-core

首先什麼是babel?
官網的介紹是:Use next generation JavaScript, today.
簡單的說,就是讓你能夠在此時此刻此地使用下一代JavaScript語法和API,babel能夠幫助你轉換成瀏覽器能夠運行的穩定的版本,由於各大瀏覽器對es6+的支持並不都很好。
且從babel6以及更高版本,babel自身不負責轉換工做,具體的轉換工做由插件來實現,babel只提供babel-core來把JavaScript代碼分析爲AST(抽象語法樹),供插件作轉換。react

如何使用babel

通用的方式是在項目中寫 .babelrc文件,或者在package.json中配置"babel"選項(圖二react腳手架就是這麼作的)webpack

plugins、presets、transform-runtime、stage-X、env和babel-polyfill

npm install babel-core --save-d
寫一個這樣的例子git

let a = 'a';
let assign = Object.assign({name: 'jack'}, {name: 'bob'});
let f = () => {
  console.log('arrow func');
}
let i = [].includes;
let p = new Promise();
var q = async function q() {
  console.log('async');
};

這是一段典型的es6語法的代碼,爲了將它轉換爲es5代碼,咱們須要使用插件來轉換。
圖片描述
能夠看到這有許多的插件供選擇,只須要挑選合適的插件便可,
.babelrc文件配置以下:es6

{
  "plugins": [
    "some plugin",
    "some plugin",
    ...
  ]
}

可是若是須要不少不少插件的話,一個一個寫是很費力的
因此,presets能夠拯救咱們,presets能夠理解爲plugin的集合
繼續配置.babelrc文件:github

{
  "presets": [
    "es2015",
  ],
  "plugins": [
  ]
}

編譯完的結果爲
圖片描述
能夠看到只轉換了let箭頭函數這樣的語法,assign、includes、Promise、async被原樣輸出
這個時候就須要transform-runtime了web

{
  "presets": [
    "es2015"
  ],
  "plugins": [
    "transform-runtime"
  ]
}

編譯完的結果爲:
圖片描述npm

能夠看到let、箭頭函數、Object.assign、Promise都被正確編譯,可是async、includes依然沒有變化
此時能夠引入stage-X的概念了,Stage-x preset 中的任何轉換都是對未被批准爲 JavaScript 版本一部分的語言的變化,大白話就是還未被髮布的版本中的語法,好比如今JavaScript的最新規範版本的es6,因此es7的一些語法咱們就須要引入stage-X來使用,好比async這樣的語法。
不成熟的想法(stage-0:Strawman)——>經過以後變成提議(stage-1:Proposal)——>經過進入草案(stage-2: Draft)——>經過進入候選(stage-3: Candidate)——>進入標準(stage-4:finished)能夠看到這裏面有個層層篩選的過程,因此stage-0包含的功能最多,要是不知道哪一個階段的功能,直接stage-0
至於stage-0、stage-一、stage-二、stage-3分別具體的使用,看文檔babel-stage
繼續配置.babelrcjson

{
  "presets": [
    "es2015"
    "stage-0"
  ],
  "plugins": [
    "transform-runtime"
  ]
}

編譯結果:
圖片描述
圖雖然沒截全,可是能夠看到async方法被轉換過來了,然而includes方法依然沒有轉換。
此時就要使用babel-polyfill了,babel-polyfill會仿效一個完整的 ES2015+ 環境,這意味着你可使用新的內置對象好比 Promise 或者 WeakMap, 靜態方法好比 Array.from 或者Object.assign, 實例方法好比 Array.prototype.includes 和生成器函數。簡言之,babel-polyfill就像lodash這種庫同樣,引入以後能夠爲所欲爲的使用es6+的方法。
使用方法:segmentfault

import "babel-polyfill"

module.exports = {
    entry: ["babel-polyfill", "./index.js"]
};

最後,env是什麼意思呢?它是environment的縮寫,根據你支持的環境自動決定適合你的 Babel 插件的 Babel presets,其實就是根據你的環境來自動決定插件集合。

總結

plugin:真正作轉換工做的,寫在plugins數組中,實現一些語法的轉換
presets:一組插件
stage-X:轉換一些還未正式發佈的語法,例如async
presets-env:根據你支持的環境自動決定適合你的 Babel 插件的 Babel presets
transform-runtime:轉換一些對象以及方法,例如Promise、Set,而且它動態提供你所使用的插件,且不會強行的修改全局對象的prototype,可是runtime不會轉換實例方法,只會轉換靜態方法。最後,寫工具庫的時候考慮使用transform-runtime,不會衝突
babel-polyfill:這是一個庫,安裝的時候咱們須要讓它成爲一個 dependency, 而不是一個 devDependency,且它直接在全局對象上擴展,能夠很自由的使用es6+,能夠轉換實例方法和靜態方法,使用它能夠取代transform-runtime和presets。可是它的問題是體積較大回帶來許多咱們並用不到的東西以及可能會帶來衝突,須要兼容平臺和環境較多時考慮使用

參考:
https://juejin.im/entry/5a290...
https://github.com/youngwind/...
https://segmentfault.com/a/11...

相關文章
相關標籤/搜索