自定义实现webpack插件原理解析
webpack插件构成部分
- 一个具名javascript函数
- 在他的原型上定义apply方法
- 指定一个触及到 webpack本身的事件钩子
- 操作webpack内部的特定实例数据
- 实现功能后调用 webpack提供的callback函数
webpack基本架构
插件有一个构造函数实例化出来, 构造函数定义apply方法,在安装插件时,apply方法会被webpack的compiler调用一次。apply方法可以接受一个webpack的compiler对象的引用, 从而可以在回调函数中访问到compiler对象。
插件钩子和触发方法简介
Webpack 提供钩子有很多,这里简单介绍几个
- entryOption:在 webpack 选项中的
entry
配置项 处理过之后。 afterPlugins
: 设置完初始插件之后。compilation
: 编译创建之后,生成文件之前。emit
: 生成资源到output
目录之前。done
: 编译完成。
Webpack 提供三种触发钩子的方法:
tap
:以同步方式触发钩子(支持两个参数,插件名称compilation 和回调函数callback)tapAsync
:以异步方式触发钩子;tapPromise
:以异步方式触发钩子,返回 Promise;\
官网提供简单的插件结构
class HelloWorldPlugin {apply(compiler) {compiler.hooks.done.tap('Hello World Plugin', (stats /* 在 hook 被触及时,会将 stats 作为参数传入。 */) => {console.log('Hello World!');});}
}
module.exports = HelloWorldPlugin;
使用插件
// webpack.config.js
var HelloWorldPlugin = require('hello-world');module.exports = {// ... 这里是其他配置 ...plugins: [new HelloWorldPlugin({ options: true })]
};
自定义实现插件需求:动态添加script标签
我们先在模版中做个标记,后面进行标记替换
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Webpack 插件开发入门</title>
</head>
<body><!-- other code --><!--SetScriptTimestampPlugin inset script-->
</body>
</html>
我们插件应该是要在 HTML 输出之前,动态添加 script
标签,所以我们选择钩子是 compilation
阶段
compilation 继承于compiler
,包含 compiler
所有内容(也有 Webpack 的 options
),而且也有 plugin
函数接入任务点。
class SetScriptTimestampPlugin {apply(compiler) {compiler.hooks.compilation.tap('SetScriptTimestampPlugin', (compilation, callback) => {// 插件逻辑 调用compilation提供的plugin方法compilation.plugin("html-webpack-plugin-before-html-processing",function(htmlPluginData, callback) {// 读取并修改 script 上 src 列表let jsScr = htmlPluginData.assets.js[0];htmlPluginData.assets.js = [];let result = `<script>let scriptDOM = document.createElement("script");let jsScr = "./${jsScr}";scriptDOM.src = jsScr + "?" + new Date().getTime();document.body.appendChild(scriptDOM)</script>`;let resultHTML = htmlPluginData.html.replace("<!--SetScriptTimestampPlugin inset script-->", result);// 返回修改后的结果htmlPluginData.html = resultHTML;});});}
}
module.exports = SetScriptTimestampPlugin;
在上面插件逻辑中,具体做了这些事
1. 执行 compilation.plugin
方法,并传入两个参数:插件事件和回调方法
- 所谓“插件事件”即插件所提供的一些事件,用于监听插件状态
2.获取脚本文件名称列表并清空
- 在回调方法中,通过
htmlPluginData.assets.js
获取需要通过script
引入的脚本文件名称列表,拷贝一份,并清空原有列表
3.编写替换逻辑
- 动态创建一个
script
标签,将其src
值设置为上一步读取到的脚本文件名,并在后面拼接 时间戳 作为参数。
4.插入替换逻辑
- 通过
htmlPluginData.html
可以获取到模版文件的字符串输出,我们只需要将模版字符串中替换入口<!--SetScriptTimestampPlugin inset script-->
替换成我们上一步编写的替换逻辑即可。
5.返回HTML文件
- 最后将修改后的 HTML 字符串,赋值给原来的
htmlPluginData.html
达到修改效果
最后使用插件
// webpack.config.jsconst SetScriptTimestampPlugin = require("./SetScriptTimestampPlugin.js");
module.exports = {// ... 省略其他配置plugins: [// ... 省略其他插件new SetScriptTimestampPlugin() ]
}
自定义实现webpack插件原理解析相关推荐
- MyBatis插件原理解析及自定义插件实践
一.插件原理解析 首先,要搞清楚插件的作用.不管是我们自定义插件,还是用其他人开发好的第三方插件,插件都是对MyBatis的四大核心组件:Executor,StatementHandler,Param ...
- android黑科技系列——微信抢红包插件原理解析和开发实现
一.前言 自从几年前微信添加抢红包的功能,微信的电商之旅算是正式开始正式火爆起来.但是作为Android开发者来说,我们在抢红包的同时意识到了很多问题,就是手动去抢红包的速度慢了,当然这些有很多原因导 ...
- Webpack HMR 原理解析
Hot Module Replacement(以下简称 HMR)是 webpack 发展至今引入的最令人兴奋的特性之一 ,当你对代码进行修改并保存后,webpack 将对代码重新打包,并将新的模块发送 ...
- “约见”面试官系列之常见面试题第四十四篇之webpack打包原理解析?(建议收藏)
webpack打包是如何运行的 也可以称为,webpack是如何实现模块化的 CommonJS是同步加载模块,一般用于node.因为node应用程序运行在服务器上,程序通过文件系统可以直接读取到各个模 ...
- http-invoker插件原理解析
背景 项目中不可避免的使用第三方api接口,但是如果使用apache-httpclient总是不可避免需要设置连接池等,即使每次拷贝对于项目来说也显得冗余 http-api-invoker的方式可以使 ...
- 真香定律!Android动态换肤实现原理解析,原理+实战+视频+源码
自己项目中一直都是用的开源的xUtils框架,包括BitmapUtils.DbUtils.ViewUtils和HttpUtils四大模块,这四大模块都是项目中比较常用的.最近决定研究一下xUtils的 ...
- 霖呆呆的六个自定义Webpack插件详解-自定义plugin篇(3)
霖呆呆的webpack之路-自定义plugin篇 你盼世界,我盼望你无bug.Hello 大家好!我是霖呆呆! 有很多小伙伴在打算学写一个webpack插件的时候,就被官网上那一长条一长条的API给吓 ...
- webpack原理解析【万字长文】
开场白 大家好,我是Webpack,AKA打包老炮,我的slogan是:"打天下的包,让Rollup无包可打". 今天我要带来的才艺是:剖析打包的艺术 故事还要从一次npm包工头 ...
- Android 插件化原理解析——插件加载机制
上文 Activity生命周期管理 中我们地完成了『启动没有在AndroidManifest.xml中显式声明的Activity』的任务:通过Hook AMS和拦截ActivityThread中H类对 ...
最新文章
- 百万级访问量网站的技术准备工作[转帖]
- 在C#里怎样获得当前Windows操作系统的语言种类?以及如何知道当前Windows版本?...
- modelandview 可以返回html么_Python: 爬虫网页解析工具lxml.html(一)
- 常见排序算法(C实现)
- 各个线程顺序循环执行
- linux mount 原文件夹,window文件夹mount挂载Linux
- VIP客户服务系统设计(四)——按用户角色构思系统功能(上)
- android应用程序列表,List列表应用程序-小知识 #103
- JavaScript 凭什么力压 Java、Python 横扫编程语言榜单?
- catkin_make和cmake
- python中requests模块使用
- silverlight:手写板/涂鸦/墨迹/InkPresenter示例程序
- matlab常用插值函数
- 利用接口和继承实现 求三角形 圆形面积 和以圆形为底的圆锥形的体积
- 转:稻盛和夫:在软弱的领导人手下工作,是可悲的
- 关于数字的智力题-三个女儿的年龄
- WORDBOOK - ForeverStrong Cheng - YongQiang Cheng
- 信息安全-网站安全需求分析与安全保护工程(一)
- mysql 查看等待事件_分享两个实用SQL--查看故障时间等待事件、问题sql及会话访问次数...
- 【ZZULIOJ】1107: 回文数猜想(函数专题)
热门文章
- 传统餐桌行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- 蓝桥杯12题c语言,2012.C语言‘蓝桥杯“预赛.真题.高职
- 数字电子技术基础大作业---电子表、流水灯
- 代表 YGG 的 Illuvium 首席游戏大使 —— Zom
- 频率选择性衰落、时间选择性衰落
- 前端安全系列:如何防止CSRF攻击?
- 前端开发工具HbuilderX的使用技巧
- 厦大2021届大一小学期C语言作业1 数组+字符串+指针+位操作
- git 分支教程小游戏
- 养猫日记-20200411