Webpack4.0各个击破(7)plugin篇
一. plugin概述
1.1 Plugin的作用
plugin机制是webpack中另一个核心概念,它基于事件流框架tapable,你可以参考浏览器环境中的【DOM事件模型】,【SPA模型中的生命周期钩子】或是node环境中的【EventEmitter模块】来理解其作用。plugin系统提供给开发者监听webpack生命周期并在特定事件触发时执行指定操作的能力。
当然,要写一个真正能实现一定功能的插件,你还需要了解Compiler和Compilation这两个概念,网上可以找到非常多相关的文章(《webpack-docs/plugin》)。
1.2 Compiler
从表现上看,Compiler暴露了和webpack整个生命周期相关的钩子,通过如下的方式访问:
//基本写法
compiler.hooks.someHook.tap(...)
//如果希望在entry配置完毕后执行某个功能
compiler.hooks.entryOption.tap(...)
//如果希望在生成的资源输出到output指定目录之前执行某个功能
compiler.hooks.emit.tap(...)
webpack在重要的生命周期节点上都提供了事件钩子,我们可以借此加入一些自定义的功能。我们来编写一个插件,直观地看看webpack中涉及的钩子:
//check-compiler-hooks-plugin.js
const pluginName = 'checkCompilerHooksPlugin';
module.exports = class checkCompilerHooksPlugin {
apply(compiler){
//打印出entryOption执行完毕时Compiler暴露的钩子
for(var hook of Object.keys(compiler.hooks)){
console.log(hook);
}
}
}
可以看到Compiler上可以使用的钩子(当然这种方式看到的钩子和实际触发顺序无关):

注意上图中Compiler.hooks暴露的事件钩子中有一个compilation,下一小节将解释它。
1.3 Compilation
Compilation暴露了与模块和依赖有关的粒度更小的事件钩子,官方文档中的说法是模块会经历加载(loaded),封存(sealed),优化(optimized),分块(chunked),哈希(hashed)和重新创建(restored)这几个典型步骤,从上面的示例可以看到,compilation是Compiler生命周期中的一个步骤,使用compilation相关钩子的通用写法为:
compiler.hooks.compilation.tap('SomePlugin',function(compilation, callback){
compilation.hooks.someOtherHook.tap('SomeOtherPlugin',function(){
....
})
});
我们仿照上面的方法就可以查看到compilation对象上(compilation事件触发时,在回调函数中取得的引用)暴露的事件钩子。
Compiler和Compilation暴露的事件钩子总数超过30个,具体信息可以直接在官方文档直接查询API,在特定的阶段钩入想要添加的自定义功能。想要更好地理解
plugin的作用机制,还需要了解webpack的整个生命周期以及事件流框架tapable.
二. 如何写一个plugin
根据webpack官方文档的说明,一个自定义的plugin需要包含:
- 一个javascript命名函数
- 插件函数的prototype上要有一个
apply方法 - 指定一个绑定到webpack自身的事件钩子
- 注册一个回调函数来处理webpack实例中的指定数据
- 处理完成后调用webpack提供的回调
官网给出了一个基本的结构示例:
//console-log-on-build-webpack-plugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler){
compiler.hooks.run.tap(pluginName, compilation=>{
console.log('webpack构建过程开始');
});
}
}
将其添加到webpack插件中后可以看到运行中触发了传入的回调函数:

四. 实战
在《webpack4.0各个击破(4)——javascript & splitChunks》一文中,我们使用splitChunks功能对初始模块进行代码分割,在为多页面应用模型的html入口插入script标签时遇到了无法自动插入的问题,那么本节我们用一个webpack-dispatch-chunk-plugin来解决一下这个问题。

