成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入理解Webpack核心模塊Tapable鉤子[同步版]

cangck_X / 2881人閱讀

摘要:本文將根據(jù)以下章節(jié)分別梳理每個鉤子同步鉤子首先安裝是簡單的同步鉤子,它很類似于發(fā)布訂閱。至此,我們把的所有同步鉤子都解析完畢異步鉤子比同步鉤子麻煩些,我們會在下一章節(jié)開始解析異步的鉤子傳送門深入理解核心模塊鉤子異步版代碼

記錄下自己在前端路上爬坑的經(jīng)歷 加深印象,正文開始~

tapable是webpack的核心依賴庫 想要讀懂webpack源碼 就必須首先熟悉tapable
ok.下面是webapck中引入的tapable鉤子 由此可見 在webpack中tapable的重要性

const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
 } = require("tapable");

這些鉤子可分為同步的鉤子和異步的鉤子,Sync開頭的都是同步的鉤子,Async開頭的都是異步的鉤子。而異步的鉤子又可分為并行和串行,其實同步的鉤子也可以理解為串行的鉤子。

本文將根據(jù)以下章節(jié)分別梳理每個鉤子

同步鉤子

SyncHook

SyncBailHook

SyncWaterfallHook

SyncLoopHook

首先安裝tapable
npm i tapable -D

SyncHook

SyncHook是簡單的同步鉤子,它很類似于發(fā)布訂閱。首先訂閱事件,觸發(fā)時按照順序依次執(zhí)行,所以說同步的鉤子都是串行的。

const { SyncHook } = require("tapable");

class Hook{
    constructor(){
        /** 1 生成SyncHook實例 */
        this.hooks = new SyncHook(["name"]);
    }
    tap(){
        /** 2 注冊監(jiān)聽函數(shù) */
        this.hooks.tap("node",function(name){
            console.log("node",name);
        });
        this.hooks.tap("react",function(name){
            console.log("react",name);
        });
    }
    start(){
        /** 3出發(fā)監(jiān)聽函數(shù) */
        this.hooks.call("call end.");
    }
}

let h = new Hook();

h.tap();/** 類似訂閱 */ 
h.start();/** 類似發(fā)布 */

/* 打印順序:
    node call end.
    react call end.
*/

可以看到 它是按照順序依次打印的,其實說白了就是發(fā)布和訂閱。接下來我們就手動實現(xiàn)它。

class SyncHook{ // 定義一個SyncHook類
    constructor(args){ /* args -> ["name"]) */
        this.tasks = [];
    }
    /** tap接收兩個參數(shù) name和fn */
    tap(name,fn){
        /** 訂閱:將fn放入到this.tasks中 */
        this.tasks.push(fn);
    }
    start(...args){/** 接受參數(shù) */
        /** 發(fā)布:將this.taks中的fn依次執(zhí)行 */
        this.tasks.forEach((task)=>{
            task(...args);
        });
    }
}

let h = new SyncHook(["name"]);

/** 訂閱 */
h.tap("react",(name)=>{
    console.log("react",name);
});
h.tap("node",(name)=>{
    console.log("node",name);
});
/** 發(fā)布 */
h.start("end.");

/* 打印順序:
    react end.
    node end.
*/
SyncBailHook

SyncBailHook 從字面意思上理解為帶有保險的同步的鉤子,帶有保險意思是 根據(jù)每一步返回的值來決定要不要繼續(xù)往下走,如果return了一個非undefined的值 那就不會往下走,注意 如果什么都不return 也相當于return了一個undefined。

const { SyncBailHook } = require("tapable");

class Hook{
    constructor(){
        this.hooks = new SyncBailHook(["name"]);
    }
    tap(){
        this.hooks.tap("node",function(name){
            console.log("node",name);
            /** 此處return了一個非undefined
             *  代碼到這里就不會繼續(xù)執(zhí)行余下的鉤子
             */
            return 1;
        });
        this.hooks.tap("react",function(name){
            console.log("react",name);
        });
    }
    start(){
        this.hooks.call("call end.");
    }
}

let h = new Hook();

h.tap();
h.start();

/* 打印順序:
    node call end.
*/

手動實現(xiàn)

