webpack plugin

1、基本写法及使用

这里用到 emit 钩子 及make 钩子,前者是串行后者是并行

/***  1.webpack加载webpack.config.js中所有配置,此时就会new TestPlugin(),执行插件的constructor2.webpack创建compiler对象3.遍历所有plugins中插件,调用插件的apply方法4.执行剩下编译流程《触发各个hooks事件)*/class TestPlugin {constructor() {console.log('testPlugin-constructor');}apply(compiler) {console.log('testPlugin-apply');// 由文档可知,environment是同步钩子,所以需要使用tap注册compiler.hooks.environment.tap("TestPlugin",() => (console.log("TestPlugin environment")))// 由文档可知,emit是异步串行钩子 AsyncSeriesHook// 串行则顺讯执行compiler.hooks.emit.tap("TestPlugin", (compilation) => {console.log("TestPlugin emit 111");})compiler.hooks.emit.tapAsync("TestPlugin", (compilation, callback) =>{setTimeout(() => {console.log("Testplugin emit 222");callback();}, 2000)})compiler.hooks.emit.tapPromise("TestPlugin", (compilation) => {return new Promise((resolve) => {setTimeout(() => {console.log("TestPlugin emit 333"); resolve();},1000);})})// 由文档可知,make是异步并行钩子 AsyncParallelHookcompiler.hooks.make.tapAsync("TestPlugin", (compilation, callback) => {compilation.hooks.seal.tap("TetsPlugin", ()=>{console.log("TestPlugin seal");})setTimeout(() => {console.log("Testplugin make 111");callback();}, 3000);})compiler.hooks.make.tapAsync("TestPlugin", (compilation, callback) => {setTimeout(() => {console.log("Testplugin make 222");callback();}, 1000);})compiler.hooks.make.tapAsync("TestPlugin", (compilation, callback) => {setTimeout(() => {console.log("Testplugin make 333");callback();}, 2000);})}
}
module.exports = TestPlugin

webpack.config.js中的配置

// 引入插件
const  TestPlugin  = require('./plugins/test-plugin')// 使用插件
new TestPlugin()

打印结果

2、BannerPlugin

class BannerWebpackPlugin {constructor(options = {}) {this.options = options;}apply(compiler) {// 在资源输出之前触发compiler.hooks.emit.tap("BannerWebpackPlugin", (compilation) => {// debugger;const extensions = ["css", "js"];// 1. 获取即将输出的资源文件:compilation.assets// 2. 过滤只保留js和css资源const assets = Object.keys(compilation.assets).filter((assetPath) => {// 将文件名切割 ['xxxx', 'js'] ['xxxx', 'css']const splitted = assetPath.split(".");// 获取最后一个文件扩展名const extension = splitted[splitted.length - 1];// 判断是否保护return extensions.includes(extension);});const prefix = `/*
* Author: ${this.options.author}
*/
`;// 3. 遍历剩下资源添加上注释// console.log(assets);assets.forEach((asset) => {// 获取原来内容const source = compilation.assets[asset].source();// 拼接上注释const content = prefix + source;// 修改资源compilation.assets[asset] = {// 最终资源输出时,调用source方法,source方法的返回值就是资源的具体内容source() {return content;},// 资源大小size() {return content.length;},};});});}
}module.exports = BannerWebpackPlugin;

3、CleanWebpackPlugin

class CleanWebpackPlugin {apply(compiler) {// 2. 获取打包输出的目录const outputPath = compiler.options.output.path;const fs = compiler.outputFileSystem;// 1. 注册钩子:在打包输出之前 emitcompiler.hooks.emit.tap("CleanWebpackPlugin", (compilation) => {// 3. 通过fs删除打包输出的目录下的所有文件this.removeFiles(fs, outputPath);});}removeFiles(fs, filepath) {// 想要删除打包输出目录下所有资源,需要先将目录下的资源删除,才能删除这个目录// 1. 读取当前目录下所有资源const files = fs.readdirSync(filepath);// console.log(files); // [ 'images', 'index.html', 'js' ]// 2. 遍历一个个删除files.forEach((file) => {// 2.1 遍历所有文件,判断是文件夹还是文件const path = `${filepath}/${file}`;const fileStat = fs.statSync(path);// console.log(fileStat);if (fileStat.isDirectory()) {// 2.2 是文件夹,就得删除下面所有文件,才能删除文件夹this.removeFiles(fs, path);} else {// 2.3 是文件,直接删除fs.unlinkSync(path);}});}
}module.exports = CleanWebpackPlugin;

4、AnalyzeWebpackPlugin

class AnalyzeWebpackPlugin {apply(compiler) {compiler.hooks.emit.tap("AnalyzeWebpackPlugin", (compilation) => {// 1. 遍历所有即将输出文件,得到其大小/*将对象变成一个二维数组:对象:{key1: value1,key2: value2 }二维数组:[[key1, value1],[key2, value2]]*/const assets = Object.entries(compilation.assets);/*md中表格语法:| 资源名称 | 资源大小 || --- | --- || xxx.js | 10kb |*/let content = `| 资源名称 | 资源大小 |
| --- | --- |`;assets.forEach(([filename, file]) => {content += `\n| ${filename} | ${Math.ceil(file.size() / 1024)}kb |`;});// 2. 生成一个md文件compilation.assets["analyze.md"] = {source() {return content;},size() {return content.length;},};});}
}module.exports = AnalyzeWebpackPlugin;

生成md文件

5、InlineChunkWebpackPlugin

 让 小的js 文件直接内联到 html中

const HtmlWebpackPlugin = require("safe-require")("html-webpack-plugin");class InlineChunkWebpackPlugin {constructor(tests) {this.tests = tests;}apply(compiler) {compiler.hooks.compilation.tap("InlineChunkWebpackPlugin", (compilation) => {// 1. 获取html-webpack-plugin的hooksconst hooks = HtmlWebpackPlugin.getHooks(compilation);// 2. 注册 html-webpack-plugin的hooks -> alterAssetTagGroupshooks.alterAssetTagGroups.tap("InlineChunkWebpackPlugin", (assets) => {// 3. 从里面将script的runtime文件,变成inline scriptassets.headTags = this.getInlineChunk(assets.headTags, compilation.assets);assets.bodyTags = this.getInlineChunk(assets.bodyTags, compilation.assets);});// 删除runtime文件hooks.afterEmit.tap("InlineChunkWebpackPlugin", () => {// 3. 从里面将script的runtime文件,变成inline scriptObject.keys(compilation.assets).forEach((filepath) => {if (this.tests.some((test) => test.test(filepath))) {delete compilation.assets[filepath];}});});});}getInlineChunk(tags, assets) {/*目前:[{tagName: 'script',voidTag: false,meta: { plugin: 'html-webpack-plugin' },attributes: { defer: true, type: undefined, src: 'js/runtime~main.js.js' }},]修改为:[{tagName: 'script',innerHTML: runtime文件的内容closeTag: true },]*/return tags.map((tag) => {if (tag.tagName !== "script") return tag;// 获取文件资源路径const filepath = tag.attributes.src;if (!filepath) return tag;if (!this.tests.some((test) => test.test(filepath))) return tag;return {tagName: "script",innerHTML: assets[filepath].source(),closeTag: true,};});}
}module.exports = InlineChunkWebpackPlugin;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/215563.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国信息通信研究院发布《全球数字治理白皮书》调”转变

加gzh“大数据食铁兽”,回复“20231123”,获取材料完整版 导读 中国信息通信研究院连续第三年发布《全球数字治理白皮书》本年度报告在延续以往对全球数字治理核心议题和重要机制进展评估展望的基础上,首次尝试提出全球数字治理的定义和体…

“继续教育”招生报名网存在支付漏洞

1.找到该网站的一个登录页面,注册好账户密码登录进去 2,进去之后,找到一个网上缴费功能 3.选择338元的套餐,支付方式我选的支付宝用burp抓包 发现money0参数与金额有关,于是就尝试把monet0改成一看看能不能搞一个零元购…

IO多路转接之epoll

目录 一. epoll的实现原理 二. epoll的相关接口 2.1 epoll_create -- 创建epoll模型 2.2 epoll_ctl -- 对epoll模型进行控制 2.3 epoll_wait -- 等待epoll所关注的事件就绪 2.4 epoll相关接口的使用方法 三. Epoll服务器的模拟实现 3.1 EpollServer类的声明 3.2 Epoll…

系统安全测试要怎么做?

进行系统安全测试时,可以按照以下详细的步骤进行: 1、信息收集和分析: 收集系统的相关信息,包括架构、部署环境、使用的框架和技术等。 分析系统的安全需求、威胁模型和安全策略等文档。 2、威胁建模和风险评估: …

SpringBoot3核心原理

SpringBoot3核心原理 事件和监听器 生命周期监听 场景:监听应用的生命周期 可以通过下面步骤自定义SpringApplicationRunListener来监听事件。 ①、编写SpringApplicationRunListener实现类 ②、在META-INF/spring.factories中配置org.springframework.boot.Sprin…

【Apache Doris】一键实现万表MySQL整库同步 | 快速体验

【Apache Doris】一键实现万表MySQL整库同步 | 快速体验) 一、 环境信息1.1 硬件信息1.2 软件信息 二、 流程介绍三、 前提概要3.1 安装部署3.2 JAR包准备3.2.1 数据源3.2.2 目标源 3.3 脚本模版 四、快速体验五、常见问题5.1 Mysql通信异常5.2 MySQL无Key同步异常5…

7.5 Windows驱动开发:监控Register注册表回调

在笔者前一篇文章《内核枚举Registry注册表回调》中实现了对注册表的枚举,本章将实现对注册表的监控,不同于32位系统在64位系统中,微软为我们提供了两个针对注册表的专用内核监控函数,通过这两个函数可以在不劫持内核API的前提下实…

爱心发射代码带名字升级版

上次的爱心发射发出来之后,群友想问能不能把心爱的人名字放在爱心中间。 当然没问题啊,于是我就改了改代码,让女神王铁蛋显示在爱心中间,同时还可以在屏幕上飘动满屏的王铁蛋,大大小小、快快慢慢的王铁蛋。 这还拿不下…

五种多目标优化算法(MOJS、NSGA3、MOGWO、NSWOA、MOPSO)求解微电网多目标优化调度(MATLAB代码)

一、多目标优化算法简介 (1)多目标水母搜索算法MOJS 多目标优化算法:多目标水母搜索算法MOJS(提供MATLAB代码)_水母算法-CSDN博客 (2)NSGA3 NSGA-III求解微电网多目标优化调度(M…

简答的体系架构分析

背景 一点体系架构的分析 体系架构图

基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码

基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于白鲸优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神经网络的光滑…

【C++医学影像PACS源码】CT检查中的三维重建技术

一、【PACS影像科普】CT检查中的三维重建是什么检查? 三维重建是多层螺旋CT的一个最大的优点,也是影像工作多年来,从横断解剖到多平面,乃至立体的一次飞跃,让抽象变的形象,大大地提高了准确性,…