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.mzph.cn/news/159994.shtml

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

相关文章

灵活运用Vue 3中的setup函数—深入解析Composition API

新建项目,项目主入口为App.vue(主组件),新建child.vue(子组件)。 1.1 setup 执行 时机问题 1.在主组件里引入子组件和ref: import {ref} from vue import child from ./components/child.vue2…

uni-app项目细节记录

js字符串插值 使用反引号,内容使用${参数} url:/pages/login/index?name${this.name}&passwd${this.passwd}

2024年企业软件定制开发必须了解的4大趋势

根据Statista的统计数据显示,全球企业级软件市场占据主导地位,预计到2028年市场规模将接近3760亿美元。企业应用软件市场持续稳健增长,即使在经济不景气时期也能够持续增长,彰显出软件解决方案对提高企业运营效率和盈利能力的重要…

HTML实现简易计算器

随便写的&#xff0c;可能有bug&#xff0c;可以在评论区指出哈。 HTML代码&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>AI简易计算器</title> </head> <body> <table id"c…

【剑指Offer】44.数字序列中某一位的数字

题目 数字以0123456789101112131415...的格式作为一个字符序列&#xff0c;在这个序列中第2位&#xff08;从下标0开始计算&#xff09;是2&#xff0c;第10位是1&#xff0c;第13位是1&#xff0c;以此类题&#xff0c;请你输出第n位对应的数字。 数据范围&#xff1a;0≤n≤…

【小黑送书—第九期】>>重磅!这本30w人都在看的Python数据分析畅销书:更新了!

想学习python进行数据分析&#xff0c;这本《利用python进行数据分析》是绕不开的一本书。目前该书根据Python3.10已经更新到第三版。 Python 语言极具吸引力。自从 1991 年诞生以来&#xff0c;Python 如今已经成为最受欢迎的解释型编程语言。 pandas 诞生于2008年。它是由韦…

Mysql中自增主键是如何工作的

自增主键的特点是当表中每新增一条记录时&#xff0c;主键值会根据自增步长自动叠加&#xff0c;通常会将自增步长设置1&#xff0c;也就是说自增主键值是连续的。那么MySQL自增主键值一定会连续吗&#xff1f;今天这篇文章就来说说这个问题&#xff0c;看看什么情况下自增主键…

第三阶段学习beiqi3

滑行回馈力矩给定修改力矩 if(1 Vehicle_cmd.cmdmode.data.slip_feedback_flag)//滑行回馈{motor_regen_power EV_MCU_Para.field.Motor_regen_power_slip_level;//滑行固定功率在 10kw *****11.22 这里除去2 5kw motor_regen_trq_lmt _IQmpyI32(motor_regen_power, 9550)…

postman设置接口关联这样做,薪资直接涨3k

postman设置接口关联 在实际的接口测试中&#xff0c;后一个接口经常需要用到前一个接口返回的结果&#xff0c; 从而让后一个接口能正常执行&#xff0c;这个过程的实现称为关联。 在postman中实现关联操作的步骤如下&#xff1a; 1、利用postman获取上一个接口指定的返回值…

kubernetes资源管理

kubernetes资源管理 文章目录 kubernetes资源管理1.资源管理介绍2.YAML语言介绍3.资源管理方式3.1 命令式对象管理3.2 命令式对象配置3.3 声明式对象配置扩展&#xff1a;kubectl在node节点上运行 1.资源管理介绍 在kubernetes中&#xff0c;所有的内容都抽象为资源&#xff0…

c语言编程(模考3)统计字符串中数字字符的个数

统计字符串中数字字符的个数 #include<stdio.h> int main(){char inputString[100];int digitCount 0;printf("请输入一个字符串&#xff1a;");scanf("%s",inputString);for(int i0;inputString[i]!\0;i){if (inputString[i]>0&&inpu…

jQuery的学习(一篇文章齐全)

目录 Day29 jQuery 1、jQuery介绍 2、jQuery的选择器 2.1、直接查找 2.2、导航查找 3、jQuery的绑定事件 案例1&#xff1a;绑定取消事件 案例2&#xff1a;模拟事件触发 4、jQuery的操作标签 tab切换案例jQuery版本&#xff1a; 案例1&#xff1a; 案例2&#xff…

Thread的常用方法

一&#xff0c;常用方法 二&#xff0c;案例 父类&#xff1a; package ThreadLianXi;import ThreadLianXi.ZhiLeiA;public class Name {public static void main(String[] args)throws Exception{Thread t1 new ZhiLeiA("1号");//修改名字t1.setName("1号&quo…

中国最常用的制作报表的软件有哪些?

​随着信息化时代的浪潮席卷而来&#xff0c;报表制作软件已经成为了企业管理中的得力助手。在中国的大地上&#xff0c;有许多优秀的报表制作软件&#xff0c;而本文将为您揭示五位佼佼者&#xff0c;其中更以VeryReport报表软件为首选。 编辑搜图 请点击输入图片描述&#x…

华为昇腾开发板共享Windows网络上网的方法

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 具体参考文章&#xff1a;linux(内网&#xff09;通过window 上网。具体是两步&#xff1a;一是在windows上设置internet连接共享。二是打开Atlas 200I D…

最长连续序列[中等]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个未排序的整数数组nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。请你设计并实现时间复杂度为O(n)的算法解决此问题。 示例 1&#xff1a; 输入&#xff1a;nums […

【性能测试学习】2023最有效的7大性能测试技术(建议收藏)

进入互联网时代&#xff0c;性能测试显得越来越重要&#xff0c;移动应用、web应用和物联网应用都需要进行性能测试和性能调优&#xff0c;而进行性能和负载测试会产生了大量的数据&#xff0c;这些数据难以分析。除了数据分析&#xff0c;我们还会遇到其它一些困难和挑战。 今…

win10 eclipse安装教程

前言&#xff1a;安装eclipse之前必须安装JDK&#xff0c;JDK是编译环境&#xff0c;eclipse是集成开发平台。 一、JDK的安装 Java Development Kit 简称 JDK (一). 官方下载地址&#xff1a; Java Archive Downloads - Java SE 8u211 and later (oracle.com) 找到&#xf…

关于的Java线程池,简解

Java线程池是一种常见的多线程编程技术&#xff0c;它可以在执行任务时复用已创建的多个线程&#xff0c;并且可以控制同时运行的线程数以避免资源占用过多的问题。 线程池可以用于处理需要频繁创建并执行线程的情况&#xff0c;例如在需要执行大量短期异步任务的环境中。通过使…

2020年计网408

第33题 下图描述的协议要素是&#xff08; &#xff09;。I. 语法 II. 语义 III. 时序 A. 仅 I B. 仅 II C. 仅 III D. I、II 和 III 本题考察网络协议三要素的相关知识。 网络协议的三要素分别是语法、语义、同步&#xff08;时序&#xff09;。语法&#xff1a;定义收发双…