扩展 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:
扩展 HtmlwebpackPlugin 插入自定义的脚本的更多相关文章
- ueditor插入自定义内容和样式
UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点 通过UEditor提供的API接口可以很方便的读写操作内容并设置编辑器里的样式 页 ...
- BlazeMeter发布chrome扩展插件,支持JMeter脚本创建
BlazeMeter发布chrome扩展插件,支持JMeter脚本创建http://www.automationqa.com/forum.php?mod=viewthread&tid=3898 ...
- centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobackupex/Xtrabackup 第四十节课
centos shell编程6一些工作中实践脚本 nagios监控脚本 自定义zabbix脚本 mysql备份脚本 zabbix错误日志 直接送给bc做计算 gzip innobacku ...
- 11月16日《奥威Power-BI基于SQL的存储过程及自定义SQL脚本制作报表》腾讯课堂开课啦
上周的课程<奥威Power-BI vs微软Power BI>带同学们全面认识了两个Power-BI的使用情况,同学们已经迫不及待想知道这周的学习内容了吧!这周的课程关键词—— ...
- nagios和zabbix自定义监控脚本
一. 自定义nagios监控脚本1. 在客户端上创建脚本/usr/local/nagios/libexec/check_disk.shvim /usr/local/nagios/libexec/ch ...
- GridView控件中插入自定义删除按钮并弹出确认框
GridView控件中插入自定义删除按钮,要实现这个功能其实有多种方法,这里先记下我使用的方法,以后再添加其他方法. 一.实现步骤 1.在GridView中添加模板列(TemplateField). ...
- MVC 用扩展方法执行自定义视图,替代 UIHint
MVC 用扩展方法执行自定义视图,替代 UIHint 项目中用了 Bootstrap , 这样就不用写太多的CSS了,省去很多事情.但是这个业务系统需要输入的地方很多,每个表都有100多个字段,每个页 ...
- 写一个可插入自定义标签的 Textarea 组件
- “插入自定义标签是什么鬼?” - “比如你要插入一个<wise></wise>的标签...” - “什么情况下会有这种需求?” - “得罪了产品的情况下...” 一.需求背 ...
- Sql 插入自定义主键
在遇到数据库设计是自增的主键,且需要插入自定义的主键Id时,这个时候如果直接Insert的话,将会发生错误,错误提示信息: 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 'XXX' ...
随机推荐
- Hadoop集群搭建安装过程(二)(图文详解---尽情点击!!!)
Hadoop集群搭建安装过程(二)(配置SSH免密登录)(图文详解---尽情点击!!!) 一.配置ssh无密码访问 ®生成公钥密钥对 1.在每个节点上分别执行: ssh-keygen -t rsa(一 ...
- VS 2005 修复重置(深度重置)
/resetuserdata 参数 如果 Visual Studio 在运行时被损坏,且无法从损坏状态进行恢复,您可以使用此参数将 Visual Studio 重置到其使用之初的状态.这些问题的例子可 ...
- js代码实现下拉菜单
效果 js代码: <script type="text/javascript"> function ShowSub(li) {//函数定义 var subMenu = ...
- 使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE)
一.原始写法 模块就是实现特定功能的一组方法. 只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块. function m1(){ //... } function m2(){ // ...
- CSS盒子模型的一些理解
盒子模型相当于把现实中的盒子形象化. 盒子模型的大小="内容(content)+内填充(padding)+边框(border)+外边距(margin)" 盒子模型方向为:top, ...
- 3、C#入门第3课
1.c#中一个解决方案 里面两个程序 怎么一个启动另一个? 我一个解决方案下,有两个工程,我想让A工程在适当时候,启动B工程,比如A中有个按钮,一点,B工程就启动了. System.Diagnosti ...
- 知识积累:CA详解
所有证书有多种文件编码格式,主要包括: CER编码(规范编码格式):是BER(基本编码格式)的一个变种,比BER规定得更严格DER编码(卓越编码格式):是BER(基本编码格式)的一个变种, 比BER ...
- yii2史上最简单式安装教程,没有之一
写一篇绝对堪称史上最easy的Yii2安装教程教你入门. 既然是安装Yii,我们先去官网下载一份Yii的高级模版,什么,你说打开页面乱七八糟的英文字母你看不懂?那这样大哥,你按照下面的截图进行操作好吧 ...
- javascript中无法通过div.style.left获取值的问题
一.问题总结: 样式必须直接写在元素内部才能通过div.style.left直接获取属性值(也就是必须是内联样式才行),定义在css中的样式不能通过这种方式获取. 让元素移动到200停止 setTim ...
- 【mysql】Infobright和mysql数据入库性能测试
产生测试文件 测试文件部分内容如下: 产生测试文件代码: package foo; import java.io.File; import java.io.FileWriter; import jav ...