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

資訊專欄INFORMATION COLUMN

babel各單元簡(jiǎn)介&如何寫一個(gè)babel插件

peixn / 2515人閱讀

摘要:是怎么工作的如何編譯應(yīng)用場(chǎng)景語(yǔ)法糖的代碼統(tǒng)一相關(guān)概念介紹依賴,提供的方法,只轉(zhuǎn)化語(yǔ)法,不轉(zhuǎn)換類,的基礎(chǔ)配置利用對(duì)進(jìn)行劫持,在中進(jìn)行原理見(jiàn)同時(shí)對(duì)后的進(jìn)行緩存,提高下次效率讀取緩存根據(jù)判斷是否需要重新中傳入配置入口函數(shù)提供

Babel babel是怎么工作的?

parse->AST->transform->gengerate

如何編譯js->AST

babel應(yīng)用場(chǎng)景

語(yǔ)法糖的polyfill

代碼統(tǒng)一hack

相關(guān)概念介紹 babel-polyfill

依賴core-js,提供es*->es3的方法,只轉(zhuǎn)化語(yǔ)法,不轉(zhuǎn)換API(類Promise,WeakMap)

babel-helper babel-register(0.7.0-beta)

babel的基礎(chǔ)配置init

利用pirate對(duì)require進(jìn)行劫持,在hook中進(jìn)行babel 原理見(jiàn)

同時(shí)對(duì)babel后的code進(jìn)行緩存,提高下次babel效率

function compile(code, filename) {
    ...

  let cacheKey = `${JSON.stringify(opts)}:${babel.version}`;

  const env = babel.getEnv(false);

  if (env) cacheKey += `:${env}`;

    //讀取緩存 根據(jù)mtime判斷是否需要重新babel
  if (cache) {
    const cached = cache[cacheKey];
    if (cached && cached.mtime === mtime(filename)) {
      return cached.code;
    }
  }

  const result = babel.transform(code, {
    ...opts,
    sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps,
    ast: false,
  });

  if (cache) {
    cache[cacheKey] = result;
    result.mtime = mtime(filename);
  }

  if (result.map) {
    if (Object.keys(maps).length === 0) {
      installSourceMapSupport();
    }
    maps[filename] = result.map;
  }

  return result.code;
}

//hook中傳入ext配置
function hookExtensions(exts) {
  if (piratesRevert) piratesRevert();
  piratesRevert = addHook(compile, { exts, ignoreNodeModules: false });
}

//入口函數(shù)
export default function register(opts?: Object = {}) {
  // Clone to avoid mutating the arguments object with the "delete"s below.
  opts = Object.assign({}, opts);
  if (opts.extensions) hookExtensions(opts.extensions);

  if (opts.cache === false && cache) {
    registerCache.clear();
    cache = null;
  } else if (opts.cache !== false && !cache) {
    registerCache.load();
    cache = registerCache.get();
  }
  
  ...
}
babel-core

提供基礎(chǔ)的transform方法

如何寫一個(gè)babel插件

babel-plugin其實(shí)是對(duì)code轉(zhuǎn)出的ast進(jìn)行操作,

準(zhǔn)備工具

ast轉(zhuǎn)換工具

ast轉(zhuǎn)換可視化工具

ast的解構(gòu)可以類比成一個(gè)樹狀或者json嵌套結(jié)構(gòu),他的每一層結(jié)構(gòu)都可以叫做一個(gè)節(jié)點(diǎn),如下圖

babel提供一個(gè)visitor的方法,允許我們?cè)诶锩嬷付ㄎ覀兿胍L問(wèn)的節(jié)點(diǎn),并且可以在命中該節(jié)點(diǎn)時(shí)做出自定義的的操作

實(shí)例分析

現(xiàn)在我們有一個(gè)需要移除整個(gè)業(yè)務(wù)bundle包里所有console.log的需求

1.那我們首先要知道console.log實(shí)際在ast是怎樣的一個(gè)節(jié)點(diǎn)結(jié)構(gòu)

形如

console.log("a")

實(shí)際ast的展現(xiàn)如下

對(duì)于各個(gè)節(jié)點(diǎn)具體含義,這里不做細(xì)講,可以參考文末的babel手冊(cè)

2.這里直接貼上代碼講吧

module.exports = function (babel) {

    const { types: t, template } = babel;

    const visitor = {
            //需要訪問(wèn)的節(jié)點(diǎn)名
            //訪問(wèn)器默認(rèn)會(huì)被注入兩個(gè)參數(shù) path(類比成dom),state
        ExpressionStatement(path, state) {
            const node = path.node;
            //延當(dāng)前節(jié)點(diǎn)向內(nèi)部訪問(wèn),判斷是否符合console解析出的ast的特征
            const expressionNode = keyPathVisitor(node, ["expression"]);
            const isCallExpression = expressionNode.type === "CallExpression";
            if (isCallExpression) {
                const objectName = keyPathVisitor(expressionNode, ["callee", "object", "name"]);
                const prototypeName = keyPathVisitor(expressionNode, ["callee", "property", "name"]);
                if (objectName === "console" && prototypeName === "log" && !MAC) {
                        //如果符合上述條件,直接移除該節(jié)點(diǎn)
                    path.remove();
                }
            }
        }
    };

    return {
        visitor
    };
};

3.進(jìn)階版:如果我們想在babel-plugin中新增代碼呢

差不多有三種方法

A:手動(dòng)添加節(jié)點(diǎn)(很惡心~相信你不會(huì)想去了解)
B:先生成ast,直接path.insertBefore
C:使用babel-template
例子: 移除autobind裝飾器,并在constructor中自動(dòng)bind this

