babel的初步瞭解

前段時間開始研究ast,而後慢慢的順便把babel都研究了,至於ast稍後的時間會寫一篇介紹性博客專門介紹ast,本博客先介紹一下babel的基本知識點。前端

  • 背景:

因爲如今前端出現了不少非es5的語法,如jsx,.vue,ts等等的格式和寫法,若是要在瀏覽器的設備上識別並執行,須要額外將這些非傳統格式的語法轉成傳統的es5格式,而babel插件,就是用來將非es5格式的語法轉成es5語法。vue

babel實際上是一個解釋器,它主要講進行中的代碼分爲三個階段執行:解釋,轉換,生成。其中babel插件或者其餘插件都是在轉換階段起做用。node

  • babel核心包:

babel既然是個解釋器,那麼就會擁有解釋,遍歷,以及生成的一系列工具和api:webpack

1)babylon:babel裏面用來將js代碼詞法分析,生成ast,他的結構有些像acron,它的返回的結構裏面包含着ast和tokens。es6

require("babylon").parse("code", {
  // parse in strict mode and allow module declarations
  sourceType: "module",

  plugins: [
    // enable jsx and flow syntax
    "jsx",
    "flow"
  ]
});

sourceType: module表示的是在嚴格模式下解析而且容許模塊定義(即能識別import和expor語法);script識別不了。web

2)babel-traverse:功能就像estraverse同樣,主要是給plugin提供遍歷ast節點的功能;api

var babylon = require('babylon');
var result = babylon.parse(code, { sourceType: "module",});
console.log('result:', result);

import traverse from "babel-traverse";

traverse(result, {
    enter(node) {
       console.log(node);
    }
});

3)babel-generator:將ast生成js代碼;瀏覽器

var babylon = require('babylon');
var result = babylon.parse(code, { sourceType: "module",});
console.log('result:', result);

import traverse from "babel-traverse";
import generate from 'babel-generator';

traverse(result, {
    enter(node) {
       console.log(node);
    }
});

var conde1 = generate(result);
console.log('generate:', conde1);
  • babel工具包:

要完成複雜的轉換工做,單靠核心包是不能完成的,因此必要還要依賴於其餘工具包輔助。babel

1)babel-types:包含着ast中的全部類型,能夠生成一個ast的節點,而後替換真是ast的節點,從而改變ast的內容(ast工具庫,相似於lodash,具備校驗,建立和轉換ast的方法)。ide

import * as t from "babel-types";

console.log(t.stringLiteral("my-module"));

語法:t.anyTypeAnnotation(內容) // 最終返回一個類型的對象

2)babel-template:能夠經過字符串的形式生成一個ast;

import template from "babel-template";
const buildRequire = template(`
  var IMPORT_NAME = require(SOURCE);
`);

const ast2 = buildRequire({
    IMPORT_NAME: t.identifier("myModule"),
    SOURCE: t.stringLiteral("my-module")
});

console.log('ast2', ast2);

3)babel-helps: 主要是用來協助babel轉換;

4)babel-core-frame: 主要是用來將錯誤信息打印出來;

5)babel-cli:babel的命令行工具,經過命令行對js代碼進行轉譯;

6)babel-register: 由於babel工具文件,插件裏面使用了不少require,而 該文件能夠將node中的require於babel中的require綁定,從而可使用require引入文件;

7)babel-plugin-xxx: 在轉換過程當中使用的插件;

8)babel-plugin-transform-xxx: 在transerform過程當中使用到的插件;

(.babelrc文件:該文件會在babel編譯過程當中,自動配置babel的參數,babel的運行環境--env,babel的設置---preset,babel的所須要用到的插件---plugins等)

9)babel-core:該核心包包含着babel的核心(babel-lon,babel-traverse,babel-generate),提供了更多更友善的api給開發者使用。

  • babel編譯原理:

編譯器就是講高級的語言或者語法,編譯成更進階機器識別的語言和語法;

babel其實更像一個轉譯器,由於它主要是將高級的js語法轉成低級的語法;

他們二者雖然有區別,但有不少類似之處(都是經歷三個過程:解析,處理,生成);

以es6轉成es5爲例:

ES6代碼輸入 ==》 babylon進行解析 ==》 獲得AST ==》 plugin用babel-traverse對AST樹進行遍歷轉譯 ==》 獲得新的AST樹 ==》 用babel-generator經過AST樹生成ES5代碼

  • babel-pollfill,babel-runtime,transfer-runtime的區別:

babel-pollfill是針對於應用和頁面範圍內,對新的對象和新的語法進行兼容,主要是經過一些輔助函數進行兼容新的語法,但若是針對外部的庫使用,就會產生污染全局環境的影響,通常對項目代碼使用;

babel-runtime是對於外部插件和庫的語法兼容,能將新的對象和語法,經過在運行時,把對應的可識別的語法和對象匹配出來並進行轉換,從而顯示在運行時進行語法降級兼容,且不會產生全局污染,通常對外部的插件使用;

transfer-babel是對babel-runtime進行封裝,新的語法,對象能經過該插件,換種形式引用runtime的東西;

(其實runtime,pollfill都是創建在core-js之上的)。

對於babel的插件,主要是由於生成的ast的底層中有一個accept方法,專門用來接收visitor(插件)訪問者對象,而後在visitor中定義各類節點類型的操做-visite,每一個visite均可以接受一個path參數(節點信息,節點和位置信息的對象,其包含不少有用的方法),在visit中處理path,從而實現轉換的做用。

const result = babel.transform(code, {
    plugins: [{
        visitor
    }]
})
console.log(result.code);

至於visitor後續會詳細介紹。

整個babel的結構圖,我大概花了一張圖表示出來:

clipboard.png

而babel和webpack的協同開發,我也大概花了一張圖表示他們之間的關係,但裏面的原理,我後續會再去研究,研究好再分享一下:

clipboard.png

以上是我對babel的初步理解,若是有不正確的地方,歡迎指出。

相關文章
相關標籤/搜索