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


    一. 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上可以使用的钩子(当然这种方式看到的钩子和实际触发顺序无关):
    1.png

    注意上图中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插件中后可以看到运行中触发了传入的回调函数:
    2.png

    四. 实战

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

    3.png

    处理的逻辑就是利用html-webpack-plugin暴露的更改资源标签的事件钩子htmlWebpackPluginAlterAssetTags来进行资源处理,此时资源已经离过模块化和代码分割并已经在名称中加入了hash标记,只需要此时过滤掉名称中含有vendors且不包含相应入口名称的新的chunk即可,当然这只是一个基本功能,想要动态实现功能,还需要将上例中checkMap部分变为对Compiler或是Compilation上对应属性的引用,本篇不再赘述。

    【参考】

    [1] webpack之内部运行机制》

    作者:大史不说话
    链接:Webpack4.0各个击破(7)plugin篇
    来源:博客园
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    C 语言编程经典 100 例
    visual studio.net已检测到指定的web服务器运行的不是asp.net1.1版。无法运行asp.net web应用程序
    如何编译及运行java
    VBScript 函数集
    SQL SERVER定时作业的设置方法
    显示桌面按钮不小心被删,有什么办法找回?
    随机抽取n个记录的SQL
    打开项目时提示如下错误:Visual Studio .NET 无法创建应用程序 。问题很可能是因为本地 Web 服务器上没有安装所需的组件
    简单的数据库连接
    ASP中各种数据库连接代码
  • 原文地址:https://www.cnblogs.com/xzsj/p/xzsj-frontend-webpack-plugin.html
Copyright © 2020-2023  润新知