Webpack中Loader和Plugin的區別和編寫思路
導讀 | 由於webpack基於釋出訂閱模式,在執行的生命週期中會廣播出許多事件,外掛透過監聽這些事件,就可以在特定的階段執行自己的外掛任務 |
前面兩節我們有提到Loader與Plugin對應的概念,先來回顧下
loader 是檔案載入器,能夠載入資原始檔,並對這些檔案進行一些處理,諸如編譯、壓縮等,最終一起打包到指定的檔案中
plugin 賦予了 webpack 各種靈活的功能,例如打包最佳化、資源管理、環境變數注入等,目的是解決 loader 無法實現的其他事
從整個執行時機上來看,如下圖所示:
可以看到,兩者在執行時機上的區別:
loader 執行在打包檔案之前
plugins 在整個編譯週期都起作用
在Webpack 執行的生命週期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機透過Webpack提供的 API改變輸出結果
對於loader,實質是一個轉換器,將A檔案進行編譯形成B檔案,操作的是檔案,比如將A.scss或A.less轉變為B.css,單純的檔案轉換過程
在編寫 loader 前,我們首先需要了解 loader 的本質
其本質為函式,函式中的 this 作為上下文會被 webpack 填充,因此我們不能將 loader設為一個箭頭函式
函式接受一個引數,為 webpack 傳遞給 loader 的檔案源內容
函式中 this 是由 webpack 提供的物件,能夠獲取當前 loader 所需要的各種資訊
函式中有非同步操作或同步操作,非同步操作透過 this.callback返回,返回值要求為 string 或者 Buffer
程式碼如下所示:
// 匯出一個函式,source為webpack傳遞給loader的檔案源內容 module.exports = function(source) { const content = doSomeThing2JsString(source); // 如果 loader 配置了 options 物件,那麼this.query將指向 options const options = this.query; // 可以用作解析其他模組路徑的上下文 console.log('this.context'); /* * this.callback 引數: * error:Error | null,當 loader 出錯時向外丟擲一個 error * content:String | Buffer,經過 loader 編譯後需要匯出的內容 * sourceMap:為方便除錯生成的編譯後內容的 source map * ast:本次編譯生成的 AST 靜態語法樹,之後執行的 loader 可以直接使用這個 AST,進而省去重複生成 AST 的過程 */ this.callback(null, content); // 非同步 return content; // 同步 }
一般在編寫loader的過程中,保持功能單一,避免做多種功能
如less檔案轉換成 css檔案也不是一步到位,而是 less-loader、css-loader、style-loader幾個 loader的鏈式呼叫才能完成轉換
由於webpack基於釋出訂閱模式,在執行的生命週期中會廣播出許多事件,外掛透過監聽這些事件,就可以在特定的階段執行自己的外掛任務
在之前也瞭解過,webpack編譯會建立兩個核心物件:
compiler:包含了 webpack 環境的所有的配置資訊,包括 options,loader 和 plugin,和 webpack 整個生命週期相關的鉤子
compilation:作為 plugin 內建事件回撥函式的引數,包含了當前的模組資源、編譯生成資源、變化的檔案以及被跟蹤依賴的狀態資訊。當檢測到一個檔案變化,一次新的 Compilation 將被建立
如果自己要實現plugin,也需要遵循一定的規範:
外掛必須是一個函式或者是一個包含 apply 方法的物件,這樣才能訪問compiler例項
傳給每個外掛的 compiler 和 compilation 物件都是同一個引用,因此不建議修改
非同步的事件需要在外掛處理完任務時呼叫回撥函式通知 Webpack 進入下一個流程,不然會卡住
實現plugin的模板如下:
class MyPlugin { // Webpack 會呼叫 MyPlugin 例項的 apply 方法給外掛例項傳入 compiler 物件 apply (compiler) { // 找到合適的事件鉤子,實現自己的外掛功能 compiler.hooks.emit.tap('MyPlugin', compilation => { // compilation: 當前打包構建流程的上下文 console.log(compilation); // do something... }) } }
在 emit 事件發生時,代表原始檔的轉換和組裝已經完成,可以讀取到最終將輸出的資源、程式碼塊、模組及其依賴,並且可以修改輸出資源的內容
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2772868/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 說說Loader和Plugin的區別?編寫Loader,Plugin的思路?Plugin
- webpack loader和plugin編寫WebPlugin
- 深入淺出webpack -- loader和plugin原理及區別WebPlugin
- 面試題: Webpack 的 plugin 和 loader 有什麼區別面試題WebPlugin
- 回顧webpack在vue.config.js中寫loader和pluginWebVueJSPlugin
- webpack3-loader和plugin的概念理解WebPlugin
- Webpack原理-編寫PluginWebPlugin
- 初探webpack之編寫loaderWeb
- webpack輸出檔案分析以及編寫一個loaderWeb
- Webpack外掛是如何編寫的——prerender-spa-plugin原始碼解析WebPlugin原始碼
- 方法重置和重寫的區別
- 過載和重寫的區別
- JavaScript中for in 和for of的區別JavaScript
- Js中for in 和for of的區別JS
- mysql中!=和is not的區別MySql
- Python中is和==的區別Python
- JavaScript中==和===的區別JavaScript
- Linux中“>”和“>>”的區別Linux
- Python 中 is 和 == 的區別Python
- mysql中“ ‘ “和 “ ` “的區別MySql
- webpack loader的"套路"Web
- webpack loader的”套路”Web
- Webpack的pluginWebPlugin
- ==和is的區別 以及編碼和解碼
- PHP 中的 -> 和 :: 的區別PHP
- 淺談C#中重寫和隱藏的區別C#
- webpack和vite的區別,為什麼vite啟動速度比webpack快?WebVite
- ../和./和/的區別
- java 中equals和==的區別Java
- SQL中where和on的區別SQL
- deferred中done和then的區別
- webpack4升級extract-text-webpack-plugin和UglifyJsPlugin問題WebPluginJS
- Python3中_和__的用途和區別Python
- javascript中break和continue的區別和作用JavaScript
- 電位器和編碼器的區別
- webpack-loaderWeb
- webpack系列-loaderWeb
- JS中的!=、== 、!==、=== 的用法和區別JS