webpack(四)——webpack里面的plugin和loader的區別


 

一 、區別:

 前面我們介紹了webpack里面的 loader  plugin ,這里來回顧一下:

  *  loader是文件加載器,能夠加載資源文件,並對文件進行一些處理,如編譯壓縮 等,最終一起打包到指定的文件中。

  * plugin賦予了webpack各種靈活的功能,如打包優化資源管理環境變量注入等,目的是為了解決loader無法實現的功能

 從整體的運行機制上來看,如下圖所示:

 

  從上圖可以看出:

  *  loader運行在項目打包之前;

  * plugins運行在整個項目的編譯時期;

 

 在Webpack運行的整個生命周期中會廣播出許多事件,Plugin會監聽這些事件,在合適的事件通過 webpack 提供的 api 改變輸出結果。

對於 loader 而言,它實質上是一個轉換器,將A文件編譯成B文件,操作的是 文件比如將A文件編譯成B文件,單純的是一個文件轉換過程。

 

二、編寫loader

  在編寫 loader 之前,我們需要先理解 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; // 同步
}
View Code

  注意:

  一般在做 loader  的功能裝換的時候,保持功能單一,避免做多種功能。

 

三、編寫plugin

  由於 webpack 基於發布訂閱模式,在運行的生命周期中會廣播出許多事件,插件會通過監聽這些事件,就可以在特定的階段執行自己的插件任務。

 

  webpack 編譯會創建兩個核心對象:

  * compiler :包含了 webpack 環境所有的 配置信息,包括了 optionsloaderplugin和 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 事件發生的時候,代表源文件的轉換和組裝已經完成,可以讀取到最終將輸出的 資源,代碼塊,模塊,依賴,並且可以修改輸出資源的內容

 

 

 

轉自:https://mp.weixin.qq.com/s/U5J6nCANyKx3olFTzRVr6g


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM