国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Babel.js插件開(kāi)發(fā)之二 - 開(kāi)始編寫(xiě)

focusj / 2130人閱讀

摘要:完整專題上一篇已經(jīng)介紹了編寫(xiě)插件所需要了解的基礎(chǔ)知識(shí),這篇我們就開(kāi)始編寫(xiě)插件了。如字面意思,他們分別代表了節(jié)點(diǎn)數(shù)據(jù)父節(jié)點(diǎn)群數(shù)據(jù)。看到這里你已經(jīng)可以動(dòng)手開(kāi)始嘗試寫(xiě)一個(gè)插件了。使用上述文件目錄結(jié)構(gòu)為在中編寫(xiě)程序。

  

完整專題:http://www.codefrom.com/p/Babel.js

上一篇已經(jīng)介紹了編寫(xiě)babel.js插件所需要了解的基礎(chǔ)知識(shí),這篇我們就開(kāi)始編寫(xiě)babel.js插件了。

第一篇傳送門(mén): Babel.js插件開(kāi)發(fā)之一 - Babel與AST

開(kāi)始

新建一個(gè)新的ES6項(xiàng)目,創(chuàng)建目錄結(jié)構(gòu)如下的項(xiàng)目:

YourProject/
    |- src/
    |   |- index.es6
    |- js/
    |
    |- app.js

進(jìn)入到 YourProject 并安裝babel開(kāi)發(fā)模塊 babel-core

$ cd path/to/YourProject/
$ npm install babel-core

之后目錄結(jié)構(gòu)如下:

YourProject/
    |- src/
    |- js/
    |- node_modules/
    |   |- babel-core/
    |       |- ...
    |- app.js

新建插件目錄

cd node_modules/
mkdir babel-plugin-test

并且新建目錄下的nodejs模塊文件,之后目錄結(jié)構(gòu)如下:

fileYourProject/
    |- src/
    |- js/
    |- node_modules/
    |   |- babel-core/
    |   |- babel-plugin-test/
    |       |- index.js
    |       |- package.json
    |- app.js

接下來(lái)我們就可以在 index.js 中編寫(xiě)插件了。

轉(zhuǎn)換
  

由于AST中節(jié)點(diǎn)類型眾多,我在這里就講如何通過(guò)如上文檔中的個(gè)別常用的類型進(jìn)行轉(zhuǎn)換,其他的都是類似的。

  

PS: 最近Babel.js更新了5.6+的API,支持用ES6編寫(xiě),也換了新的轉(zhuǎn)換器接口= = 可素他們自己官方的栗子都跑不起來(lái)= =,放棄,之后弄明白再換上新借口的版本,現(xiàn)在依然按照可用的例子進(jìn)行講解。

首先 創(chuàng)建一個(gè)入口: 在新創(chuàng)建的 index.js 中添加:

javascript"use strict";

module.exports = function(babel) {
    var t = babel.types; // AST模塊
    var imports = {}; 
    // 如果你有自己的模塊組織方式,用這里把模塊名和路徑記錄下來(lái)。

    var moduleRoot = ""; // 你其他的自定義變量

    // module_name寫(xiě)你的插件名稱,但并不在調(diào)用時(shí)使用
    return new babel.Transformer("module_name", {
        // 這里寫(xiě)你的轉(zhuǎn)換邏輯 [邏輯區(qū)域]
    });
};

在AST中,我們可以把整個(gè)程序看成一個(gè) Program 例如

var a = 42;
var b = 5;
var c = a + b;

其AST樹(shù)長(zhǎng)這樣:(圖 1)

program 是它的根節(jié)點(diǎn)。

于是我們可以在上面的邏輯區(qū)域添加以下代碼:

Program: function(node) {
},

除了 Program 常用的還有:

Class (對(duì)類的處理方法)

NewExpression (對(duì)new新建對(duì)象表達(dá)式的處理)

CallExpression (對(duì)調(diào)用函數(shù)表達(dá)式的處理)

MethodDefinition (對(duì)類成員方法的處理)

... (等等)

