Babel是一個工具鏈,主要用於將ECMAScript 2015+版本代碼向後兼容 Javascript 語法,以即可以運行到舊版本瀏覽器或其餘環境中。node
做爲一種語言,JavaScript在不斷髮展,新的標準/提案和新的特性層出不窮。在獲得普遍普及以前,Babel可以讓你提早(甚至數年)使用他們。es6
Babel 的三個主要處理步驟分別是: 解析(parse),轉換(transform),生成(generate)。npm
將代碼解析成抽象語法樹(AST),每一個js引擎(好比Chrome瀏覽器中的V8引擎)都有本身的AST解析器,而Babel是經過Babylon實現的。在解析過程當中有兩個階段:詞法分析和語法分析,詞法分析階段把字符串形式的代碼轉換爲令牌(tokens)流,令牌相似於AST中節點;而語法分析階段則會把一個令牌流轉換成 AST的形式,同時這個階段會把令牌中的信息轉換成AST的表述結構。json
在這個階段,Babel接受獲得AST並經過babel-traverse對其進行深度優先遍歷,在此過程當中對節點進行添加、更新及移除操做。這部分也是Babel插件介入工做的部分。gulp
例如,Babel可以將新的ES2015箭頭函數語法:api
const square = n => n * n;
複製代碼
轉譯爲:瀏覽器
const square = function square(n) {
return n * n;
}
複製代碼
babel的核心模塊,包括一些核心api例如:transform。bash
/* * @param {string} code 要轉譯的代碼字符串 * @param {object} options 可選,配置項 * @return {object} */
babel.transform(code: string, options?: Object)
//返回一個對象(主要包括三個部分):
{
generated code, //生成碼
sources map, //源映射
AST //即abstract syntax tree,抽象語法樹
}
複製代碼
更多AST知識點babel
一些使用babel插件的打包或構建工具都有使用到這個方法,下面是一些引入babel插件中的源碼:模塊化
//gulp-babel
const babel = require('babel-core');
/* some codes... */
module.exports = function (opts) {
opts = opts || {};
return through.obj(function (file, enc, cb) {
try {
const fileOpts = Object.assign({}, opts, {
filename: file.path,
filenameRelative: file.relative,
sourceMap: Boolean(file.sourceMap),
sourceFileName: file.relative,
sourceMapTarget: file.relative
});
const res = babel.transform(file.contents.toString(), fileOpts);
if (res !== null) {
//some codes
}
} catch (err) {
//some codes
}
}
}
//babel-loader
var babel = require("babel-core");
/* some codes... */
var transpile = function transpile(source, options) {
//some code
try {
result = babel.transform(source, options);
} catch (error) {
//some codes
}
//some codes
}
//rollup-pugin-babel
import { buildExternalHelpers, transform } from 'babel-core';
/* some codes... */
export default function babel ( options ) {
//some codes
return {
// some methods
transform ( code, id ) {
const transformed = transform( code, localOpts );
//some codes
return {
code: transformed.code,
map: transformed.map
};
}
}
}
複製代碼
Babel的CLI是一種在命令行下使用Babel編譯文件的簡單方法。主要用於文件的輸入輸出。
全局安裝
npm install -g babel-cli
複製代碼
咱們能夠這樣編譯咱們第一個文件:
babel test.js
//編譯後的文件輸出在終端
複製代碼
babel test.js -o test-out.js
//編譯後的文件輸出在test-out.js文件中
複製代碼
儘管能夠把Babel CLI全局安裝在你的機器上,可是按項目逐個安裝在本地會更好。 有兩個主要的緣由。
將Babel CLI安裝到本地能夠運行:
npm install --save-dev babel-cli
複製代碼
如今能夠不直接在命令行運行Babel了,取而代之咱們將命令寫在package.json的script裏。
只需將"scirpts"字段添加到你的package.json文件內。
{
"scripts":{
"build": "babel src -d lib",
...
},
...
}
複製代碼
如今能夠在終端裏運行:
npm run build
複製代碼
這將以與以前一樣的方式運行Babel。
babel-node是隨babel-cli一塊兒安裝的,只要安裝了babel-cli就會自帶babel-node。 在命令行輸入babel-node會啓動一個REPL(Read-Eval-Print-Loop),這是一個支持ES6的js執行環境。
babel-register字面意思能看出來,這是babel的一個註冊器,它在底層改寫了node的require方法,引入babel-register以後全部require並以.es6, .es, .jsx 和 .js爲後綴的模塊都會通過babel的轉譯。
//test.js
const name = 'test';
module.exports = () => {
const json = {name};
return json;
};
//main.js
require('babel-register');
var test = require('./test.js'); //test.js中的es6語法將被轉譯成es5
console.log(test.toString()); //經過toString方法,看看控制檯輸出的函數是否被轉譯
/* function () { var json = { name: name }; return json; } */
複製代碼
babel-polyfill在代碼中的做用主要是用已經存在的語法和api實現一些瀏覽器尚未實現的api,對瀏覽器的一些缺陷作一些修補。例如Array新增了includes方法,我想使用,可是低版本的瀏覽器上沒有,引入babel-polyfill則幫咱們添加了這些方法。
babel全部的操做基本都會來讀取這個配置文件,除了一些在回調函數中設置options參數的,若是沒有這個配置文件,會從package.json文件的babel屬性中讀取配置。
babel中的插件,經過配置不一樣的插件才能告訴babel,咱們的代碼中有哪些是須要轉譯的。
預設就是一系列插件的集合,就好像修圖同樣,把上次修圖的一些參數保存爲一個預設,下次就能直接使用。
// cnpm install -D babel-preset -env
{
"presets": [
["env", {
"targets": { //指定要轉譯到哪一個環境
//瀏覽器環境
"browsers": ["last 2 versions", "safari >= 7"],
//node環境
"node": "6.10", //"current" 使用當前版本的node
},
//是否將ES6的模塊化語法轉譯成其餘類型
//參數:"amd" | "umd" | "systemjs" | "commonjs" | false,默認爲'commonjs'
"modules": 'commonjs',
//是否進行debug操做,會在控制檯打印出全部插件中的log,已經插件的版本
"debug": false,
//強制開啓某些模塊,默認爲[]
"include": ["transform-es2015-arrow-functions"],
//禁用某些模塊,默認爲[]
"exclude": ["transform-es2015-for-of"],
//是否自動引入polyfill,開啓此選項必須保證已經安裝了babel-polyfill
//參數:Boolean,默認爲false.
"useBuiltIns": false
}]
]
}
複製代碼
關於最後一個參數useBuiltIns,有兩點必需要注意: