Webpack 自定義插件開發指南:構建流程詳解與實戰開發全攻略

一. webpack打包流程

開發 Webpack 插件的第一步,就是明確:我的插件要接入 Webpack 構建流程的哪個階段,解決什么問題。

  • 了解流程之前首先要了解插件的兩個核心概念:compilercompilation
1. compiler:全局構建控制器
你可以這樣理解它:
  • 是 Webpack 的“大腦”,負責整個構建流程
  • 只會在整個 Webpack 啟動時創建一次
  • 提供入口:如 compiler.hooks.compile、compiler.hooks.run 等

注冊插件

class MyPlugin {apply(compiler) {// 插件注冊時調用一次}
}

使用鉤子

compiler.hooks.beforeRun.tap('MyPlugin', () => { ... })
2. compilation:本次構建上下文
你可以這樣理解它:
  • 是每次構建過程中的“局部快照”
  • 管理模塊 (module)、代碼塊 (chunk)、資源 (asset)等
  • 在監聽模式或熱更新時,每次都會重新生成一個 compilation 實例

你要修改文件,生成資源,訪問chunk的時候,一定是在 compilation 階段完成的

compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {// compilation 是這一次構建的上下文compilation.hooks.buildModule.tap(...)compilation.hooks.processAssets.tap(...)
});
舉個例子
class FileListPlugin {apply(compiler) {// 第一次執行,僅執行一次,注冊插件鉤子compiler.hooks.thisCompilation.tap('FileListPlugin', (compilation) => {// 每次構建及熱更新都會觸發compilation.hooks.processAssets.tap({name: 'FileListPlugin',stage: compilation.constructor.PROCESS_ASSETS_STAGE_SUMMARIZE},() => {const files = Object.keys(compilation.assets).join('\n');compilation.emitAsset('filelist.md', new compiler.webpack.sources.RawSource(files));});});}
}
webpack打包流程
階段對應方法插件鉤子說明
1?? 初始化webpack() 創建 compilercompiler.hooks.environment讀取配置、初始化插件
2?? 編譯開始compiler.run()compiler.hooks.beforeRunruncompile啟動構建,調用編譯
3?? 創建 Compilationnew Compilation()thisCompilationcompilation代表一次構建,管理模塊、資源
4?? 構建模塊buildModule/handleModuleCreationcompilation.hooks.buildModule構建入口與遞歸依賴
5?? 完成模塊seal()sealoptimizeModules完成依賴分析與模塊關系確定
6?? 生成代碼塊createChunkGraph()optimizeChunks把模塊打成 chunk
7?? 生成資源emitAssets()processAssets將 chunk 渲染為文件(此時文件還在內存中)
8?? 輸出結果outputFileSystem.writeFileafterEmitdone寫入磁盤,構建完成

二. 插件的開發

1. 插件的基本結構
class MyPlugin {constructor(options) {this.options = options;}// 創建插件類并實現 apply(compiler) 方法apply(compiler) {// 注冊 compiler 生命周期鉤子compiler.hooks.thisCompilation.tap('MyPlugin', (compilation) => {// 注冊 compilation 生命周期鉤子compilation.hooks.processAssets.tap({name: 'MyPlugin',stage: compilation.constructor.PROCESS_ASSETS_STAGE_SUMMARIZE},(assets) => {const { RawSource } = compiler.webpack.sources;// 修改、添加資源const content = 'hello plugin';compilation.emitAsset('my-output.txt', new RawSource(content));});});}
}module.exports = MyPlugin;
  • stage 是一個數字,標識你要插入的邏輯在整個資源處理生命周期中的階段優先級
  • PROCESS_ASSETS_STAGE_SUMMARIZE的stage為7000,代表總結階段,可以做輸出文件列表、日志、清單等操作
  • 其他更多的stage可以翻閱webpack官網查看
2. 注冊鉤子的方法
tap: 同步鉤子
compiler.hooks.beforeRun.tap('MyPlugin', (compiler) => {console.log('Before run');
});
tapAsync:異步鉤子(使用回調)
compiler.hooks.beforeRun.tapAsync('MyPlugin', (compiler, callback) => {setTimeout(() => {console.log('Before run (async)');callback();}, 1000);
});
  • 用于需要手動處理異步任務的情況,必須調用 callback()
tapPromise:異步鉤子(使用 Promise)
compiler.hooks.beforeRun.tapPromise('MyPlugin', (compiler) => {return new Promise((resolve) => {setTimeout(() => {console.log('Before run (promise)');resolve();}, 1000);});
});
  • 推薦用于現代異步開發場景

三. 利用webpack插件實現上線后熱更新的功能

1. 構建完成后自動生成一個帶 hash 的版本號文件
class VersionFilePlugin {constructor(options = {}) {this.filename = options.filename || 'version.txt';}apply(compiler) {compiler.hooks.thisCompilation.tap('VersionFilePlugin', (compilation) => {const { RawSource } = compiler.webpack.sources;compilation.hooks.processAssets.tap({name: 'VersionFilePlugin',stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONS},() => {// 獲取當前構建 hashconst hash = compilation.fullHash;const content = `version: ${hash}`;// 添加 version.txt 文件compilation.emitAsset(this.filename, new RawSource(content));});});}
}module.exports = VersionFilePlugin;
注冊插件
const VersionFilePlugin = require('./plugins/VersionFilePlugin');module.exports = {// ...plugins: [new VersionFilePlugin({filename: 'version.txt'})]
};
2. 定時輪詢 version.txt,檢測 hash 是否變化
<script>
(function () {const VERSION_CHECK_INTERVAL = 1000 * 60 * 5; // 每 5 分鐘檢查一次const VERSION_URL = '/version.txt';let currentVersion = null;async function checkVersion() {try {const res = await fetch(VERSION_URL, { cache: 'no-store' });const text = await res.text();const latestVersion = text.trim().split('version: ')[1];if (currentVersion && latestVersion !== currentVersion) {console.warn('[version check] 新版本已發布,自動刷新頁面');location.reload(true); // 強制刷新頁面}currentVersion = latestVersion;} catch (err) {console.error('[version check] 檢查失敗:', err);}}// 初始加載checkVersion();// 定時檢查setInterval(checkVersion, VERSION_CHECK_INTERVAL);
})();
</script>

?? 需要將該文件一并部署到 Web 服務器根目錄

有好多全局構建的生命周期鉤子每次構建生成的模塊、資源、chunk 等上下文生命周期鉤子本文沒有展示,想了解更多的可以去看下webpack官方文檔

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86746.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86746.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86746.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

本地部署Dify+Ragflow及使用(一)

概念說明 RAGflow&#xff1a; 吃透知識&#xff1a;將企業文檔&#xff08;如技術白皮書&#xff09;解析為結構化知識片段。精準檢索&#xff1a;當用戶提問時&#xff0c;從知識庫中召回最相關內容。 模型供應商&#xff1a; 提供大腦&#xff1a;為 Dify 提供生成答案的模…

2025.06.24【R語言】|clusterProfiler安裝與常見報錯FAQ全解

文章目錄 一、clusterProfiler安裝方法1. Bioconductor官方推薦2. Conda安裝&#xff08;個人推薦 適合服務器/依賴復雜環境&#xff09;3. 檢查安裝 二、常見依賴包安裝三、常見報錯與解決方案1. 報錯&#xff1a;could not find function "bitr"2. 報錯&#xff1a…

【轉】PostgreSql的鏡像地址

docker.io/postgres 項目中國可用鏡像列表 | 高速可靠的 Docker 鏡像資源 docker.io/postgrest/postgrest:v12.2.8 linux/amd64 docker.io17.34MB2025-04-04 13:14 346 docker.io/postgrest/postgrest:v12.2.12 linux/amd64 docker.io17.38MB2025-05-27 22:02 79 docker.io…

爬蟲005----Selenium框架

在總結爬蟲 &#x1f577; 框架之前&#xff0c;先總結一下selenium框架&#xff0c;也可以說是selenium庫&#xff0c;在自動化測試中是老生常談了&#xff08;長時間??不用&#xff0c;已經忘記了&#xff0c;實際測試工作中做UI自動化的也很少了&#xff0c;上次搞UI自動化…

記一次 Kafka 磁盤被寫滿的排查經歷

開篇扯犢子 今天踏進辦公聽到不是同事的早安&#xff0c;而是“有一個好消息&#xff0c;一個壞消息&#xff0c;你想聽哪個&#xff1f;” 我一愣&#xff0c;心想“大早上&#xff0c;就要玩刺激的嗎&#xff1f;” 但是還是淡定的回復說“無所謂&#xff0c;哥什么場面沒見…

python多線程:各線程的輸出在控制臺中同一行原因分析

代碼例子 import threading import timedef error_worker():print("子線程開始")time.sleep(1)raise Exception("子線程出錯了&#xff01;")t threading.Thread(targeterror_worker) t.start()print("主線程繼續執行&#xff0c;不受子線程異常影響…

Promptify與ReActAgent

一、Promptify 定位&#xff1a;NLP 任務的「自動化流水線」 1. 解決什么問題&#xff1f; 傳統 LLM 應用開發痛點&#xff1a; 反復調試&#xff1a;需手工編寫/調整 prompt 格式&#xff08;如調整分隔符、示例數量&#xff09;兼容性差&#xff1a;不同模型需重寫適配代碼…

如何將視頻從 iPhone 發送到 Android 設備

如果您想將視頻從 iPhone 發送到 Android 設備&#xff0c;尤其是視頻尺寸較大時&#xff0c;您需要一種高效的傳輸方法。本文將為您提供 7 種實用方法&#xff0c;讓您輕松發送大型視頻文件或短視頻片段&#xff0c;并且不會損失視頻質量。 第 1 部分&#xff1a;如何通過 iRe…

Stable Diffusion入門-ControlNet 深入理解 第四課:風格遷移與重繪控制模型——讓AI也有“藝術天賦”!

大家好&#xff0c;歡迎回到 Stable Diffusion入門-ControlNet 深入理解 系列的第四課&#xff01; 如果你還沒有看過上一課&#xff0c;趕緊補課哦&#xff1a;Stable Diffusion入門-ControlNet 深入理解 第三課。 上一課我們講解了 ControlNet 結構類模型&#xff0c;今天我…

國產鴻蒙系統開放應用側載,能威脅到Windows地位嗎?

上個月華為正式發布了 HarmonyOS PC 操作系統&#xff0c;關于生態方面大家其實一直蠻擔心。 例如不兼容Windows應用、不支持應用側載等。 不過&#xff0c;在最近舉行的華為開發者大會 2025 電腦分論壇上&#xff0c;華為終端 BG 平板與 PC 產品線總裁&#xff08;朱懂東&am…

Linux登錄檢查腳本

登錄檢查腳本 提高兼容性&#xff08;適應不同Linux發行版&#xff09;增強可視化效果和可讀性增加關鍵資源警戒提示優化表格對齊和顏色使用添加系統安全狀態檢查 #!/bin/bash# 改進版系統登錄提示腳本 # 優化點&#xff1a;兼容性增強、資源警戒提示、表格美化、安全狀態檢查…

jenkinsfile調用groovy

先決條件 gitlab存放jenkinsfile以及groovy代碼,jenkins我個人使用的是2.486具體的部署方法自己搞定,一堆文檔. gitlab創建一個devops8項目組以及my-jenkins-demo2項目用于演示過程 創建群組 這里已經創建好相關群組. 進入群組創建新項目 創建一個空白項目 配置項目選項 說明…

Ubuntu20.04離線安裝Realtek b852無線網卡驅動

最近有個項目&#xff0c;需要在 Ubuntu20.04 LTS 下開發&#xff0c;首先是安裝 Linux&#xff0c;我們可以從下面的網址下載&#xff1a; https://releases.ubuntu.com/20.04/ 本以為一切順利&#xff0c;結果剛開始就給我整不會了。我的電腦是聯想設計師GeekPro7&#xff…

1 Studying《Computer Architecture A Quantitative Approach》5-7

目錄 5 Thread-Level Parallelism 5.1 Introduction 5.2 Centralized Shared-Memory Architectures 5.3 Performance of Symmetric Shared-Memory Multiprocessors 5.4 Distributed Shared-Memory and Directory-Based Coherence 5.5 Synchronization: The Basics 5.6 M…

融智興科技: RFID超高頻柔性抗金屬標簽解析

在當今科技飛速發展的時代&#xff0c; RFID技術憑借其獨特的優勢&#xff0c;在眾多領域得到了廣泛應用。然而&#xff0c;在金屬環境中&#xff0c;傳統RFID標簽往往面臨著諸多挑戰&#xff0c;如信號干擾、識別距離短等問題。融智興科技推出的RFID 超高頻柔性抗金屬標簽&…

PHP Error: 深入解析與解決策略

PHP Error: 深入解析與解決策略 引言 PHP作為世界上最流行的服務器端腳本語言之一,在全球范圍內被廣泛使用。然而,在PHP的開發過程中,錯誤處理是一個非常重要的環節。本文將深入探討PHP錯誤處理的相關知識,包括錯誤類型、錯誤配置、錯誤日志以及常見的錯誤解決策略。 PH…

零基礎langchain實戰二:大模型輸出格式化成json

零基礎langchain實戰一&#xff1a;模型、提示詞和解析器-CSDN博客 書接上文 大模型輸出格式化 在下面例子中&#xff1a;我們需要將大模型的輸出格式化成json。 import os from dotenv import load_dotenvload_dotenv() # 加載 .env 文件 api_key os.getenv("DEEPS…

高通手機跑AI系列之——人臉變化算法

環境準備 手機 測試手機型號&#xff1a;Redmi K60 Pro 處理器&#xff1a;第二代驍龍8移動--8gen2 運行內存&#xff1a;8.0GB &#xff0c;LPDDR5X-8400&#xff0c;67.0 GB/s 攝像頭&#xff1a;前置16MP后置50MP8MP2MP AI算力&#xff1a;NPU 48Tops INT8 &&…

TortoiseSVN 安裝教程

前言 TortoiseSVN 是一款流行的 免費開源 的 Subversion (SVN) 客戶端&#xff0c;專門為 Windows 操作系統 設計。它通過 Windows 資源管理器集成 提供直觀的圖形化界面&#xff0c;使用戶可以輕松管理版本控制的文件和目錄&#xff0c;無需使用命令行。 主要特點 資源管理器…

多張圖片生成PDF每張圖片生成pdf的一頁

需要的庫 <!-- 生成pdf--><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.10</version></dependency><!-- https://mvnrepository.com/artifact/commons-net/commons-n…