說說Loader和Plugin的區別?編寫Loader,Plugin的思路?

来源:https://www.cnblogs.com/smileZAZ/p/18209166
-Advertisement-
Play Games

一、區別 前面兩節我們有提到Loader與Plugin對應的概念,先來回顧下 loader 是文件載入器,能夠載入資源文件,並對這些文件進行一些處理,諸如編譯、壓縮等,最終一起打包到指定的文件中 plugin 賦予了 webpack 各種靈活的功能,例如打包優化、資源管理、環境變數註入等,目的是解決 ...


一、區別

前面兩節我們有提到LoaderPlugin對應的概念,先來回顧下

  • loader 是文件載入器,能夠載入資源文件,並對這些文件進行一些處理,諸如編譯、壓縮等,最終一起打包到指定的文件中
  • plugin 賦予了 webpack 各種靈活的功能,例如打包優化、資源管理、環境變數註入等,目的是解決 loader 無法實現的其他事

從整個運行時機上來看,如下圖所示:

 

可以看到,兩者在運行時機上的區別:

  • loader 運行在打包文件之前
  • plugins 在整個編譯周期都起作用

Webpack 運行的生命周期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過Webpack提供的 API改變輸出結果

對於loader,實質是一個轉換器,將A文件進行編譯形成B文件,操作的是文件,比如將A.scssA.less轉變為B.css,單純的文件轉換過程

二、編寫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; // 同步
}

一般在編寫loader的過程中,保持功能單一,避免做多種功能

less文件轉換成 css文件也不是一步到位,而是 less-loadercss-loaderstyle-loader幾個 loader的鏈式調用才能完成轉換

三、編寫plugin

由於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 事件發生時,代表源文件的轉換和組裝已經完成,可以讀取到最終將輸出的資源、代碼塊、模塊及其依賴,並且可以修改輸出資源的內容

參考文獻

  • https://webpack.docschina.org/api/loaders/
  • https://webpack.docschina.org/api/compiler-hooks/
  • https://segmentfault.com/a/1190000039877943
  • https://vue3js.cn/interview

如果對您有所幫助,歡迎您點個關註,我會定時更新技術文檔,大家一起討論學習,一起進步。

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • @目錄前言需求:拼接函數:截取函數:總結 前言 請各大網友尊重本人原創知識分享,謹記本人博客:南國以南i、 提示:以下是本篇文章正文內容,下麵案例可供參考 需求: 將資料庫中的某一個欄位的前6位替換成一個新的字元串,其它位置不變。 拼接函數: CONCAT(A,B):將A和B拼接起來。 截取函數: ...
  • 前言 應用上下文(Context)是應用程式的全局信息的介面。它是一個抽象類,提供了訪問應用程式環境的方法和資源的方法。應用上下文可以用於獲取應用程式的資源、啟動Activity、發送廣播等。每個應用程式都有一個應用上下文對象,它在整個應用程式的生命周期內都是唯一的。通過應用上下文,我們可以獲得 ...
  • 前言 組件容器是一種用於管理和組織組件的工具或環境。它可以提供一些基本的功能,如組件的註冊、創建、銷毀和查找。組件容器通常會維護一個組件的依賴關係,並負責將這些依賴註入到組件中。它還可以提供一些其他的功能,如生命周期管理、事件通知、配置管理等。通過使用組件容器,開發者可以更方便地管理和使用組件, ...
  • ADB Remote ATV Android TV 的遙控器,基於 ADB Shell 命令 ADB Remote ATV 是一個 Android TV 的遙控器,基於 ADB Shell 命令,泛用性更高。 下麵的 shell 命令,是軟體的基本原理,通過 shell 命令可模擬物理遙控器的基本按 ...
  • 版本控制在軟體開發中至關重要,而 Git 是廣泛使用的代碼管理工具。有時,我們可能需要在多個平臺 (如 GitHub、GitLab 和 Gitee) 上同步同一 Git 倉庫,以便備份、協作等。 本文將帶你玩轉此操作,其中關鍵是“配置 SSH” 和“遠程倉庫”。首先,我們來講述 SSH 的配置。 配 ...
  • 一、卡片數據交互 HarmonyOS卡片數據交互是指在基於鴻蒙操作系統的設備上,卡片界面之間進行數據的傳輸和交互。 HarmonyOS的卡片是一種輕量級的應用界面,可以在設備的屏幕上顯示信息和提供操作功能。卡片可以包含各種類型的內容,如文本、圖片、按鈕、輸入框等,並可以根據用戶的操作進行相應的響 ...
  • 用戶在頁面訪問時發送數據到後臺,頁面關閉時也發送數據到後臺。 第一次進入頁面時觸發頁面訪問 刷新當前頁面時觸發頁面訪問 新 tab 進入頁面時觸發頁面訪問 當前頁面點擊 nav 進入其他模塊時,觸發頁面關閉&頁面訪問 關閉頁面時觸發頁面關閉 ...
  • 本章內容: 行分隔符(U + 2028)和段分隔符(U + 2029)符號現在允許在字元串文字中,與 JSON 匹配 更加友好的 JSON.stringify 新增了 Array 的flat()方法和flatMap()方法 新增了 String 的trimStart()方法和trimEnd()方法 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...