class SyncHook{
    constructor(args){ 
        this.tasks = [];
    }
    tap(name,fn){
        this.tasks.push(fn);
    }
    start(...args){
        let index = 0;
        let result;
        /** 利用do while先執(zhí)行一次的特性 */
        do{
            /** 拿到每一次函數(shù)的返回值 result */
            result = this.tasks[index++](...args);
            /** 如果返回值不為undefined或者執(zhí)行完畢所有task -> 中斷循環(huán) */
        }while(result === undefined && index < this.tasks.length);
    }
}

let h = new SyncHook(["name"]);

h.tap("react",(name)=>{
    console.log("react",name);
    return 1;
});
h.tap("node",(name)=>{
    console.log("node",name);
});

h.start("end.");

/* 打印順序:
   react end.
*/
SyncWaterfallHook

SyncWaterfallHook是同步的瀑布鉤子,瀑布怎么理解呢? 其實就是說它的每一步都依賴上一步的執(zhí)行結果,也就是上一步return的值就是下一步的參數(shù)。

const { SyncWaterfallHook } = require("tapable");

class Hook{
    constructor(){
        this.hooks = new SyncWaterfallHook(["name"]);
    }
    tap(){
        this.hooks.tap("node",function(name){
            console.log("node",name);
            /** 此處返回的值作為第二步的結果 */
            return "第一步返回的結果";
        });
        this.hooks.tap("react",function(data){
            /** 此處data就是上一步return的值 */
            console.log("react",data);
        });
    }
    start(){
        this.hooks.call("callend.");
    }
}

let h = new Hook();

h.tap();
h.start();

/* 打印順序:
    node callend.
    react 第一步返回的結果
*/

手動實現(xiàn):

class SyncWaterFallHook{
    constructor(args){
        this.tasks = [];
    }
    tap(name,fn){
        this.tasks.push(fn);
    }
    start(...args){
        /** 解構 拿到tasks中的第一個task -> first */
        let [first, ...others] = this.tasks;
        /** 利用reduce() 累計執(zhí)行 
         * 首先傳入第一個 first 并執(zhí)行
         * l是上一個task n是當前task
         * 這樣滿足了 下一個函數(shù)依賴上一個函數(shù)的執(zhí)行結果
        */
        others.reduce((l,n)=>{
            return n(l);
        },first(...args));
    }
}

let h = new SyncWaterFallHook(["name"]);

/** 訂閱 */
h.tap("react",(name)=>{
    console.log("react",name);
    return "我是第一步返回的值";
});
h.tap("node",(name)=>{
    console.log("node",name);
});
/** 發(fā)布 */
h.start("end.");

/* 打印順序:
    react end.
    node 我是第一步返回的值
*/
SyncLoopHook

SyncLoopHook是同步的循環(huán)鉤子。 循環(huán)鉤子很好理解,就是在滿足一定條件時 循環(huán)執(zhí)行某個函數(shù):

const { SyncLoopHook } = require("tapable");

class Hook{
    constructor(){
        /** 定義一個index */
        this.index = 0;
        this.hooks = new SyncLoopHook(["name"]);
    }
    tap(){
        /** 箭頭函數(shù) 綁定this */
        this.hooks.tap("node",(name) => {
            console.log("node",name);
            /** 當不滿足條件時 會循環(huán)執(zhí)行該函數(shù) 
             * 返回值為udefined時 終止該循環(huán)執(zhí)行
            */
            return ++this.index === 5?undefined:"學完5遍node后再學react";
        });
        this.hooks.tap("react",(data) => {
            console.log("react",data);
        });
    }
    start(){
        this.hooks.call("callend.");
    }
}

let h = new Hook();

h.tap();
h.start();

/* 打印順序:
    node callend.
    node callend.
    node callend.
    node callend.
    node callend.
    react callend.
*/

可以看到 執(zhí)行了5遍node callend后再繼續(xù)往下執(zhí)行。也就是當返回undefined時 才會繼續(xù)往下執(zhí)行:

class SyncWaterFallHook{
    constructor(args){
        this.tasks = [];
    }
    tap(name,fn){
        this.tasks.push(fn);
    }
    start(...args){
        let result;
        this.tasks.forEach((task)=>{
            /** 注意 此處do{}while()循環(huán)的是每個多帶帶的task */
            do{
                /** 拿到每個task執(zhí)行后返回的結果 */
                result = task(...args);
                /** 返回結果不是udefined時 會繼續(xù)循環(huán)執(zhí)行該task */
            }while(result !== undefined);
        });
    }
}

