前言
在學(xué)習(xí)ES7的時(shí)候肯定會(huì)使用到Babel,然后就我就找了一些demo來看人家是如何配置Babel的,于是乎梧疲,各種參數(shù)就會(huì)莫名其妙的在那里颠放,于是乎排惨,一大堆問題就會(huì)在我腦海中出現(xiàn):
- Babel為什么有兩種截然不同的配置方法?(也就是Babel5 vs Babel6)
- 為什么安裝包會(huì)使用
babel-register
而不需要babel-core
碰凶? - 為什么要使用
babel-polyfill
暮芭? - 為什么preset中設(shè)置的是
stage-2
而不是其他stage
? - 有了
babel-plugin-transform-async-to-generator
還需要babel-plugin-syntax-async-functions
嗎欲低?
那么各位童鞋看到這里辕宏,如果上面的問題你的心中都明白的話,這篇文章應(yīng)該是不適合你的砾莱,否則大家可以細(xì)細(xì)聽我道來緣由瑞筐。
1、Babel5 vs Babel6
Babel6是在2015年10月30號(hào)發(fā)布的腊瑟,所以仍然有一些項(xiàng)目在使用Babel5聚假,因此你就有可能看到兩種不同的配置方法块蚌。因此我們只要大致了解一下這兩種版本之間的一些重要區(qū)別即可:
-
babel
這個(gè)npm包不再存在,取而代之的是幾個(gè)重要的核心包:babel-core
膘格、babel-cli
峭范、babel-polyfil
等。 - 每一種轉(zhuǎn)換現(xiàn)在成為了插件瘪贱,包含ES2015和JSX
- Babel6需要添加預(yù)置條件或者一系列的插件纱控,也就是說如果你想要使用ES2015的所有特性,那就添加
babel-preset-es2015
這個(gè)預(yù)置條件政敢,如果你只想要使用其某個(gè)或某幾個(gè)特性其徙,那么可以直接添加對(duì)應(yīng)的插件(轉(zhuǎn)換)即可。 -
.babelrc
現(xiàn)在成為必配的文件喷户,根據(jù)官網(wǎng)解釋唾那,Babel6已經(jīng)移除了默認(rèn)的轉(zhuǎn)換,如果你沒有指定任何插件/預(yù)置條件褪尝,那么Babel將返回原始代碼闹获。(要知道在Babel5中是默認(rèn)將ES2015和React作為默認(rèn)的轉(zhuǎn)換的) -
stage-0
現(xiàn)在分離成一個(gè)預(yù)置條件,而不是一個(gè)選項(xiàng) - 選項(xiàng)
--external-helpers
現(xiàn)在也稱為了一個(gè)插件河哑。
至于如何升級(jí)Babel6可以參考Quick guide: how to update Babel 5.x -> 6.x
2避诽、Babel Package
Babel Package包含了幾類:核心包、外圍包璃谨、預(yù)置條件包沙庐、插件包。我們根據(jù)官網(wǎng)的解釋來大致了解一下這些包佳吞,讓大家心中有數(shù)拱雏,以后使用Babel的時(shí)候可以自己決斷,而不是到處去問底扳。
2.1铸抑、核心包
-
babel-core
:babel的編譯器;它暴露了babel.transform
方法衷模。 -
babylon
:Babel的分析器 -
babel-traverse
:Babel的遍歷器鹊汛,所有的transformers都使用該工具遍歷所有的AST(抽象語法樹)。 -
babel-generator
:Babel生成器阱冶。
整個(gè)編譯器就被分成了三部分:分析器刁憋、轉(zhuǎn)換器、生成器熙揍,大致的流程是:
輸入字符串 -> babylon分析器 -> 得到AST -> 轉(zhuǎn)換器 -> 得到AST -> babel-generator -> 輸出
2.2职祷、外圍包
-
babel-cli
是可以運(yùn)行babel-core
的CLI工具(包含了babel-node
命令),通過它你可以編譯一個(gè)文件、一個(gè)目錄然后輸出到一個(gè)文件或一個(gè)目錄或者stdout中有梆。 -
babel-types
用于檢驗(yàn)是尖、構(gòu)建、改變AST節(jié)點(diǎn) -
babel-polyfill
只是core-js
和regenerator-runtime的一個(gè)簡(jiǎn)單封裝泥耀。 -
babel-runtime
類似于polyfill除了它不會(huì)修改全局作用域并且是和babel-plugin-transform-runtime
一起使用的饺汹。 -
babel-register
:通過綁定到node的require中實(shí)現(xiàn)在程序運(yùn)行的時(shí)候自動(dòng)編譯文件的功能。 -
babel-template
是一個(gè)輔助性功能痰催,用來生成AST節(jié)點(diǎn)兜辞。這樣的話你就可以傳遞給一段你想創(chuàng)建的代碼而不用繁瑣地使用babel-types
來編譯它們。 -
babel-helpers
是一組預(yù)先做好的babel-template
功能夸溶,用在一些插件上逸吵。 -
babel-code-frame
是一個(gè)獨(dú)立的包,用于生成錯(cuò)誤缝裁,并打印對(duì)應(yīng)的源碼以及源碼錯(cuò)誤的位置扫皱。
2.3、預(yù)置條件包
預(yù)置條件只是一組簡(jiǎn)單的插件集合讓你更容易地運(yùn)行整個(gè)一組轉(zhuǎn)換器而不需要手動(dòng)去指定捷绑。目前官方維護(hù)的預(yù)置條件有下面幾個(gè):
babel-preset-es2015
babel-preset-es2016
babel-preset-es2017
babel-preset-latest
babel-preset-stage-0
babel-preset-stage-1
babel-preset-stage-2
babel-preset-stage-3
babel-preset-react
2.4韩脑、插件包
如今的Babel運(yùn)作都是依靠這些插件包了,插件包分為轉(zhuǎn)換插件以及語法插件粹污。這個(gè)類型的包比較多段多,就不列出來了,可以參考:http://babeljs.io/docs/plugins/壮吩。
如果你想查找每個(gè)預(yù)置條件包含的哪些轉(zhuǎn)換插件进苍,也可以在上面的鏈接上找到。值得注意的一點(diǎn)是:轉(zhuǎn)換插件已經(jīng)包含了語法插件鸭叙,所以無需二者同時(shí)引用進(jìn)來琅捏, 這個(gè)剛好解答了問題5!
3递雀、Babel-register
要回答問題2其實(shí)很簡(jiǎn)單,看一下babel-register的package.json文件就知道了蚀浆,它依賴了babel-core
缀程,所以自然就不需要了。根據(jù)第2.2小節(jié)的介紹市俊,我們知道babel-register
是綁定了node的require命令杨凑,每當(dāng)我們使用require文件加載后綴為.es6
、.es
摆昧、.jsx
撩满、.js
的時(shí)候都會(huì)自動(dòng)使用Babel進(jìn)行編譯轉(zhuǎn)換。因?yàn)檫@種轉(zhuǎn)換是實(shí)時(shí)轉(zhuǎn)換,所以建議只在開發(fā)環(huán)境下使用伺帘。
默認(rèn)是不會(huì)去轉(zhuǎn)換node_modules下的文件昭躺,不過也可以配置重寫:
require("babel-register")({
// This will override `node_modules` ignoring - you can alternatively pass
// an array of strings to be explicitly matched or a regex / glob
ignore: false
});
ignore
可以使用正則表達(dá)式、函數(shù)形式來使用伪嫁。同時(shí)還提供了only
领炫、extensions
進(jìn)行配置,具體參考Require Hook。
4张咳、babel-polyfill
回答問題3需要知道該包是干嘛的帝洪,上面的小節(jié)中略微提過,不過不夠細(xì)致脚猾。我們知道Babel默認(rèn)是只轉(zhuǎn)換JS的語法的葱峡,一些重要的API如Promise
、WeakMap
龙助,一些靜態(tài)方法Array.from
或Object.assign
砰奕、實(shí)例方法Array.prototype.includes
以及生成器函數(shù)都是沒有轉(zhuǎn)換的。這個(gè)時(shí)候我們就需要該包來進(jìn)行轉(zhuǎn)碼泌参。polyfill是會(huì)添加到全局作用對(duì)象中去就像原生的原型String
一樣脆淹。
Babel默認(rèn)不轉(zhuǎn)碼的API非常多,詳細(xì)清單可以查看babel-plugin-transform-runtime
模塊的definitions.js沽一。
所以如果你想體驗(yàn)完整的ES6盖溺,那么還是建議添加該包。
5铣缠、preset
想要理解preset中的stage
烘嘱,那么你就需要閱讀TC39。TC39是專門負(fù)責(zé)演進(jìn)ECMAScript編程語言以及認(rèn)證其規(guī)格的委員會(huì)蝗蛙。他們將ECMAScript中的每一個(gè)新特性的最終定稿分為了5個(gè)階段蝇庭,也就是大家看到的:
- stage-0 - Strawman: just an idea, possible Babel plugin.
- stage-1 - Proposal: this is worth working on.
- stage-2 - Draft: initial spec.
- stage-3 - Candidate: complete spec and initial browser implementations.
- stage-4 - Finished: will be added to the next yearly release.
那么我們?nèi)绾闻袛辔覀冃枰褂玫膕tage是哪一個(gè)呢?
在TC39的提案中捡硅,有對(duì)應(yīng)的一個(gè)詳細(xì)的列表表明哪種特性處于哪個(gè)階段:https://github.com/tc39/proposals 哮内。 如果你想要用到對(duì)應(yīng)的特性,查找其處于的階段即可壮韭。
Babel是會(huì)根據(jù)每一次TC39的會(huì)議更改的特性實(shí)時(shí)地改變自己的代碼實(shí)現(xiàn)北发,這一點(diǎn)做的相當(dāng)給力。一般我們不建議使用stage-0喷屋,因?yàn)樵撾A段的特性是最不穩(wěn)定的琳拨,極有可能在未來中不會(huì)集成到任何的JS版本中去。
注意:stage預(yù)置條件是會(huì)后向兼容的屯曹,也就是說stage-0的預(yù)置條件是會(huì)包含stage-1狱庇、stage-2惊畏、stage-3等預(yù)置條件的
至此5個(gè)問題已經(jīng)回答完畢(啊密任?問我沒有回答第5題颜启?那請(qǐng)仔細(xì)看看前面說的哈),不知道大家對(duì)Babel有了更加細(xì)致的認(rèn)識(shí)了批什?寫完這篇我就立馬發(fā)現(xiàn)組內(nèi)的項(xiàng)目中有一個(gè)項(xiàng)目的Babel使用有一些不合理的地方农曲,立馬修改優(yōu)化去了~~~~~~
參考
- http://jamesknelson.com/the-six-things-you-need-to-know-about-babel-6/
- https://babeljs.io/blog/2015/10/31/setting-up-babel-6
- https://github.com/babel/babel
- 插件與預(yù)置條件的關(guān)系
- Babel用戶手冊(cè)
最后
歡迎訪問我的個(gè)人博客主頁:豆米的博客