注意點(diǎn)

1.因?yàn)閎abel判斷是否babel是根據(jù)modify time,所以babel插件寫完想實(shí)時(shí)生效,需要給當(dāng)前的env加上 BABEL_DISABLE_CACHE

//babel-register/cache.js

function load() {
  if (process.env.BABEL_DISABLE_CACHE) return;
    
  process.on("exit", save);
  process.nextTick(save);
    
  if (!_fs2.default.existsSync(FILENAME)) return;
    
  try {
    data = JSON.parse(_fs2.default.readFileSync(FILENAME));
  } catch (err) {
    return;
  }
}

2.babel插件寫完后發(fā)布npm時(shí),記得一定要加上babel-plugin-前綴,因?yàn)榕渲迷赽abelrc中的插件名都會(huì)被babel在加載時(shí)統(tǒng)一加上babel-plugin前綴,然后在模塊系統(tǒng)中去查找

題外話 如何實(shí)現(xiàn)給require加上hook

傳送門

參考文獻(xiàn)

Babel插件手冊(cè)

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

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

相關(guān)文章

  • Babel 插件原理的理解與深入

    摘要:抽象語(yǔ)法樹是怎么生成的談到這點(diǎn),就要說(shuō)到計(jì)算機(jī)是怎么讀懂我們的代碼的。需要注意什么狀態(tài)狀態(tài)是抽象語(yǔ)法樹轉(zhuǎn)換的敵人,狀態(tài)管理會(huì)不斷牽扯我們的精力,而且?guī)缀跛心銓?duì)狀態(tài)的假設(shè),總是會(huì)有一些未考慮到的語(yǔ)法最終證明你的假設(shè)是錯(cuò)誤的。 現(xiàn)在談到 babel 肯定大家都不會(huì)感覺(jué)到陌生,雖然日常開發(fā)中很少會(huì)直接接觸到它,但它已然成為了前端開發(fā)中不可或缺的工具,不僅可以讓開發(fā)者可以立即使用 ES 規(guī)范...

    draveness 評(píng)論0 收藏0
  • babel插件入門-AST

    摘要:是一個(gè)對(duì)象,它表示兩個(gè)節(jié)點(diǎn)之間的連接。接著返回一個(gè)對(duì)象,其屬性是這個(gè)插件的主要節(jié)點(diǎn)訪問(wèn)者。所以上面的執(zhí)行方式是運(yùn)行引入了自定義插件的打包文件現(xiàn)在為明顯減小,自定義插件成功插件文件目錄覺(jué)得好玩就關(guān)注一下歡迎大家收藏寫評(píng)論 目錄 Babel簡(jiǎn)介 Babel運(yùn)行原理 AST解析 AST轉(zhuǎn)換 寫一個(gè)Babel插件 Babel簡(jiǎn)介 Babel 是一個(gè) JavaScript 編譯器,它能將es...

    sanyang 評(píng)論0 收藏0
  • 2020年如何一個(gè)現(xiàn)代的JavaScript庫(kù)

    摘要:我寫過(guò)一些開源項(xiàng)目,在開源方面有一些經(jīng)驗(yàn),最近開到了阮老師的微博,深有感觸,現(xiàn)在一個(gè)開源項(xiàng)目涉及的東西確實(shí)挺多的,特別是對(duì)于新手來(lái)說(shuō)非常不友好最近我寫了一個(gè),旨在從多方面快速幫大家搭建一個(gè)標(biāo)準(zhǔn)的庫(kù),本文將已為例,介紹寫一個(gè)開源庫(kù)的知識(shí) 我寫過(guò)一些開源項(xiàng)目,在開源方面有一些經(jīng)驗(yàn),最近開到了阮老師的微博,深有感觸,現(xiàn)在一個(gè)開源項(xiàng)目涉及的東西確實(shí)挺多的,特別是對(duì)于新手來(lái)說(shuō)非常不友好 show...

    joyqi 評(píng)論0 收藏0
  • 基于 Gulp + Browserify 構(gòu)建 ES6 環(huán)境下的自動(dòng)化前端項(xiàng)目

    摘要:本文特此給大家介紹下如何使用配合來(lái)構(gòu)建基于的前端項(xiàng)目。最后,在目錄下會(huì)生成最終的項(xiàng)目文件。執(zhí)行單元測(cè)試本例中使用進(jìn)行單元測(cè)試。 隨著React、Angular2、Redux等前沿的前端框架越來(lái)越流行,使用webpack、gulp等工具構(gòu)建前端自動(dòng)化項(xiàng)目也隨之變得越來(lái)越重要。鑒于目前業(yè)界普遍更流行使用webpack來(lái)構(gòu)建es6(ECMAScript 2015)前端項(xiàng)目,網(wǎng)上的相關(guān)教程也比...

    yuanxin 評(píng)論0 收藏0
  • Next.js踩坑入門系列(二)— 添加Antd && CSS

    摘要:踩坑入門系列一二添加三目錄重構(gòu)再談路由陸續(xù)更新個(gè)人對(duì)于腳手架的有一種執(zhí)念,如果搭建出來(lái)就是一個(gè)首頁(yè)標(biāo)簽跳轉(zhuǎn),實(shí)在不是我這個(gè)處女座的風(fēng)格,因此第二步我就想引用框架,相信很多使用的開發(fā)者用的也都是這個(gè)框架吧。 Next.js踩坑入門系列 (一) Hello Next.js (二) 添加Antd && CSS (三) 目錄重構(gòu)&&再談路由 陸續(xù)更新... 個(gè)人對(duì)于腳手架的UI有一種執(zhí)...

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

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

0條評(píng)論

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