处理的逻辑就是利用html-webpack-plugin暴露的更改资源标签的事件钩子htmlWebpackPluginAlterAssetTags来进行资源处理,此时资源已经离过模块化和代码分割并已经在名称中加入了hash标记,只需要此时过滤掉名称中含有vendors且不包含相应入口名称的新的chunk即可,当然这只是一个基本功能,想要动态实现功能,还需要将上例中checkMap部分变为对Compiler或是Compilation上对应属性的引用,本篇不再赘述。
【参考】
[1] webpack之内部运行机制》
作者:大史不说话
链接:Webpack4.0各个击破(7)plugin篇
来源:博客园
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
Webpack4.0各个击破(7)plugin篇的更多相关文章
- webpack4.0各个击破(7)—— plugin篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- Webpack4.0各个击破(8)tapable篇
目录 一. tapable概述 二. tapable-0.2源码解析 2.1 代码结构 2.2 事件监听方法 2.3 事件触发方法 三. tapable1.0概述 一. tapable概述 tapab ...
- webpack4.0各个击破(5)—— Module篇
webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决 ...
- Webpack4.0各个击破(10)integration篇
一. Integration 下文摘自webpack中文网: 首先我们要消除一个常见的误解,webpack是一个模块打包工具(module bundler),它不是一个任务执行工具,任务执行器是用来自 ...
- Webpack4.0各个击破(6)loader篇
目录 一. loader综述 二. 如何写一个loader 三. loader的编译器本质 [参考] 一. loader综述 loader是webpack的核心概念之一,它的基本工作流是将一个文件以字 ...
- Webpack4.0各个击破(5)module篇
一. 模块化乱炖 脚本合并是基于模块化规范的,javascript模块化是一个非常混乱的话题,各种[*MD]规范乱飞还要外加一堆[*.js]的规范实现.现代化前端项目多基于框架进行开发,较为流行的框架 ...
- Webpack4.0各个击破(1)html篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- webpack4.0各个击破(4)—— Javascript & splitChunk
目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 ...
- webpack4.0各个击破(2)—— CSS篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
随机推荐
- Vitis AI--个人调试篇
一.下载VITIS-AI的仓库 单独git clone很慢,因此先将其导入到gitee平台,再执行clone 1. Import VITIS-AI github repo into gitee rep ...
- JavaSwing 船只停靠管理可视化(三)
JavaSwing 船只停靠管理可视化(一) JavaSwing 船只停靠管理可视化(二) JavaSwing 船只停靠管理可视化(三) JavaSwing 船只停靠管理可视化(四) JavaSwin ...
- ESXi 中重新启动管理代理
使用直接控制台用户界面 (DCUI)重启管理代理: 连接到您的 ESXi 主机的控制台. 按 F2 自定义系统. 以 root 身份登录. 使用上下箭头导航至故障排除选项>重新启动管理代理. 按 ...
- 【NC基础操作】开发环境配置初体验
当我们拿到开发工具UAP-STUDIO-6.5.0.2和Home文件的时候,意味着我们可以用这两样东西开始进行项目开发了(默认其他准备已就绪). 运行UAP-STUDIO-6.5.0.2 双击进入&q ...
- 架构设计哲学【三种方式:支持DevOps的原则】
三种方式:支持DevOps的原则 2012年8月22日作者Gene Kim 45条评论 这篇文章是杨波老师分享的一篇文章:这几年对他架构影响最深的一篇文章.主要描述是关于DevOps的,但对系统架构同 ...
- Python强大的日志模块logging
前言 日志是对于软件执行所发生的事件的一种追踪记录方式.日常使用过程中对代码执行的错误和问题会进行查看日志来分析定位问题所在.平常编写代码以及调试也经常用到.通常的新手的做法是直接print打印,但是 ...
- JavaCV FFmpeg AAC编码
上次成功通过FFmpeg采集麦克风的PCM数据,这次针对上一次的程序进行了改造,使用AAC编码采集后的数据. (传送门) JavaCV FFmpeg采集麦克风PCM音频数据 采集麦克风数据是一个解码过 ...
- SpringBoot对静态资源的映射规则
在WebMvcAutoConfiguration类中有相对应的方法addResourceHandlers public void addResourceHandlers(ResourceHandler ...
- python函数1-函数基础
- 【Linux】如何查找命令及历史记录history
如何查找命令及历史记录 文章目录 如何查找命令及历史记录 1.如何找到一个命令 2.命令的历史记录 3.一些实用的快捷键 4.小结 5.参考资料 如何找到一个命令.命令的历史记录.一些实用的快捷键.总 ...