Babel手冊

介紹

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

  • 生成 將通過轉換的AST經過babel-generator再轉換成js代碼,過程就是深度優先遍歷整個AST,而後構建能夠表示轉換後代碼的字符串。

例如,Babel可以將新的ES2015箭頭函數語法:api

const square = n => n * n;
複製代碼

轉譯爲:瀏覽器

const square = function square(n) {
    return n * n;
}
複製代碼

babel各個模塊介紹

1.babel-core

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
            };
        }
    }
}
複製代碼

2.babel-cli

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全局安裝在你的機器上,可是按項目逐個安裝在本地會更好。 有兩個主要的緣由。

  • 1.在同一臺機器上的不一樣項目或許會依賴不一樣版本的Babel並容許你有選擇的更新。
  • 2.意味着對工做環境沒有隱式依賴,讓項目有很好的移植性並易於安裝

將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。

3.babel-node

babel-node是隨babel-cli一塊兒安裝的,只要安裝了babel-cli就會自帶babel-node。 在命令行輸入babel-node會啓動一個REPL(Read-Eval-Print-Loop),這是一個支持ES6的js執行環境。

4.babel-register

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; } */
複製代碼

5.babel-polyfill

babel-polyfill在代碼中的做用主要是用已經存在的語法和api實現一些瀏覽器尚未實現的api,對瀏覽器的一些缺陷作一些修補。例如Array新增了includes方法,我想使用,可是低版本的瀏覽器上沒有,引入babel-polyfill則幫咱們添加了這些方法。

項目使用

1. .babelrc

babel全部的操做基本都會來讀取這個配置文件,除了一些在回調函數中設置options參數的,若是沒有這個配置文件,會從package.json文件的babel屬性中讀取配置。

2.plugins

babel中的插件,經過配置不一樣的插件才能告訴babel,咱們的代碼中有哪些是須要轉譯的。

3.presets

預設就是一系列插件的集合,就好像修圖同樣,把上次修圖的一些參數保存爲一個預設,下次就能直接使用。

// 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,有兩點必需要注意:

  • 1.若是useBuiltIns爲true,項目中必須引入babel-polyfill。
  • 2.babel-polyfill只能被引入一次,若是屢次引入會形成全局做用域的衝突。
相關文章
相關標籤/搜索