【webpack核心】- 13、插件plugin - 監聽編譯中的事件,把功能嵌入到webpack的編譯流程中

1、plugin 作用 – (監聽編譯中的事件,把功能嵌入到webpack的編譯流程中)

  • 加載器loader 和 插件plugin 都是擴展webpack的功能
  • loader的定位是轉換代碼,把一種格式的代碼 轉換成另一種格式的代碼,eg: css 或者圖片 沒辦法進行語法樹分析,要轉換成js代碼
  • 有一些其他的操作難以使用loader完成,比如如下需要把功能嵌入到webpack的編譯流程中,而這種事情的實現是依託於plugin的
  • plugin 作用 – 監聽編譯中的事件把功能嵌入到webpack的編譯流程中
  • 當webpack生成文件時,順便多生成一個說明描述文件
  • 當webpack編譯啓動時,控制檯輸出一句話表示webpack啓動了
  • 當xxxx時,xxxx

這種類似的功能需要把功能嵌入到webpack的編譯流程中,而這種事情的實現是依託於plugin的

在這裏插入圖片描述

  • 如上簡圖中:在編譯流程中的每一步,都會觸發很多事件,這些事件需要有人來處理的,plugin就是來處理這些被觸發的事件的;所以plugin 就是來監聽事件的
  • 上圖中的紅點,可以認爲是一部分事件的觸發點,plugin 會監聽這些事件點,當事件觸發後,去處理事件

2、plugin的寫法 – plugin 如何監聽事件的

plugin的本質是一個帶有apply方法的對象apply方法會在初始化階段創建好compiler對象後調用/運行,並向方法傳入一個compiler對象

npx webpack 命令運行的時候,apply方法只會運行一次

var plugin = {
    apply: function(compiler){
        
    }
}

通常,習慣上,我們會將該對象寫成構造函數的模式

module.exports = class MyPlugin{     //導出一個插件
    apply(compiler){  //compiler是一個對象
		console.log('插件運行了')  //在webpack運行時執行
    }
}

關於compiler

compiler對象是在編譯的時候 初始化階段構建,整個webpack打包期間只有一個compiler對象,後續完成打包工作的是compiler對象內部創建的compilation(具體的編譯過程 和 輸出 由compilation完成的)
在這裏插入圖片描述

問題:compiler 和 compilation 的區別?
答:

  • compiler是打包初始化階段產生的,
    compilation 是compiler 內部產生的,具體的編譯過程 和 輸出 由compilation完成的
  • webpack 啓動監聽,監控文件的變化, 如果文件發生變化,保存後就重新打包,重新打包的時候,不會從初始化開始(因爲初始化是分析配置文件,配置文件並沒有變化),而是從編譯階段開始,重新創建一個compilation, 所以compilation可能由多個,而compiler 只有一個
module.exports = {
		mode:"development",
		watch:true,   //webpack 啓動監聽,監控文件的變化
}

關於 apply 方法

module.exports = class MyPlugin{     //導出一個插件
    apply(compiler){  //compiler是一個對象
		console.log('插件運行了')  //在webpack運行時執行
    }
}
  • npx webpack 命令運行的時候,apply方法只會運行一次

  • 所以如上寫法:webpack打包的時候,apply方法裏的console.log('插件運行了')只會運行打印一次

  • apply方法會在初始化階段創建好compiler對象後調用/運行,並向方法傳入一個compiler對象

  • 那麼問題: 插件plugin 可以監聽各種事件,那apply方法只運行一次,是怎麼監聽的?-- 我們在apply 方法裏註冊事件,類似window.onload

  • compiler對象提供了大量的鉤子函數(hooks,可以理解爲事件),plugin的開發者可以註冊這些鉤子函數,參與webpack編譯和生成

你可以在apply方法中使用下面的代碼註冊鉤子函數:

module.exports = class MyPlugin{     //導出一個插件
    apply(compiler){  //compiler是一個對象,提供了大量的鉤子函數
		//在這裏註冊事件,類似window.onload  $(function(){})
		 compiler.hooks.事件名稱.事件類型(name, function(compilation){
            //事件處理函數
        })
    }
}
  • 事件名稱:
    編譯的過程中要監聽的事件名,即鉤子名,所有的鉤子:具體鉤子查看官網
  • 事件類型:
    這一部分使用的是 Tapable API,這個小型的庫是一個專門用於鉤子函數監聽的庫。

它提供了一些事件類型:
tap:註冊一個同步的鉤子函數,函數運行完畢則表示事件處理結束
tapAsync:註冊一個基於回調的異步的鉤子函數,函數通過調用一個回調錶示事件處理結束
tapPromise:註冊一個基於Promise的異步的鉤子函數,函數通過返回的Promise進入已決狀態表示事件處理結束


  • 處理函數:
    處理函數有一個事件參數compilation

3、plugin的配置

要將插件應用到webpack,需要在webpack.config.js中把插件對象配置到webpack的plugins數組中,如下:

var MyPlugin = require('./plugins/MyPlugin');   //1.引入插件

module.exports = {
    plugins:[
        new MyPlugin()    //2.實例化插件
    ]
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章