扩展 HtmlwebpackPlugin 插入自定义的脚本

webpack提供了一个如何开发 webpack 插件的介绍,你可以直接访问这里查看,这里提供一个扩展 HtmlWebpackPlugin 的开发实例。

前面我们介绍过 HtmlWebpackPlugin, 这个插件允许将 webpack 动态打包的输出注入到页面中,但是,有的时候我们需要在这个页面中注入一些自定义的样式表或者脚本,HtmlWebpackPlugin 并不支持这个特性。有人向插件作者提了建议,这里是讨论的内容,结果是插件提供了几个事件来支持自己来实现这个特性。我们通过一个实例来演示如何使用这些事件来扩展 webpack。

需求

我们希望能够自动插入一个脚本的 script 在 webpack 生成的 script 之前,以便提前加载我们自定义的数据。最后生成的 HTML 类似这样的效果。

    <script type="text/javascript" src="./configuration/config.js"></script>
    <script type="text/javascript" src="style.bundle.js"></script>
    <script type="text/javascript" src="app.bundle.js"></script>

第一行是我们期望注入的脚本,其它两行是 webpack 导出的脚本。

插件入门

作为一个 webpack 的插件,使用方式是这样的。

plugins: [
    new MyPlugin({
        paths: ["./configuration/config.js"]
    }),
    new HtmlwebpackPlugin({
        title: ‘Hello Angular2!‘,
        template: ‘./src/index.html‘,
        inject: true
    })
],

所有的插件定义在 plugins 中,插件组成的一个数组,每个元素是一个插件的对象实例,具体传递什么参数,是你自己定义的。

从使用方式中可以看出,其实我们需要一个 JavsScript 的类函数,也就是说,写 webpack 插件就是定义一个这样的函数,这个函数需要接收参数。

webpack 还要求这个对象提供一个名为 apply 的函数,这个函数定义在插件的原型上,webpack 会调用插件实例的这个方法,在调用的时候还会传递一个参数,以便我们访问 webpack 的上下文信息。

官方提供的实例函数如下,最后一行是使用 CommonJs 风格导出这个插件。

function HelloWorldPlugin(options) {
  // Setup the plugin instance with options...
}

HelloWorldPlugin.prototype.apply = function(compiler) {
  compiler.plugin(‘done‘, function() {
    console.log(‘Hello World!‘);
  });
};

module.exports = HelloWorldPlugin;

传递参数

在我们的需求中,我们希望传递一个名为 paths 的路径参数,其中的每个路径需要生成一个 script 元素,插入到 webpack 导出的 script 之前。

new MyPlugin({
        paths: ["./configuration/config.js"]
    }),

在我们的插件中,需要保存这个参数,以便在 apply 函数中使用。

function MyPlugin(options) {
    // Configure your plugin with options...
this.options = options;
}

直接保存到当前的对象实例中,在配合 new 的时候,this 就是刚刚创建的插件对象实例了。

实现

在 webpack 调用插件对象的 apply 方式的时候,我们首先应该获取我们保存的参数,使用 this 访问当前对象,获取刚刚保存的参数。

MyPlugin.prototype.apply = function(compiler) {
    // ...
    var paths = this.options.paths;

};

在我们的 apply 方法内,需要调用 compiler 的 plugin 函数。这个函数注册到 webpack 各个处理阶段上,可以支持的参数有:

我们这里使用了 compilation 编译任务。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin(‘compilation‘, function(compilation, options) {

    });
};

webpack 会给我们提供的回调函数提供参数,我们可以注册编译阶段的事件了。html-webpack-plugin 提供了一系列事件。

Async:

  • html-webpack-plugin-before-html-generation
  • html-webpack-plugin-before-html-processing
  • html-webpack-plugin-alter-asset-tags
  • html-webpack-plugin-after-html-processing
  • html-webpack-plugin-after-emit

Sync:

  • html-webpack-plugin-alter-chunks

我们可以注册到它处理 HTML 之前,使用 html-webpack-plugin-before-html-processing 事件。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin(‘compilation‘, function(compilation, options) {
        compilation.plugin(‘html-webpack-plugin-before-html-processing‘, function(htmlPluginData, callback) {
         ......        });
    });
};

在这个回调函数中,我们可以得到 html-webpack-plugin 提供的上下文对象,比如,它准备生成 script 所对应的 javascript 文件路径就保存在 htmlPluginData.assets.js 数组中,它会根据这个数组中的路径,依次生成 script 元素,然后插入到 Html 网页中。

我们需要的就是就我们的路径插入到这个数组的前面。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin(‘compilation‘, function(compilation, options) {
        compilation.plugin(‘html-webpack-plugin-before-html-processing‘, function(htmlPluginData, callback) {
            for (var i = paths.length - 1; i >= 0; i--) {
                htmlPluginData.assets.js.unshift(paths[i]);
            }
            callback(null, htmlPluginData);
        });
    });
};

完整的插件代码如下所示。

function MyPlugin(options) {
this.options = options;
}

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin(‘compilation‘, function(compilation, options) {
        compilation.plugin(‘html-webpack-plugin-before-html-processing‘, function(htmlPluginData, callback) {
            for (var i = paths.length - 1; i >= 0; i--) {
                htmlPluginData.assets.js.unshift(paths[i]);
            }
            callback(null, htmlPluginData);
        });
    });
};

module.exports = MyPlugin;

最后一行是导出我们的插件。

讨论

