博客講解內容以下:javascript
凡是看到這個標題點進來的同窗,相信對babel都有了必定的瞭解。babel使用起來很簡單,簡單到都沒有必要寫一篇文章去介紹,直接看看官方文檔就能夠。因此我也在懷疑到底該不應寫這篇文章。想來想去仍是決定動手寫寫,緣由是很簡單,本身在剛開始接觸babel也出現過懵逼的狀態,因此但願這篇文檔能給其餘人以幫助。html
babel官網正中間一行黃色大字寫着「babel is a javascript compiler」,翻譯一下就是babel是一個javascript轉譯器。爲何會有babel存在呢?緣由是javascript在不斷的發展,可是瀏覽器的發展速度跟不上。以es6爲例,es6中爲javascript增長了箭頭函數、塊級做用域等新的語法和Symbol、Promise等新的數據類型,可是這些語法和數據類型並不可以立刻被如今的瀏覽器所有支持,爲了能在現有的瀏覽器上使用js新的語法和新的數據類型,就須要使用一個轉譯器,將javascript中新增的特性轉爲現代瀏覽器能理解的形式。babel就是作這個方面的轉化工做。java
在這裏有必要簡單講一下javascript版本,我只是大致講下,javascript是網景公司開發的一種腳本語言,1996年的時候以ECMAScript的名字正式成爲一種標準。2007年的時候發佈了版本es5,而後在隨後近10年裏js並無大的變化。因此如今的瀏覽器均可以很好的支持es5。這一局面直到2015年被打破。2015年6月,TC39(javascript標準的制定組織)公佈了新版本的js語言——ES6。並且從ES6開始,TC39規定每一年都要發佈一個js的新版本,新版本將包含年號,都是以ESxxxx的方式進行命名。因此2015年發佈的ES6又叫ES2015,2016年發佈的新的js版本就叫ES2016,2017年發佈的新的js版本就叫ES2017……。node
由於版本都是向前兼容的,就是老版本js版本中規定的語法和api在新版本的js中一樣也會合理的。因此咱們能夠想到後面的規範確定是包含前面的規範的,也就是ES2016版本的js規範是包含ES2015(ES6)規範的,ES2017是包含ES2016的也包含ES2015的。針對不一樣的規範,Babel也提供了對應的轉換器。react
babel-preset-es2015 將es2015版本的js轉譯爲es5。webpack
babel-preset-es2016 將es2016版本的js轉譯爲es5。es6
babel-preset-es2017 將es2017版本的js轉譯爲es5。web
在轉譯過程當中遇到更高版本的js語法,babel是會直接忽略的。算法
在這裏在簡單講一下js新規範的製做過程。chrome
js規範的製做分4個階段。
Stage0 :任何還沒有提交爲正式提案的討論,想法,改變或對已有規範的補充建議都被認爲是一個稻草人草案(「strawman」 proposal),但只有TC39成員能夠提出此階段的草案。
Stage1 :此階段,稻草人草案升級爲正式化的提案,並將逐步解決多部門關切的問題,如與其餘提案的相互之間會有什麼影響,這一草案具體該如何實施等問題。人們須要對這些問題提供具體的解決方案。stage1的提案一般還須要包括API描述,擁有說明性使用示例,並對語義和算法進行討論,通常來講草案在這一階段會經歷巨大的變化。
Stage2 :此階段,草案就有了初始的規範。經過polyfill(打補丁。編寫一些代碼實現瀏覽器以前不支持的功能),開發者能夠開始使用這一階段的草案了,一些瀏覽器引擎也會逐步對這一階段的規範的提供原生支持,此外經過使用構建工具(相似babel的工具)也能夠編譯源代碼爲現有引擎能夠執行的代碼,這些方法都使得這一階段的草案能夠開始被使用了。
State3 :此階段的規範就屬於候選推薦規範了,這一階段以後變化就不會那麼大了,要達到這一階段須要知足如下條件:
規範的編輯和指定的審閱者必須在最終規範上簽字;
用戶也應該對該提議感興趣;
提案必須至少被一個瀏覽器原生支持;
擁有高效的ployfill,或者被Babel支持;
Stage4 :此階段的提案必須有兩個獨立的經過驗收測試的實現,進入第4階段的提案將包含在 ECMAScript 的下一個修訂版中。
針對js規範的不一樣階段,babel也提供了對應的轉譯器
Stage0:preset-stage-0
Stage1:preset-stage-1
Stage2:preset-stage-2
Stage3:preset-stage-3
不一樣階段的轉譯器之間是包含的關係,preset-stage-0轉譯器除了包含了preset-stage-1的全部功能還增長了transform-do-expressions插件和transform-function-bind插件,一樣preset-stage-1轉譯器除了包含preset-stage-2的所有功能外還增長了一些額外的功能……。
好了,javascript的製做規範大致講完了,如今咱們來說下babel轉譯器。
爲了便於說明,首先咱們來定義兩個概念。
轉譯插件,轉譯插件是用來轉譯單一功能的插件,好比transform-es2015-arrow-functions,這個插件只負責轉譯es2015新增的箭頭函數。
轉譯器,轉譯器是一系列轉譯插件的集合。好比babel-preset-es2015就包含了es2015新增語法的全部轉譯插件,好比包含transform-es2015-arrow-functions(es2015箭頭函數轉譯插件)、transform-es2015-classes(es2015 class類轉譯插件)等。
js規範新增的每一個語法都有對應的babel插件,所以babel插件衆多。爲了便於管理,會把某些插件集合在一塊兒,構成一個轉譯器。要否則若是咱們想轉譯es2015的語法就要安裝一大堆插件了,有了轉譯器以後咱們只須要安裝一個轉譯器就能夠了。babel的轉譯器根據用途的不一樣也分了不一樣給的類,這些類很是多,因此babel看起來很混亂。不過大致上babel的轉譯器分爲3類。
語法轉譯器,這些轉譯器只負責轉譯js最新的語法,並不負責轉譯js新增的api和全局對象。這類轉譯器包括babel-preset-env、babel-preset-es201五、babel-preset-es201六、babel-preset-es201七、babel-preset-latest等,之後確定還會有新的轉譯器加入,不過你只要理解轉譯器就是一堆轉譯插件的集合就能夠了。
補丁轉譯器,這些轉譯器只負責轉譯js最新的api和全局對象。好比瀏覽器不支持String新增的String.padStart方法和Promise全局對象。經過babel-profill轉譯,咱們能夠經過其餘代碼來讓瀏覽器實現相似String.padStart和Promise的功能。
jsx和flow插件,這類轉譯器用來轉譯JSX語法和移除類型聲明的,使用Rect的時候你將用到它,轉譯器名稱爲babel-preset-react
另外你能夠對babel已有的轉譯器進行改造或者建立新的轉譯器。如何建立babel轉譯器能夠點這裏。
babel支持的使用場景很是多,能夠在瀏覽器中使用(browser)也能夠在命令行(cli),還能夠是咱們常見的gulp和webpack中。
如下以安裝babel-cli爲例進行說明。babel更多的使用方法請點擊這裏。
在本地磁盤上建立一個文件夾es6(名字任意),在該文件夾下打開命令行工具,初始化項目。
D:\webpack\demo\es6>npm init -y
這個命令目的就是建立一個默認的package.json文件。
安裝babel的命令行工具的目的是爲了在命令行使用babel。
babel命令行工具能夠全局安裝也能夠本地安裝,官方文檔推薦本地安裝,緣由有2點;
本地安裝不一樣的項目可使用不一樣版本的babel,你也能夠單獨對某個項目的babel進行升級等操做
每一個項目單獨安裝的意味着對計算機環境沒有依賴,便於移植
在命令行中繼續執行以下命令
npm install --save-dev babel-cli
若是你已經全局安裝了babel,可使用以下的命令進行卸載
npm uninstall --global babel-cli
這樣就已經在本地安裝好babel了。
此時個人package.json文件以下(請忽略main字段)。
{ "name": "es6", "version": "1.0.0", "description": "", "main": "arrow.js", //請忽略main字段 "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1" } }
本地安裝的babel是不可以在直接命令行中運行的,爲了在命令行中運行babel,咱們有兩個方法,1是須要配置下package.json文件的scripts項。好比以下代碼,配置了一個build命令,運行該命令(npm run build)的時候就會在命令行執行babel src -d lib
{ "name": "es6", "version": "1.0.0", "description": "", "main": "arrow.js", "scripts": { "build": "babel src -d lib" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1" } }
第2個方法是你須要能夠進入node_modules文件夾,再進入.bin文件夾,而後執行在命令行中執行babel src -d lib
。
推薦使用npm run build的方法。
這裏須要解釋babel src -d lib
這個命令的意思。這個命令目的是把src文件夾下的文件都轉譯,轉譯後的文件放到lib目錄下。
關於babel的命令行使用方法請點這裏
ps:此時不管你是運行npm run build 仍是運行babel src -d lib命令(其實兩個方法本質上都是同樣的,都是運行babel src -d lib)命令行都會報錯,緣由是如今尚未src文件夾。能夠先不用管它,稍後咱們再新建src文件夾。
在cmd中鍵入如下命令。
D:\webpack\demo\es6>type nul>.babelrc
這個時候你的文件夾裏就多了一個.babelrc文件了。windows是不能直接建立空文件名的文件的,因此必須經過命令行建立。
這裏咱們以babel-preset-env爲例。
在命令行中執行以下代碼就會安裝babel-preset-env轉譯器。
D:\webpack\demo\es6>npm install babel-preset-env --save-dev
注意:babel命令行工具(babel-cli)跟babel轉譯器是兩個不一樣的東西,命令行工具並不具備轉譯代碼的功能,只是爲了在命令行中使用babel。要轉碼必須安裝轉譯器,好比babel-preset-env轉譯器或者babel-preset-react轉譯器。要轉譯的時候,還要在.babelrc文件或者命令行中配置這些轉譯器(presets)選項
.babelrc用於配置除回調之外的全部babel api 選項。例如plugins和presets。plugins用於配置咱們轉譯所須要的插件,presets用於配置咱們所須要的轉譯器。
.babelrc不是必須的,咱們在.babelrc中配置的選項均可以經過命令行添加,好比在命令行執行 babel src -d lib --presets=env
等價於在.babelrc中配置 "presets":["env"]
。固然.babelrc要明顯方便不少。
babel在轉譯代碼的過程當中會自動讀取當前目錄.babelrc配置文件,若是當前目錄沒有的話就遍歷整個目錄樹去尋找,直到找到.babelrc文件或者含有"babel"字段的package.json文件,而後使用這些配置選項來轉譯代碼。
關於.babelrc的注意點以下。
一、若是沒有.babelrc文件,或者沒有在其餘文件中設置過babel的presets的配置選型,而且命令行中也沒有配置--presets,那麼代碼是不會轉譯的。原es6代碼什麼樣,轉譯後的代碼仍是什麼樣。
二、若是你的.babelrc或者你的命令行使用了你沒有安裝的轉譯器(presets),代碼就會報錯
三、但.babelrc中的配置跟你在命令行中使用的配置衝突的時候,以.babelrc中的配置爲準
{ "presets":["env"] }
關於.babelrc文件的更多使用方法請點擊這裏
若是你不想生成.babelrc文件,你能夠在你的package.json文件中對babel進行配置。若是你使用gulp或者webpack之類的管理工具的話,也能夠在這裏工具的配置選項裏添加babel的配置選項。
如下以在package.json中配置爲例。
{ "name": "es6", "version": "1.0.0", "description": "", "main": "arrow.js", "scripts": { "build": "babel src -d lib --comments=true" }, "babel":{ //babel選項 "presets":["es2015"], "comments":false }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1", "babel-loader": "^7.1.1", "babel-preset-env": "^1.6.0", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.24.1", "webpack": "^3.2.0" } }
在package.json中配置babel等同於使用.babelrc文件
由於咱們使用的babel命令是babel src -d lib
因此咱們須要在目錄中建立一個叫src的文件夾。目錄結構以下:
|-node_modules |-src |-.babelrc |-package.json
在src文件夾下咱們建立一個person.js文件(文件名任意),編寫以下es6代碼(代碼任意,只有是es6代碼便可,方便看出編譯後的效果)。編輯好代碼後保存。
class Person{ constructor(){ this.name="bigbigStrong" } sayName(){ console.log(`my name is ${this.name}`); } } var p = new Person(); p.sayName();
在命令行工具中執行npm run build
就能夠發現目錄中多了一個lib文件夾,lib文件夾下有一個person.js的文件,這個文件就是src下的person.js文件轉譯後的代碼。
D:\webpack\demo\es6>npm run build
轉譯後的代碼以下:
"use strict"; var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Person = function () { function Person() { _classCallCheck(this, Person); this.name = "bigbigStrong"; } _createClass(Person, [{ key: "sayName", value: function sayName() { console.log("my name is " + this.name); } }]); return Person; }(); var p = new Person(); p.sayName();
通過上面的步驟咱們已經完成了轉譯代碼的工做,如今咱們介紹下babel中經常使用的轉譯器和配置選項
轉譯器,最經常使用的轉譯器。經過在.babelrc中配置env選項,可讓代碼兼容不一樣版本的瀏覽器或者node。瀏覽器或者node已經支持的語法將再也不轉譯了,不支持的才轉譯。若是不配置env選項,該轉譯器等同於babel-preset-latest。更多詳情和方法點這裏
{ "presets": [ ["env", { "targets": { "browsers": ["last 2 versions", "safari >= 7"] } }] ] }
轉譯器,將es2015版本的js代碼轉譯爲es5代碼,對於es2016版本的代碼或者es2017版本的代碼不轉譯。
轉譯器,將最新版本的js代碼轉譯爲es5代碼。不推薦使用,已經廢除。建議使用babel-preset-env代替
轉譯器,剝離流類型並將JSX轉換爲createElement調用,主要在轉譯react代碼的時候使用。
要兼容老版本的ie瀏覽器,可使用對應的es3和es5插件
轉譯器就是一堆轉譯插件的集合。babel轉譯器不少,可是咱們經常使用的就那幾個。若是要轉譯新版本的js的話,只須要使用babel-presets-env這一個轉譯器就能夠了。
關於babel的更多轉譯器介紹,能夠點擊這裏查看。你能夠點擊每個轉譯器進去查看轉譯器的適用場景是使用方法
babel的配置選項在命令行的使用規則是babel --name-value
好比咱們使用es2015轉譯器,咱們的命令就是
babel src -d lib --presets=es2015
babel的配置選項很是多,每一個轉譯器也都有本身的配置選項,關於babel的配置選項的詳細功能和使用方法,請點擊這裏查看。我這裏只介紹幾個常見的。
默認值爲true,用於配置是否適用.babelrc和.babelignore文件,當命令行中添加--no-babelrc選項的時候,表示忽略.babelrc和.babelignore文件。在.babelrc文件中配置babelrc我的測試沒有卵用。
默認值爲一個空對象{}. env用於配置代碼須要兼容的環境,好比你的代碼要在chrome52上運行,能夠這樣配置.babelrc。
{ "presets": [ ["env", { "targets": { "chrome": 52 } }] ] }
配置代碼兼容最新的node,能夠這樣設置.babelrc
{ "presets": [ ["env", { "targets": { "node": "current" } }] ] }
忽略某些文件,默認值爲null,好比src文件夾下有person.js和foo.js兩個文件,轉譯的時候你要忽略src文件夾下的foo.js,能夠這樣配置.babelrc。這樣就再也不轉譯foo.js文件了
{ "presets":["env"], "ignore":["foo.js"] }
與ignore相對應的是only選項,only表示只轉譯某些文件。
是否壓縮轉譯後的代碼,默認值爲false
{ "presets":["env"], "ignore":["foo.js"], "minified":true }
配置轉譯所須要的插件。使用插件的順序是按照插件在數組中的順序依次調用的。好比以下命令,轉譯的時候先使用transform-decorators-legacy轉譯,再使用transform-class-properties轉譯
{ "plugins": [ "transform-decorators-legacy", "transform-class-properties" ] }
配置你要使用的轉譯器。使用轉譯器的順序是按照轉譯器在數組中的反順序進行調用的。先使用數組最末尾的轉譯器,而後使用倒數第2個,倒數第3個,依次類推。好比使用下面命令的時候,先使用stage-2轉譯器轉譯,再react轉譯器轉譯,最後使用es2015轉譯器轉譯。
{ "presets": [ "es2015", "react", "stage-2" ] }
詳情點這裏
若是同時存在plugins和presets,則先使用plugins轉譯
plugin的調用順序是從第一個到最後一個,
presets的調用的順序是相反的,從最後一個到第一個
bable-node是babel-cli自帶的命令,提供了一個支持ES6的REPL環境,它支持node的REPL環境的全部功能,並且能夠直接運行ES6代碼。爲了體驗下這個功能,咱們須要全局安裝babel-cli。而後在命令行執行下面的命令。
安裝
npm install --save-dev -g babel-cli
執行命令就會輸出咱們代碼執行的結果
D:\webpack\demo\es6>babel-node -e "var name='tom';console.log(`my name is ${name}`)"; //my name is tom;
babel-node的詳細用法點擊這裏
引用自阮一峯babel講解
babel-register模塊會改寫require命令,爲它加上一個鉤子。此後每當使用require加載.js
、.jsx
、.es
、.es6
後綴名文件的時候,都會先用babel進行轉碼
安裝
$ npm install --save-dev babel-register
使用的時候必須先加載babel-register。
require("babel-register"); require("./index.js");
而後,就不須要手動對index.js
轉碼了。
須要注意的是,babel-register
只會對require
命令加載的文件轉碼,而不會對當前文件轉碼。另外,因爲它是實時轉碼,因此只適合在開發環境使用。
babel-register的詳細使用方法點擊這裏
babel-core主要在node等環境中使用,能夠用來開發本身的babel轉譯器。直接調用babel的api對某些代碼或者某些文件進行轉譯。
安裝
npm install babel-core --save
使用方法
var babel =require('babel-core'); babel.transform(code,options);//轉譯程序片斷 babel.transform(filename,options,callback); //轉譯文件
babel-core的詳細使用方法點擊這裏
D:\webpack\demo\es6>npm install --save-dev webpack
若是你是跟着我這份教程一路看下來的,那麼你babel-preset-env已經安裝了。已經安裝的話就不用再安裝了。記得要安裝babel-loader就好。
D:\webpack\demo\es6>npm install --save-dev babel-preset-env babel-loader
此時你的package.json以下。確保devDependencies中有babel-loader、babel-preset-env和webpack便可,其餘的能夠跟我不一樣。
{ "name": "es6", "version": "1.0.0", "description": "", "main": "arrow.js", "scripts": { "build": "babel src -d lib" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "babel-cli": "^6.24.1", "babel-loader": "^7.1.1", "babel-preset-env": "^1.6.0", "babel-preset-react": "^6.24.1", "webpack": "^3.2.0" } }
在根目錄下建立webpack.config.js文件,內容以下。
var path = require("path"); module.exports = { entry: './src/person.js', output: { path: path.resolve(__dirname,"lib"), filename: 'person.compiled.js', }, module: { loaders: [{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', query:{ presets:["env"] } }] } }
entry爲入口文件,咱們選擇當前目錄下,src文件夾下的person.js文件做爲入口。output爲輸出選項,path爲輸出的目錄,filename爲輸出文件名。query選項爲.babelrc中的配置選項。在webpack中設置了query字段後,就再也不須要.babelrc文件了。
此時咱們的目錄結構是這樣子的。
-lib
-node_modules
-src
-person.js
-foo.js -package.json -webpack.config.js
在命令行中執行webpack,webpack會自動讀取webpack.config.js文件中的配置。而後對咱們配置的文件進行轉譯。
D:\webpack\demo\es6>webpack
打開lib文件夾,咱們發現多了一個轉譯後的文件person.compiled.js。
-lib
-person.compiled.js
-node_modules
-src
-person.js -foo.js -package.json -webpack.config.js
咱們src文件夾下除了有person.js文件外,還有一個foo.js文件。可是咱們上面的操做只轉譯了person.js文件,爲了同時轉譯foo.js文件咱們須要在person.js文件中引入foo.js
foo.js文件代碼以下:
let name="tom"; console.log(`my name is ${name}`);
咱們在person.js文件頂部中添加require("./foo");
;這樣就能夠person.js文件中添加對foo.js的依賴。修改後的person.js代碼以下:
require("./foo"); class Person{ constructor(){ this.name="bigbigStrong" } sayName(){ console.log(`my name is ${this.name}`); } } var p = new Person(); p.sayName();
這樣在編譯後的文件person.compiled.js文件裏,就包含了foo.js的代碼。
關於webpack的更多使用方法,請點擊查看webpack文檔
關於babel的知識點大概就這些。
babel經常使用的轉譯器是babel-preset-env。
經常使用的配置選項是plugins和presets
經常使用的使用場景是在webpack中
以上講的都是經常使用的,關於babel更細的知識點還須要你本身查看babel官方文檔。