webpack之loader與plugin
loader與plugin的區別
loader的作用是將程式碼進行轉換,比如less轉成css,一個loader就是一個函式,接收的引數是上一個loader的返回值,loader進行一系列處理後 返回新的程式碼
plugin的作用是在webpack的編譯流程中完成某些操作,比如當webpack編譯啟動時,控制檯輸出一句話表示webpack啟動了,plugin是一個帶有apply方法的物件,apply方法的引數是compiler,在apply中註冊compiler物件的鉤子函式,鉤子函式在官網中有相應的描述。
loader
基本配置
module.exports = { mode: "development", module: { rules: [ { test:/\.css$/, // 先執行 css-loader 再執行 style-loader use: ["style-loader","css-loader"], } ], }, };
loaders處理流程
判斷當前檔名是否滿足module.rules.test的規則
滿足規則,則根據loaders陣列從最後一個loader依次執行到最前的一個loader;不滿足規則,loaders陣列為空,沒有可執行的loader
最後返回loaders處理結果
loader的寫法
css-loader:
module.exports = function(sourceCode) { var code = `var style = document.createElement("style"); style.innerHTML = \`${sourceCode}\`; document.head.appendChild(style); module.exports = \`${sourceCode}\``; return code; }
plugin
loader的功能定位是轉換程式碼,而一些其他的操作難以使用loader完成,比如:
- 當webpack生成檔案時,順便多生成一個說明描述檔案
- 當webpack編譯啟動時,控制檯輸出一句話表示webpack啟動了
- 當xxxx時,xxxx
當我們需要把功能嵌入到webpack的編譯流程中的時候,要藉助於plugin
基本配置
module.exports = { plugins:[ new MyPlugin() ] }
plugin是一個帶有apply方法的物件
var plugin = { apply: function(compiler){ } }
也可以使用class的寫法
class MyPlugin{ apply(compiler){ } } var plugin = new MyPlugin();
apply
apply方法會在初始化階段,建立好Compiler物件後執行。
compiler物件是在初始化階段構建的,整個webpack打包期間只有一個compiler物件,後續完成打包工作的是compiler物件內部建立的compilation
apply方法在一次打包過程中只執行一次,該方法接收一個compiler物件
compiler物件提供了大量的鉤子函式(hooks,可以理解為事件),plugin的開發者可以註冊這些鉤子函式,參與webpack編譯和生成。
你可以在apply方法中使用下面的程式碼註冊鉤子函式:
class MyPlugin{ apply(compiler){ compiler.hooks.事件名稱.事件型別(name, function(compilation){ //事件處理函式 }) } }
事件名稱
即要監聽的事件名,即鉤子名,所有的鉤子:https://www.webpackjs.com/api/compiler-hooks
事件型別
這一部分使用的是 Tapable API,這個小型的庫是一個專門用於鉤子函式監聽的庫。
它提供了一些事件型別:
- tap:註冊一個同步的鉤子函式,函式執行完畢則表示事件處理結束
- tapAsync:註冊一個基於回撥的非同步的鉤子函式,函式通過呼叫一個回調錶示事件處理結束
- tapPromise:註冊一個基於Promise的非同步的鉤子函式,函式通過返回的Promise進入已決狀態表示事件處理結束
處理函式
處理函式有一個事件引數compilation