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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…