手写一个webpack插件(plugin)
熟悉 vue 和 react 的小伙伴们都知道,在执行过程中会有各种生命周期钩子,其实webpack也不例外,在使用webpack的时候,我们有时候需要在 webpack 构建流程中引入自定义的行为,这个时候就可以在 hooks 钩子中添加自己的方法。
创建插件
webpack 加载 webpack.config.js 中所有配置,此时 webpack 创建 compiler 对象,遍历所有 plugins 中插件,调用插件的 apply 方法,执行剩下编译流程(触发各个 hooks 事件),具体使用什么钩子和钩子是同步还是异步,请移步compiler 钩子
- 创建一个 JavaScript 命名函数或 JavaScript 类
- 在插件函数的 prototype 上定义一个 apply 方法
- 绑定到 webpack 自身的事件钩子上
- 导出这个JavaScript 命名函数或 JavaScript 类
- 在 webpack.config.js 文件中引入并调用方法
自定义 banner-webpack-plugin
自定义 banner-webpack-plugin 插件,该插件会在每一个打包后的 js 、css 文件第一行添加注释,先看效果图。

- emit 钩子是输出 asset 到 output 目录之前执行
- 获取即将输出的资源文件:compilation.assets
- 遍历 assets,只处理js和css资源,其他文件不处理
- 通过 content = entcompilation.assets[filename].source() 获取原来内容
- 拼接上注释 content = prefix + content
- 修改资源的 source 和 size
// plugins/banner-webpack-plugin.jsclass BannerWebpackPlugin {constructor(options = {}) {this.options = options;}apply(compiler) {// 在资源输出之前触发compiler.hooks.emit.tap("BannerWebpackPlugin", (compilation) => {const extensions = ["css", "js"];const prefix = `/** Author: ${this.options.author}* Build Time: ${new Date()}*/`;// 获取即将输出的资源文件:compilation.assetsfor (const filename in compilation.assets) {if (compilation.assets.hasOwnProperty(filename)) {// 将文件名进行切割const splitted = filename.split(".");// 获取文件扩展名const extension = splitted[splitted.length - 1];// 只处理js和css资源,其他文件不处理if (extensions.includes(extension)) {const asset = compilation.assets[filename];// 获取原来内容let content = asset.source();// 拼接上注释content = prefix + content;// 修改资源compilation.assets[filename] = {// 最终资源输出时,调用source方法,source方法的返回值就是资源的具体内容source: () => content,// 资源大小size: () => content.length,};}}}});}
}
module.exports = BannerWebpackPlugin;
调用 BannerWebpackPlugin
// config/webpack.config.js// 引入插件
const BannerWebpackPlugin = require('../plugins/banner-webpack-plugin');
module.exports = {plugins: [// 调用插件new BannerWebpackPlugin({author: "小小愿望",}),],
};
自定义 take-time-webpack-plugin
自定义 take-time-webpack-plugin 插件,该插件输出 “webpack 构建正在启动!”,打包完成后输出 webpack 构建已完成!总耗时 { time } ms,先看效果图。

// plugins/take-time-webpack-plugin.js// 一个命名的 Javascript 方法 或 JavaScript 类
class TakeTimeWebpackPlugin {time = 0;// 原型上需要定义 apply 的方法apply(compiler) {// 生命周期钩子函数,是由 compiler 暴露// 通过 compiler 获取 webpack 内部的钩子,获取 Webpack 打包过程中的各个阶段compiler.hooks.environment.tap("TakeTimeWebpackPlugin", (compilation) => {console.log("\x1B[36m", "webpack 构建正在启动!");this.time = new Date().getTime();});// 通过 compiler 获取 webpack 内部的钩子,获取 Webpack 打包过程中的各个阶段compiler.hooks.afterEmit.tapAsync("TakeTimeWebpackPlugin", (compilation, callback) => {const nowTime = new Date().getTime();this.time = nowTime - this.time;const str = `webpack 构建已完成!总耗时 ${this.time} ms`console.log("\x1B[32m", str);// 分为同步和异步的钩子,异步钩子在功能完成后,必须执行对应的回调callback();});}
}
module.exports = TakeTimeWebpackPlugin;
调用 TakeTimeWebpackPlugin
在 config/webpack.config.js 文件中引入并执行 TakeTimeWebpackPlugin
// config/webpack.config.js// 引入插件
const TakeTimeWebpackPlugin = require('../plugins/take-time-webpack-plugin');
module.exports = {plugins: [// 调用插件new TakeTimeWebpackPlugin(),],
};
相关文章:
手写一个webpack插件(plugin)
熟悉 vue 和 react 的小伙伴们都知道,在执行过程中会有各种生命周期钩子,其实webpack也不例外,在使用webpack的时候,我们有时候需要在 webpack 构建流程中引入自定义的行为,这个时候就可以在 hooks 钩子中添加自己的方…...
jvm常见面试题
0x01. 内存模型以及分区,需要详细到每个区放什么。 栈区: 栈分为java虚拟机栈和本地方法栈 重点是Java虚拟机栈,它是线程私有的,生命周期与线程相同。 每个方法执行都会创建一个栈帧,用于存放局部变量表࿰…...
TF-A 项目的长期支持介绍
引流关键词:Armv8-A, Armv9-A, Cortex-A, Cortex-A12, Cortex-A15, Cortex-A17, Cortex-A32, Cortex-A34, Cortex-A35, Cortex-A5, Cortex-A510, Cortex-A53, Cortex-A55, Cortex-A57, Cortex-A65, Cortex-A65AE, Cortex-A7, Cortex-A710, Cortex-A715, Cortex-A72, Cortex-A7…...
企业电子招标采购系统源码java 版本 Spring Cloud + Spring Boot
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...
7.Mysql 事务底层
一、事务的基础知识 mysql中的事务 分为 显式事务 和 隐式事务。 1.1 显式事务 显式事务就是我们手动开启事务,并且提交事务比如: -- 开启事务 begin; -- 执行查询语句 select *from where id = 1 for update ; -- 提交事务 commit;1.2 隐式事务 在 MySQL 中,隐式事务是…...
15.DIY可视化-拖拽设计1天搞定主流小程序-分类联动文章列表实时刷新
分类联动文章列表实时刷新 本教程均在第一节中项目启动下操作 分类联动文章列表实时刷新前言需求一:功能实现:点击首页分类,对应分类内容显示到当前页一、清空原分类界面:二. 设置选项卡三:设定展示内容字段:1.跨页面复制:文章分类组件到分类
CRect rect; this->GetClientRect(rect); pDC->Ellipse(rect); // DDALineView.cpp : implementation of the CDDALineView class // #include “stdafx.h” #include “DDALine.h” #include “DDALineDoc.h” #include “DDALineView.h” #ifdef _DEBUG #define new…...
Spark大数据处理学习笔记(3.2.1)掌握RDD算子
该文章主要为完成实训任务,详细实现过程及结果见【http://t.csdn.cn/FArNP】 文章目录 一、准备工作1.1 准备文件1. 准备本地系统文件2. 把文件上传到 1.2 启动Spark Shell1. 启动HDFS服务2. 启动Spark服务3. 启动Spark Shell 二、掌握转换算子2.1 映射算子 - map()…...
lammps初级:石墨烯、金属材料、纳米流体、热传导、多成分体系、金属、半导体材料的辐照、自建分子力场、MOFS、H2/CO2混合气体等模拟
1 LAMMPS的基础入门——初识LAMMPS是什么?能干什么?怎么用? 1.1 LAMMPS在win10和ubuntu系统的安装及使用 1.2 in文件结构格式 1.3 in文件基本语法:结合实例,讲解in文件常用命令 1.4 data文件格式 1.5 LAMMPS常见错误解…...
【MarkerDown】CSDN Markdown之时序图sequenceDiagram详解
CSDN Markdown之时序图sequenceDiagram详解 序列图 sequenceDiagram参与者与组参与者 participant拟人符号 actor别名 as组 box 消息(连线)激活/失活 activate/deactivate备注 Note循环 loop备选 Alt并行 par临界区 critical中断 break背景高亮 rect注释 %%转义字符的实体代码序…...
ReentrantLock实现原理-公平锁
在ReentrantLock实现原理(1)一节中,我们了解了ReentrantLock非公平锁的获取流程,在本节中我们来看下ReentrantLock公平锁的创建以及锁管理流程 创建ReentrantLock公平锁 创建公平锁代码如下: ReentrantLock reentrantLock new ReentrantL…...
掌握Scala数据结构(2)MAP、TUPLE、SET
一、映射 (Map) (一)不可变映射 1、创建不可变映射 创建不可变映射mp,用键->值的形式 创建不可变映射mp,用(键, 值)的形式 注意:Map是特质(Scala里的trait,相当于Java里的interface&#…...
flutter:文件系统目录、文件读写
参考 参考:老孟 文件存储和网络请求 数据存储 Dart的 IO 库包含了文件读写的相关类,它属于 Dart 语法标准的一部分,所以通过 Dart IO 库,无论是 Dart VM 下的脚本还是 Flutter,都是通过 Dart IO 库来操作文件的。但…...
计算机提示“找不到vcruntime140.dll,无法继续执行代码可”以这样子修复
首先,对于那些不熟悉的人来说,vcruntime140.dll是一个关键文件,用于在Windows操作系统上运行使用C语言编写的大型应用程序。如果你正在运行或安装这样的应用程序,但找不到vcruntime140.dll文件,那么你的应用程序可能无…...
深度学习pytorch实战五:基于ResNet34迁移学习的方法图像分类篇自建花数据集图像分类(5类)超详细代码
1.数据集简介 2.模型相关知识 3.split_data.py——训练集与测试集划分 4.model.py——定义ResNet34网络模型 5.train.py——加载数据集并训练,训练集计算损失值loss,测试集计算accuracy,保存训练好的网络参数 6.predict.py——利用训练好的网…...
Rust in Action笔记 第五章 深入理解数据
如果希望看到f32类型的数转换成整型数字u32类型,需要在unsafe包裹下调用std::mem::transmute(data),因为在安全的Rust语法中没有把整型数据按照bit转换成浮点数据的实现,如果想要看到浮点数的二进制输出(通过{:b})&…...
Cocos creator实现飞机大战空中大战《战击长空》小游戏资源及代码
Cocos creator实现飞机大战空中大战《战击长空》小游戏资源及代码 最近在学习Cocos Creator,作为新手,刚刚开始学习Cocos Creator,刚刚入门,这里记录一下飞机大战小游戏实现。 https://wxaurl.cn/VEgRy2eTMyi 一 安装CocosDashBo…...
2.4 逻辑代数的基本定理
学习目标: 如果我要学习逻辑代数的基本定理,我会采取以下步骤: 1. 学习基本概念:首先,我会花时间了解逻辑代数的基本概念,如逻辑运算符(合取、析取、否定等)、真值表、逻辑等价性等…...
适用于 Linux 的 Windows 子系统wsl文档
参考链接:https://learn.microsoft.com/zh-cn/windows/wsl/ 鸟哥的Linux私房菜:http://cn.linux.vbird.org/ http://cn.linux.vbird.org/linux_basic/linux_basic.php http://cn.linux.vbird.org/linux_server/ 目录 安装列出可用的 Linux 发行版列出已…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