let h = new SyncWaterFallHook(["name"]);
let total = 0;
/** 訂閱 */
h.tap("react",(name)=>{
    console.log("react",name);
    return ++total === 3?undefined:"繼續(xù)執(zhí)行";
});
h.tap("node",(name)=>{
    console.log("node",name);
});
/** 發(fā)布 */
h.start("end.");

/* 打印順序:
    react end.
    react end.
    react end.
    node end.
*/

可以看到, 執(zhí)行了3次react end.后 才繼續(xù)執(zhí)行了下一個task -> node end。至此,我們把tapable的所有同步鉤子都解析完畢. 異步鉤子比同步鉤子麻煩些,我們會在下一章節(jié)開始解析異步的鉤子.

傳送門:深入理解Webpack核心模塊Tapable鉤子(異步版)

代碼:mock-webpack-tapable

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

轉載請注明本文地址:http://systransis.cn/yun/102136.html

相關文章

  • 深入理解Webpack核心模塊Tapable鉤子[異步]

    摘要:接上一篇文章深入理解核心模塊鉤子同步版中三個注冊方法同步注冊的是中對三個觸發(fā)方法這一章節(jié)我們將分別實現(xiàn)異步的版本和版本異步鉤子的版本的版本的版本異步的鉤子分為并行和串行的鉤子,并行是指等待所有并發(fā)的異步事件執(zhí)行之后再執(zhí)行最終的異步回調。 接上一篇文章 深入理解Webpack核心模塊WTApable鉤子(同步版) tapable中三個注冊方法 1 tap(同步) 2 tapAsync(...

    AlphaWallet 評論0 收藏0
  • 手寫一個webpack插件

    摘要:引入定義一個自己的插件。一個最基礎的的代碼是這樣的在構造函數(shù)中獲取用戶給該插件傳入的配置會調用實例的方法給插件實例傳入對象導出在使用這個時,相關配置代碼如下和在開發(fā)時最常用的兩個對象就是和,它們是和之間的橋梁。 本文示例源代碼請戳github博客,建議大家動手敲敲代碼。 webpack本質上是一種事件流的機制,它的工作流程就是將各個插件串聯(lián)起來,而實現(xiàn)這一切的核心就是Tapable,w...

    cnio 評論0 收藏0
  • webpack系列-插件機制雜記

    摘要:系列文章系列第一篇基礎雜記系列第二篇插件機制雜記系列第三篇流程雜記前言本身并不難,他所完成的各種復雜炫酷的功能都依賴于他的插件機制。的插件機制依賴于一個核心的庫,。是什么是一個類似于的的庫主要是控制鉤子函數(shù)的發(fā)布與訂閱。 系列文章 Webpack系列-第一篇基礎雜記 Webpack系列-第二篇插件機制雜記 Webpack系列-第三篇流程雜記 前言 webpack本身并不難,他所完成...

    Neilyo 評論0 收藏0
  • 淺嘗webpack

    摘要:用于對模塊的源代碼進行轉換。將基礎模塊打包進動態(tài)鏈接庫,當依賴的模塊存在于動態(tài)鏈接庫中時,無需再次打包,而是直接從動態(tài)鏈接庫中獲取。負責打包出動態(tài)鏈接庫,負責從主要配置文件中引入插件打包好的動態(tài)鏈接庫文件。告一段落,淺嘗輒止。 吐槽一下 webpack 自出現(xiàn)時,一直備受青睞。作為強大的打包工具,它只是出現(xiàn)在項目初始或優(yōu)化的階段。如果沒有參與項目的構建,接觸的機會幾乎為零。即使是參與了...

    villainhr 評論0 收藏0
  • webpack詳解

    摘要:但也是最復雜的一個。中當一旦某個返回值結果不為便結束執(zhí)行列表中的插件中上一個插件執(zhí)行結果當作下一個插件的入?yún)⒄{用并行執(zhí)行插件流程篇本文關于的流程講解是基于的。 webpack是現(xiàn)代前端開發(fā)中最火的模塊打包工具,只需要通過簡單的配置,便可以完成模塊的加載和打包。那它是怎么做到通過對一些插件的配置,便可以輕松實現(xiàn)對代碼的構建呢? webpack的配置 const path = requir...

    lcodecorex 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<