通过 webpack 的插件机制,我们可以自由地扩展 webpack ,实现我们需要的特性。

See Also:

HOW TO WRITE A PLUGIN

如何写一个webpack插件(一)

webpack使用优化(基本篇) #2

html-res-webpack-plugin

时间: 2024-08-25 08:13:29

扩展 HtmlwebpackPlugin 插入自定义的脚本的相关文章

监控开发之用python扩展dstat插件自定义实时监控

dstat是一个python开源的实时监控工具,一般是用来做系统性能监控的.咱们这里只是提他的自定义插件开发,用来打造自己的dstat. 有朋友可能还没清楚是啥意思, 咱们查看系统的状体状态有人喜欢用vmstat,也有人喜欢用dstat.相比来说dstat的功能模块更全一点是,这里还只是说查看系统性能方面的 !   如果想一边查看,系统的各方面性能指标,还想看你应用的一些个负载相关,比如某个程序的负载,mongodb的锁lock百分比,mysql连接数...   懂了吧 ! 下面是dstat的插

Cacti 模板(图形模板、数据模板、主机模板)与自定义监控脚本

Cacti定义了三种类型的模板,分别是 主机模板 数据模板 图形模板     主机模板(Host templates),它是图像模板和数据查询的一个集合,描述了监控某一类型的机器需要生成那些图像. 数据模板(Data templates),它描述了 Cacti 存储哪些数据到指定类型的 RRD 文件.该模板与 RRDTool 工具的 create 命令相关. 图形模板(Graph templates),描述了生成的一张图像应该是什么样子的.包括使用哪些数据模板.展示哪些元素.是否使用 CDEF

自定义zabbix脚本--网卡平均流量

自定义zabbix脚本--网卡平均流量1. 在客户端修改配置文件 /etc/zabbix/zabbix_agentd.conf需要改动两个地方:(1) UnsafeUserParameters=1(2) UserParameter=my.net.if[*](改成英文的方括号), /usr/local/sbin/zabbix/net.sh $1 $2 //其中UserParameter用来自定义键值,(类似于net.if.in),自己写的脚本往往会有参数,所以需要加,这是固定写法,如果脚本压根就没

如何自定义服务脚本以及如何制作标准rpm服务脚本

自定义服务脚本: #!/bin/bash #myscript #chkconfig: 2345 90 20 #description: Starts, stops and saves iptables firewall case $1 in start) echo "start my script!!" sleep 1 ;; restart) echo "restart my script!!" sleep 1 ;; stop) echo "stop my

SQL Server扩展事件(Extended Events)-- 使用扩展事件跟踪监控死锁脚本实现

SQL Server扩展事件(Extended Events)-- 使用扩展事件跟踪监控死锁脚本实现 -- Create a new event session (it is better to create a new session and not modify the system's built-in session "system_health"): CREATE EVENT SESSION [Deadlock_Monitor] ON SERVER ADD EVENT sql

[Python]linux自定义Python脚本命令

在window下写好的程序配置到Linux上,要实现任意目录下的命令调用. 由于初学Linux,这里从文件传输等最基本的方法入手,记录配置的过程中遇到的各种问题. 连接远端服务器 这里使用putty这个工具,用SSH方法连上远端服务器 传输文件 使用FTP传输,这里用filezilla作为本地服务器,图形化界面,方便快捷 安装文件里引用的python包 wget url 命令联网下载安装包 wget http:/www.^&*&%%& 解压缩(具体可见blog:http://www

Dubbo源码分析(三):自定义Schema--基于Spring可扩展Schema提供自定义配置支持(spring配置文件中 配置标签支持)

在很多情况下,我们需要为系统提供可配置化支持,简单的做法可以直接基于Spring的标准Bean来配置,但配置较为复杂或者需要更多丰富控制的时候,会显得非常笨拙.一般的做法会用原生态的方式去解析定义好的xml文件,然后转化为配置对象,这种方式当然可以解决所有问题,但实现起来比较繁琐,特别是是在配置非常复杂的时候,解析工作是一个不得不考虑的负担.Spring提供了可扩展Schema的支持,这是一个不错的折中方案,完成一个自定义配置一般需要以下步骤: 设计配置属性和JavaBean 编写XSD文件 编

ansible-playbook基于role的配置一键安装zabbix客户端以及拉取自定义监控脚本

在IT工作中,您可能会一遍又一遍地执行相同的任务:没有人喜欢重复的任务.通过Ansible,IT管理员可以开始自动化日常任务中的苦差事.自动化解放了管理人员,专注于通过加快应用交付时间和建立在成功文化基础之上,为业务提供更多价值的努力.最终,Ansible为团队提供了他们永远无法获得足够的一件事:时间.让聪明的人专注于聪明的事情. Ansible是一种简单的自动化语言,可以完美地描述IT应用程序基础结构.它易于学习,自我记录,并且不需要毕业级的计算机科学学位来阅读.自动化不应该比它正在取代的任务

zabbix自定义监控脚本配置

实验环境 环境 IP 服务端 192.168.24.168 客户端 192.168.24.188 实验条件: zabbix监控服务器.客户端都已经部署完成,被监控主机已添加完成,zabbix监控运行正常.zabbix服务器设置邮箱报警运行正常. 实现目的: zabbix自定义监控客户端用户量,当用户量大于三个以上,会自动发送报警邮件到指定的邮箱. 实验步骤 1.修改客户端配置文件 [[email protected] ~]# vim /usr/local/etc/zabbix_agentd.co