它們都有三個(gè)傳入?yún)?shù): nodeparentscope

  

注: 你可以通過(guò)調(diào)試查看他們的具體構(gòu)造。

如字面意思,他們分別代表了: 節(jié)點(diǎn)數(shù)據(jù)、 父節(jié)點(diǎn)、群數(shù)據(jù)。其中,節(jié)點(diǎn)數(shù)據(jù) node 是操作一條語(yǔ)句主要的參數(shù)~。

節(jié)點(diǎn)數(shù)據(jù)就是該節(jié)點(diǎn)的屬性以及內(nèi)容,其具體的數(shù)據(jù)格式可以看我在第一篇相關(guān)概念中最后提到的兩篇文檔:

  

ES5: https://github.com/estree/estree/blob/master/spec.md - 文檔 1
ES6: https://github.com/estree/estree/blob/master/es6.md - 文檔 2

例如,上面圖1中的那顆樹(shù)的 Program 的節(jié)點(diǎn)數(shù)據(jù),文檔 1中相關(guān)描述如下:

Program

interface Program <: Node {
    type: "Program";
    body: [ Statement ];
}

我們可以看到其 node 參數(shù)是一個(gè) Node 類型的數(shù)據(jù),包含了兩個(gè)屬性:公共屬性 type 代表節(jié)點(diǎn)類別,body 代表其內(nèi)容,這里是一個(gè)子節(jié)點(diǎn)的列表,列表中有三個(gè)VariableDeclaration 代表程序中的三條語(yǔ)句,其類型也是 Node

假設(shè)我們定義了一種模塊化的方法(類似AMD的requirejs),我們將整個(gè)程序包裹在一個(gè) test.defineModule(function(){/* block */}) 方法中。

那我們可以這樣構(gòu)建Program:

"use strict";

module.exports = function(babel) {
    var t = babel.types; // AST模塊
    return new babel.Transformer("module_name", {
        // 這里寫(xiě)你的轉(zhuǎn)換邏輯 [邏輯區(qū)域]
        Program: function(node) {
            var moduleFunction = t.functionExpression( // [1]
                t.identifier(""), // [2]
                [],  // [3]
                t.blockStatement(node.body) // [4]
            );
            var moduleDefine = t.callExpression( // [5]
                t.identifier("test.defineModule"),  // [6]
                [moduleFunction] // [7]
            );
            var moduleExpression = t.expressionStatement(moduleDefine); // [8]
            node.body = [moduleExpression]; // [9]
            return node; // [10]
        }
    });
};

這里你只定義了Program的轉(zhuǎn)換機(jī)制,因此其他的轉(zhuǎn)換還是會(huì)按照默認(rèn)的方式進(jìn)行轉(zhuǎn)換。

按照這種機(jī)制,上面的AST樹(shù)的示例程序就被轉(zhuǎn)換成下面這樣了:

"use strict";

test.defineModule(function () {
  var a = 42;
  var b = 5;
  var c = a + b;
});

下面我們來(lái)逐行分析一下(以邏輯的順序):

  

[5] 新建一個(gè)函數(shù)調(diào)用 moduleDefine
[6] 這個(gè)被調(diào)用函數(shù)的名字叫做 "test.defineModule" 即: test.defineModule()
[8] 整個(gè)函數(shù)調(diào)用是一個(gè)完整的表達(dá)式 moduleExpression ,即: test.defineModule();
接下來(lái)我們需要向這個(gè)函數(shù)調(diào)用中填入?yún)?shù)列表
[7] 這個(gè)參數(shù)列表中有一個(gè)參數(shù) moduleFunction
1 moduleFunction 是一個(gè)函數(shù)
[2] 這個(gè)函數(shù)的名稱是 "",即: 這是一個(gè)匿名函數(shù)
[3] 這個(gè)函數(shù)的參數(shù)列表為空
[4] 這個(gè)函數(shù)的內(nèi)容塊的內(nèi)容是原本Program節(jié)點(diǎn)的內(nèi)容
[9] 把原有的Program節(jié)點(diǎn)的內(nèi)容替換成新的
[10] 返回這個(gè)改動(dòng),當(dāng)然你是直接在原本的對(duì)象實(shí)例上改動(dòng)的,不返回也可以

同樣你也可以重新定義 ImportDeclarationExportDeclaration,其結(jié)構(gòu)略微與普通節(jié)點(diǎn)有所不同,例如:

ImportDeclaration: function(node) {
    node.specifiers.forEach(function(specifier){
        if(specifier.type == "ImportDefaultSpecifier"){
            imports[specifier.local.name] = node.source.value;
        }
    });
    this.dangerouslyRemove();
},

ExportDeclaration: function(){
    this.dangerouslyRemove();
}

其作用為:將export 和import的相關(guān)轉(zhuǎn)換都刪掉,并且將import的值和路徑都記錄下來(lái),可以在其他的轉(zhuǎn)換中用到,又或者直接在ImportDeclaration 中直接對(duì)import的變量進(jìn)行操作,例如:

對(duì)

import $ from "jquery"

我們希望轉(zhuǎn)化成

var $ = test.requireModule("jquery");

并將其放入模塊內(nèi):

ImportDeclaration: function(node) {
    var self = this;
    node.specifiers.forEach(function(specifier){
        if(specifier.type == "ImportDefaultSpecifier"){
            //imports[specifier.local.name] = node.source.value;
            var requireCall = t.callExpression(
                t.identifier("test.requireModule"), 
                [t.literal(node.source.value)]
            );
            var assignEx = t.assignmentExpression(
                "=", 
                t.identifier(specifier.local.name), 
                requireCall
            );
            self.insertAfter(t.expressionStatement(assignEx));
        }
    });
    this.dangerouslyRemove();
},

將其假如之前的test.defineModule的轉(zhuǎn)換中,則我們發(fā)現(xiàn)

import $ from "jquery"

var a = 42;
var b = 5;
var c = a + b;

被轉(zhuǎn)換為了:

"use strict";

test.defineModule(function () {
    $ = test.requireModule("jquery");

    var a = 42;
    var b = 5;
    var c = a + b;
});

ImportDeclaration 在上述文檔2中的描述為:

interface ImportDeclaration <: Node {
    type: "ImportDeclaration";
    specifiers: [ ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier ];
    source: Literal;
}

specifiers 列表中的 specifiers 可能有三種類型,在文檔中都有很詳細(xì)的描述,這里就不多說(shuō)了。

按照這樣的理解,所有的方法都可以通過(guò)查看上面的文檔 1和文檔 2的說(shuō)明進(jìn)行改動(dòng)。

看到這里你已經(jīng)可以動(dòng)手開(kāi)始嘗試寫(xiě)一個(gè)babel.js插件了。

使用

上述文件目錄結(jié)構(gòu)為:

YourProject/
    |- src/
    |- js/
    |- node_modules/
    |   |- babel-core/
    |   |- babel-plugin-test/
    |       |- index.js
    |       |- package.json
    |- app.js

src 中編寫(xiě)es6程序 test.es6

YourProject/
    |- src/
    |   |- test.es6
    |- js/
    |- node_modules/
    |   |- babel-core/
    |   |- babel-plugin-test/
    |       |- index.js
    |       |- package.json
    |- app.js

到Y(jié)ourProject目錄下。執(zhí)行

$ babel src/ -d js/ --plugins babel-plugin-test

則在 js 文件夾中就是你轉(zhuǎn)化好的js文件啦~。

  

還有第三篇是有關(guān)英文文檔的翻譯。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/85823.html

