一、插件概述1.1插件功能插件机制是webpack中的另一个核心概念。它基于可点击的事件流框架。可以参考【浏览器环境下的DOM事件模型】、【SPA模型下的生命周期钩子】或者节点环境下的【EventEmitter模块】了解其作用。插件系统为开发人员提供了监控webpack生命周期并在触发特定事件时执行指定操作的能力。当然,要写出真正能够实现某些功能的插件,还需要了解Compiler和Compilation这两个概念。网上可以找到很多相关的文章(《webpack-docs/plugin》)。1.2Compiler从性能的角度,Compiler暴露了webpack整个生命周期相关的hooks,可以通过以下方式访问://基本写法compiler.hooks.someHook.tap(...)//如果youwanttoconfiguretheentryafterExecuteafunctioncompiler.hooks.entryOption.tap(...)//如果想在生成资源输出到输出指定目录之前执行一个函数compiler.hooks.emit.tap(...)webpack很重要在生命周期节点上提供了事件钩子,我们可以使用它来添加一些自定义功能。我们写一个插件,直观的看到webpack中涉及到的hooks://check-compiler-hooks-plugin.jsconstpluginName='checkCompilerHooksPlugin';module.exports=classcheckCompilerHooksPlugin{apply(compiler){//打印出entryOption暴露的hook编译器在执行结束时for(varhookofObject.keys(compiler.hooks)){console.log(hook);}}}可以看到Compiler上可以使用的hooks(当然这样看到的hooks与实际触发顺序无关):注意Compiler暴露的事件hook中有一个compilation。上图中的hooks,下一节会讲解。1.3编译编译公开了与模块和依赖项相关的更细粒度的事件挂钩。根据官方文档,模块会经历加载(loaded)、密封(sealed)、优化(optimized)、分块(chunked)、散列(hashed)和重新创建(restored),这些典型的步骤,从上面可以看出例如,编译是Compiler生命周期中的一个步骤,编译相关的hooks的一般使用方式是:'SomeOtherPlugin',function(){....})});我们可以按照上面的方法查看编译对象(编译事件触发时,回调函数中获取的引用)暴露事件钩子。Compiler和Compilation暴露的事件hook总数超过30个,具体可以直接在官方文档中查询API,在特定阶段hook到自己想要添加的自定义函数中。要想更好的理解plugin的机制,还需要了解webpack的整个生命周期和tapable的事件流框架。2、如何编写插件根据webpack官方文档,一个自定义插件需要包括:一个javascript命名的函数插件函数的原型上必须有一个apply方法。指定绑定到webpack本身的事件挂钩。注册一个回调函数来处理webpack实例中的指定数据。处理完成后调用webpack提供的回调。官网给出了一个基本的结构示例://console-log-on-build-webpack-plugin.jsconstpluginName='ConsoleLogOnBuildWebpackPlugin';classConsoleLogOnBuildWebpackPlugin{apply(compiler){compiler.hooks.run.tap(pluginName,compilation=>{console.log('webpack构建过程开始');});}}添加到webpack插件后,可以看到运行时触发了传入的回调函数:4.实战在《webpack4.0各个击破(4)——javascript & splitChunks》一文中,我们使用splitChunks函数对初始模块进行切分,插入脚本标签时对于多页应用模型的html入口,存在无法自动插入的问题。在本节中,我们使用webpack-dispatch-chunk-plugin来解决这个问题。处理的逻辑是利用html-webpack-plugin暴露的事件钩子htmlWebpackPluginAlterAssetTags改变资源标签进行资源处理。这时候资源已经脱离了模块化和代码分割,并且在名称中加入了hash标签。此时只需要过滤掉名称中包含vendors,不包含相应entry名称的新chunk即可。当然,这只是一个基本功能。如果想动态实现功能,需要将上例中的checkMap部分改成Compiler或Compilation上对应的属性。引文,本文不再赘述。【参考】[1]《webpack之内部运行机制》
