乐趣区

关于javascript:Webpack40各个击破7plugin篇

一. 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 之外部运行机制》

退出移动版