相關(guān)文章

  • 手把手教你從零搭建react局部熱加載環(huán)境

    摘要:有沒(méi)有辦法實(shí)現(xiàn)就局部刷新呢當(dāng)然是有第十步執(zhí)行為了實(shí)現(xiàn)局部熱加載,我們需要添加插件。 前言 用了3個(gè)多月的vue自認(rèn)為已經(jīng)是一名合格的vue框架api搬運(yùn)工,對(duì)于vue的api使用到達(dá)了一定瓶頸,無(wú)奈水平有限,每每深入底層觀賞源碼時(shí)候都迷失了自己。 遂決定再找個(gè)框架學(xué)習(xí)學(xué)習(xí)看看能否突破思維局限,加上本人早已對(duì)React、RN技術(shù)垂涎已久,于是決定找找教程來(lái)學(xué)習(xí)。無(wú)奈第一步就卡在了環(huán)境搭...

    quietin 評(píng)論0 收藏0
  • webpack實(shí)戰(zhàn)

    摘要:和類似的預(yù)處理器還有等。的用處非常多,包括給自動(dòng)加前綴使用下一代語(yǔ)法等,目前越來(lái)越多的人開(kāi)始用它,它很可能會(huì)成為預(yù)處理器的最終贏家。 webpack實(shí)戰(zhàn) 查看所有文檔頁(yè)面:全棧開(kāi)發(fā),獲取更多信息。快馬加鞭,加班加點(diǎn),終于把這個(gè)文檔整理出來(lái)了,順便深入地學(xué)習(xí)一番,鞏固知識(shí),就是太累人,影響睡眠時(shí)間和質(zhì)量。極客就是想要把事情做到極致,開(kāi)始了就必須到達(dá)終點(diǎn)。 原文鏈接:webpack實(shí)戰(zhàn),原...

    cyrils 評(píng)論0 收藏0
  • WebAssembly應(yīng)用到前端工程(下)—— webpack和webassembly

    摘要:然而在當(dāng)前以為主要編譯工具的實(shí)際工程應(yīng)用中依然存在問(wèn)題。涉及到的技術(shù)主要為模塊機(jī)制插件編寫(xiě)與插件編寫(xiě)。使用可以參考或,歡迎。上一篇應(yīng)用到前端工程上模塊的編寫(xiě) 在上一篇文章WebAssembly應(yīng)用到前端工程(上)—— webassembly模塊的編寫(xiě)中,完成了@ne_fe/gis模塊的編寫(xiě)與發(fā)布。然而webassembly在當(dāng)前以webpack4為主要編譯工具的實(shí)際工程應(yīng)用中依然存在問(wèn)...

    RichardXG 評(píng)論0 收藏0
  • 一天快速了解Babel

    摘要:在做項(xiàng)目中一直使用的是腳手架搭建的環(huán)境,一直沒(méi)有仔細(xì)的去了解這一工具,這周末抽出一天時(shí)間通過(guò)官網(wǎng)還有各種博客文章算是了解了一些內(nèi)容,起碼可以在項(xiàng)目中自己完成的配置了。不過(guò)好像目前瀏覽器端對(duì)這種諸如之類的方法支持的還不錯(cuò)了。 在做項(xiàng)目中一直使用的是腳手架搭建的環(huán)境,一直沒(méi)有仔細(xì)的去了解 babel 這一工具,這周末抽出一天時(shí)間通過(guò)官網(wǎng)還有各種博客文章算是了解了一些內(nèi)容,起碼可以在項(xiàng)目中自...

    qiangdada 評(píng)論0 收藏0
  • 「大概可能也許是」目前最好的 JavaScript 異步方案 async/await

    摘要:使用時(shí)也要注意范圍和層級(jí)。服務(wù)端配置服務(wù)端使用,最簡(jiǎn)單的方式是通過(guò)。云引擎是推出的服務(wù)器端運(yùn)行環(huán)境,支持和環(huán)境,功能強(qiáng)大而且目前免費(fèi),結(jié)合,使原本復(fù)雜的開(kāi)發(fā)工作變得簡(jiǎn)單高效。目前也支持和海外節(jié)點(diǎn),輕松滿足你的業(yè)務(wù)需求。 構(gòu)建一個(gè)應(yīng)用程序總是會(huì)面對(duì)異步調(diào)用,不論是在 Web 前端界面,還是 Node.js 服務(wù)端都是如此,JavaScript 里面處理異步調(diào)用一直是非常惡心的一件事情。以...

    Scorpion 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<