文章目錄
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.實例化插件
]
}