webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习webpack工具中相应的处理办法。(本篇中的参数配置及使用方式均基于webpack4.0版本

一. plugin概述

1.1 Plugin的作用

plugin机制是webpack中另一个核心概念,它基于事件流框架tapable,你可以参考浏览器环境中的【DOM事件模型】【SPA模型中的生命周期钩子】或是node环境中的【EventEmitter模块】来理解其作用。plugin系统提供给开发者监听webpack生命周期并在特定事件触发时执行指定操作的能力。

当然,要写一个真正能实现一定功能的插件,你还需要了解CompilerCompilation这两个概念,网上可以找到非常多相关的文章(《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)这几个典型步骤,从上面的示例可以看到,compilationCompiler生命周期中的一个步骤,使用compilation相关钩子的通用写法为:

compiler.hooks.compilation.tap('SomePlugin',function(compilation, callback){
compilation.hooks.someOtherHook.tap('SomeOtherPlugin',function(){
....
})
});

我们仿照上面的方法就可以查看到compilation对象上(compilation事件触发时,在回调函数中取得的引用)暴露的事件钩子。

CompilerCompilation暴露的事件钩子总数超过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篇的更多相关文章

  1. Webpack4.0各个击破(7)plugin篇

    目录 一. plugin概述 1.1 Plugin的作用 1.2 Compiler 1.3 Compilation 二. 如何写一个plugin 四. 实战 [参考] 一. plugin概述 1.1 ...

  2. Webpack4.0各个击破(8)tapable篇

    目录 一. tapable概述 二. tapable-0.2源码解析 2.1 代码结构 2.2 事件监听方法 2.3 事件触发方法 三. tapable1.0概述 一. tapable概述 tapab ...

  3. webpack4.0各个击破(5)—— Module篇

    webpack4.0各个击破(5)-- Module篇 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决 ...

  4. Webpack4.0各个击破(10)integration篇

    一. Integration 下文摘自webpack中文网: 首先我们要消除一个常见的误解,webpack是一个模块打包工具(module bundler),它不是一个任务执行工具,任务执行器是用来自 ...

  5. Webpack4.0各个击破(6)loader篇

    目录 一. loader综述 二. 如何写一个loader 三. loader的编译器本质 [参考] 一. loader综述 loader是webpack的核心概念之一,它的基本工作流是将一个文件以字 ...

  6. Webpack4.0各个击破(5)module篇

    一. 模块化乱炖 脚本合并是基于模块化规范的,javascript模块化是一个非常混乱的话题,各种[*MD]规范乱飞还要外加一堆[*.js]的规范实现.现代化前端项目多基于框架进行开发,较为流行的框架 ...

  7. Webpack4.0各个击破(1)html篇

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...

  8. webpack4.0各个击破(4)—— Javascript & splitChunk

    目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 ...

  9. webpack4.0各个击破(2)—— CSS篇

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...

随机推荐

  1. HDP Hive StorageHandler 下推优化的坑

    关键词:hdp , hive , StorageHandler 了解Hive StorageHandler的同学都知道,StorageHandler作为Hive适配不同存储的拓展类,同时肩负着Hive ...

  2. Redis sentinel 哨兵模式

    一.sentinel介绍 Sentinel作用: 1):Master状态检测 2):如果Master异常,则会进行Master-Slave切换,将其中一个Slave作为Master,将之前的Maste ...

  3. Centos7 通配符HTTPS证书申请 实测 笔记

    环境: 免费通配符HTTPS证书网址: https://letsencrypt.org/ 1.下载证书申请工具 [root@centos ~]# mkdir /opt/letsencrypt -p [ ...

  4. promise的异步链式调用

    场景:  淘米  干净的米下锅  蒸米饭  吃米饭 ;这几个步骤是一个接着一个执行, 也就是只有前面的做完后, 才会去做后面的. 并且每一步都需要用一部分时间去执行. function deal(ta ...

  5. js中的观察者模式

    什么事观察者模式: 这是一种创建松散耦合代码的技术.它定义对象间 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知.由主体和观察者组成,主体负责发布事件,同时观察者通过 ...

  6. Java 2018 面试

    1.Java的引用有什么作用?传递的是什么? Java的引用可以用来操作对象,传递的是对象的地址 2.引用分为几种?他们的区别是什么?弱引用用在什么地方? 分四种:强引用 . 软引用 . 弱引用 . ...

  7. React Native 填坑之神奇的报错,已解决

    下面对报错进行一下详细描述: 在debug时,点着点着,就会发生: 1.手机显示如下 : Attempted to transition from state `RESPONDER_INACTIVE_ ...

  8. 【安富莱原创开源应用第3期】花式玩转网络摄像头之VNC远程桌面版本,稳定运行2年不死机

    说明: 1.前段时间开源了一个网络摄像头的TCP版本 https://www.cnblogs.com/armfly/p/9173167.html,这次再来一个远程VNC的版本.使用更方便,无需大家制作 ...

  9. SUSE12Sp3-Nginx安装

    1.安装pcre(nginx 依赖) 把安装包pcre-8.12.tar.gz复制到服务器指定目录 tar -zxvf pcre-8.12.tar.gz # 解压 cd pcre-8.12 #进入目录 ...

  10. PHP常用设计模式讲解

    开发中适当的使用设计模式,可以让项目有更易扩展,易维护.低耦合,代码简洁等 单例模式 <?php /** * 单例模式:使类在全局范围内只允许创建一个对象,常用于数据库连接等 */ class ...