引言

我们来看看主要作用:

为html文件中引入的外部资源如scriptlink动态添加每次compile后的hash,防止引用缓存的外部文件问题

可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置Nhtml-webpack-plugin可以生成N个页面入口

html-webpack-plugin

插件的基本作用就是生成html文件。原理很简单:

将 webpack中`entry`配置的相关入口chunk  和  `extract-text-webpack-plugin`抽取的css样式   插入到该插件提供的`template`或者`templateContent`配置项指定的内容基础上生成一个html文件,具体插入方式是将样式`link`插入到`head`元素中,`script`插入到`head`或者`body`中。

实例化该插件时可以不配置任何参数,例如下面这样:

var HtmlWebpackPlugin = require('html-webpack-plugin')
webpackconfig = {
plugins: [
new HtmlWebpackPlugin()
]
}

  

不配置任何选项的html-webpack-plugin插件,他会默认将webpack中的entry配置所有入口thunk和extract-text-webpack-plugin抽取的css样式都插入到文件指定的位置。例如上面生成的html文件内容如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
<link href="index-af150e90583a89775c77.css" rel="stylesheet"></head>
<body>
<script type="text/javascript" src="common-26a14e7d42a7c7bbc4c2.js"></script>
<script type="text/javascript" src="index-af150e90583a89775c77.js"></script></body>
</html>

  

当然可以使用具体的配置项来定制化一些特殊的需求,那么插件有哪些配置项呢?

html-webpack-plugin配置项

插件提供的配置项比较多,通过源码可以看出具体的配置项如下:

 this.options = _.extend({
template: path.join(__dirname, 'default_index.ejs'),
templateParameters: templateParametersGenerator,
filename: 'index.html',
hash: false,
inject: true,
compile: true,
favicon: false,
minify: false,
cache: true,
showErrors: true,
chunks: 'all',
excludeChunks: [],
chunksSortMode: 'auto',
meta: {},
title: 'Webpack App',
xhtml: false
}, options);
title: 生成的html文档的标题。配置该项,它并不会替换指定模板文件中的title元素的内容,除非html模板文件中使用了模板引擎语法来获取该配置项值,如下ejs模板语法形式:
<title>{%= o.htmlWebpackPlugin.options.title %}</title>

filename:输出文件的文件名称,默认为index.html,不配置就是该文件名;此外,还可以为输出文件指定目录位置(例如'html/index.html')

关于filename补充两点:

1、filename配置的html文件目录是相对于webpackConfig.output.path路径而言的,不是相对于当前项目目录结构的。
2、指定生成的html文件内容中的linkscript路径是相对于生成目录下的,写路径的时候请写生成目录下的相对路径。

template: 本地模板文件的位置,支持加载器(如handlebars、ejs、undersore、html等),如比如 handlebars!src/index.hbs

关于template补充几点:

1、template配置项在html文件使用file-loader时,其所指定的位置找不到,导致生成的html文件内容不是期望的内容。
2、为template指定的模板文件没有指定任何loader的话,默认使用ejs-loader。如template:
'./index.html'
,若没有为.html指定任何loader就使用ejs-loader

templateContent:
string|function,可以指定模板的内容,不能与template共存。配置值为function时,可以直接返回html字符串,也可以异步调用返回html字符串。

inject:向template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同。

1、true或者body:所有JavaScript资源插入到body元素的底部
2、head:
所有JavaScript资源插入到head元素中
3、false: 所有静态资源css和JavaScript都不会注入到模板文件中

favicon: 添加特定favicon路径到输出的html文档中,这个同title配置项,需要在模板中动态获取其路径值

hash:true|false,是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值,添加hash形式如下所示:
html <script
type="text/javascript"
src="common.js?a3e1396b501cdd9041be"></script>

chunks:允许插入到模板中的一些chunk,不配置此项默认会将entry中所有的thunk注入到模板中。在配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk;

excludeChunks: 这个与chunks配置项正好相反,用来配置不允许注入的thunk。

chunksSortMode: none |
auto| function,默认auto; 允许指定的thunk在插入到html文档前进行排序。
>function值可以指定具体排序规则;auto基于thunk的id进行排序; none就是不排序

xhtml: true|fasle, 默认false;是否渲染link为自闭合的标签,true则为自闭合标签

cache: true|fasle, 默认true; 如果为true表示在对应的thunk文件修改后就会emit文件

showErrors:
true|false,默认true;是否将错误信息输出到html页面中。这个很有用,在生成html文件的过程中有错误信息,输出到页面就能看到错误相关信息便于调试。

minify:
{....}|false;传递
html-minifier 选项给 minify 输出,false就是不使用html压缩,minify具体配置参数请点击html-minifier

下面的是一个用于配置这些属性的一个例子:

    new HtmlWebpackPlugin({
title:'rd平台',
template: 'src/index.html', // 源模板文件
filename: './index.html', // 输出文件【注意:这里的根路径是module.exports.output.path】
showErrors: true,
inject: 'body',
chunks: ["common",'index']
})

  

配置多个html页面

html-webpack-plugin的一个实例生成一个html文件,如果单页应用中需要多个页面入口,或者多页应用时配置多个html时,那么就需要实例化该插件多次;

即有几个页面就需要在webpack的plugins数组中配置几个该插件实例:

……
plugins: [
new HtmlWebpackPlugin({
template: 'src/html/index.html',
excludeChunks: ['list', 'detail']
}),
new HtmlWebpackPlugin({
filename: 'list.html',
template: 'src/html/list.html',
thunks: ['common', 'list']
}),
new HtmlWebpackPlugin({
filename: 'detail.html',
template: 'src/html/detail.html',
thunks: ['common', 'detail']
})
]
...

  

如上例应用中配置了三个入口页面:index.html、list.html、detail.html;并且每个页面注入的thunk不尽相同;类似如果多页面应用,就需要为每个页面配置一个;

配置自定义的模板

不带参数的html-webpack-plugin默认生成的html文件只是将thunk和css样式插入到文档中,可能不能满足我们的需求;

另外,如上面所述,三个页面指定了三个不同html模板文件;在项目中,可能所有页面的模板文件可以共用一个,因为html-webpack-plugin插件支持不同的模板loader,所以结合模板引擎来共用一个模板文件有了可能。

所以,配置自定义模板就派上用场了。具体的做法,借助于模板引擎来实现,例如插件没有配置loader时默认支持的ejs模板引擎,下面就以ejs模板引擎为例来说明;

例如项目中有2个入口html页面,它们可以共用一个模板文件,利用ejs模板的语法来动态插入各自页面的thunk和css样式,代码可以这样:

<!DOCTYPE html>
<html style="font-size:20px">
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<% for (var css in htmlWebpackPlugin.files.css) { %>
<link href="<%=htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
<% } %>
</head>
<body>
<div id="app"></div>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>
</body>
</html>

  

你可能会对代码中的上下文htmlWebpackPlugin数据感到迷惑,这是啥东东?其实这是html-webpack-plugin插件在生成html文件过程中产生的数据,这些数据对html模板文件是可用的,并且我们看<%%>是不是给java里面的jsp差不多了。

自定义模板上下文数据

html-webpack-plugin在生成html文件的过程中,插件会根据配置生成一个对当前模板可用的特定数据,模板语法可以根据这些数据来动态生成html文件的内容。

那么,插件生成的特殊数据格式是什么,生成的哪些数据呢?从源码或者其官网都给出了答案。从源码中可以看出模板引擎具体可以访问的数据如下:

var templateParams = {
compilation: compilation,
webpack: compilation.getStats().toJson(),
webpackConfig: compilation.options,
htmlWebpackPlugin:
files: assets,
options: self.options
}
};

  

从中可以看出,有四个主要的对像数据。其中compilation为所有webpack插件提供的都可以访问的一个编译对象,此处就不太做介绍,具体可以自己查资料。下面就对剩下的三个对象数据进行说明。

webpack

webpack的stats对象;注意一点:

这个可以访问的stats对象是htm文件生成时所对应的stats对象,而不是webpack运行完成后所对应的整个stats对象。

webpackConfig

webpack的配置项;通过这个属性可以获取webpack的相关配置项,如通过webpackConfig.output.publicPath来获取publicPath配置。当然还可以获取其他配置内容。

htmlWebpackPlugin

html-webpack-plugin插件对应的数据。它包括两部分:

htmlWebpackPlugin.files: 此次html-webpack-plugin插件配置的chunk和抽取的css样式该files值其实是webpack的stats对象的assetsByChunkName属性代表的值,该值是插件配置的chunk块对应的按照webpackConfig.output.filename映射的值。例如对应上面配置插件各个属性配置项例子中生成的数据格式如下:

"htmlWebpackPlugin": {
"files": {
"css": [ "inex.css" ],
"js": [ "common.js", "index.js"],
"chunks": {
"common": {
"entry": "common.js",
"css": [ "index.css" ]
},
"index": {
"entry": "index.js",
"css": ["index.css"]
}
}
}
}

这样,就可以是用如下模板引擎来动态输出script脚本

<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>

  

htmlWebpackPlugin.options: 传递给插件的配置项,具体的配置项如上面插件配置项小节所描述的。

插件事件

不知道你发现没有,html-webpack-plugin插件在插入静态资源时存在一些问题:

  • 在插入js资源只能插入head或者body元素中,不能一些插入head中,另一些插入body
  • 不支持在html中文件内联*,例如在文件的某个地方用<script src="xxx.js?__inline"></script>来内联外部脚本

为此,有人专门给插件作者提问了这个问题;对此插件作者提供了插件事件,允许其他插件来改变html文件内容。具体的事件如下:

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的内容。因此,要用这些事件需要提供一个webpack插件。例如下面定义的MyPlugin插件。

function MyPlugin(options) {
// Configure your plugin with options...
} MyPlugin.prototype.apply = function(compiler) {
// ...
compiler.plugin('compilation', function(compilation) {
console.log('The compiler is starting a new compilation...'); compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
htmlPluginData.html += 'The magic footer';
callback(null, htmlPluginData);
});
}); };
module.exports = MyPlugin;

  

 

然后,在webpack.config.js文件中配置Myplugin信息:

plugins: [
new MyPlugin({options: ''})
]

  

html-webpack-plugin详解的更多相关文章

  1. vue-cli 中的 webpack 配置详解

    本篇文章主要介绍了 vue-cli 2.8.2 中的 webpack 配置详解, 做个学习笔记 版本 vue-cli 2.8.1 (终端通过 vue -V 可查看) vue 2.2.2 webpack ...

  2. webpack配置详解

    webpack配置详解 先点个赞吧,再挨个点下面的连接,觉得不值这个赞的回来骂我啊. Webpack傻瓜式指南(一) Webpack傻瓜指南(二)开发和部署技巧 Webpack傻瓜式指南 原生的官网详 ...

  3. webpack入门详解

    webpack入门详解(基于webpack 3.5.4  2017-8-22) webpack常用命令: webpack --display-error-details    //执行打包 webpa ...

  4. vue-cli中webpack配置详解

    vue-cli是构建vue单页应用的脚手架,命令行输入vue init <template-name> <project-name>从而自动生成的项目模板,比较常用的模板有we ...

  5. mysql 5.7.12 新增 X plugin 详解

     https://dev.mysql.com/doc/refman/5.7/en/document-store.html   原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息 ...

  6. Spring Boot的Maven插件Spring Boot Maven plugin详解

    Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...

  7. 10. vue之webpack打包详解

    一.什么是webpack webpack官网给出的定义是 本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应 ...

  8. 从零学脚手架(三)---webpack属性详解

    如果此篇对您有所帮助,在此求一个star.项目地址: OrcasTeam/my-cli 在上一篇中,介绍了webpack的entry.output.plugins属性. 在这一篇,接着介绍其它配置属性 ...

  9. 详解前端模块化工具-webpack

    webpack是一个module bundler,抛开博大精深的汉字问题,我们暂且管他叫'模块管理工具'.随着js能做的事情越来越多,浏览器.服务器,js似乎无处不在,这时,使日渐增多的js代码变得合 ...

  10. webpack安装配置使用教程详解

    webpack安装配置使用教程详解 www.111cn.net 更新:2015-09-01 编辑:swteen 来源:转载 本文章来为各位详细的介绍一下关于webpack安装配置使用教程吧,这篇文章对 ...

随机推荐

  1. centos6+ 安装python3.6以及pip3

    https://blog.csdn.net/weixin_42350212/article/details/83008248

  2. 移动端和PC端弹出遮罩层后,页面禁止滚动的解决方法及探究

    PC端解决方案 pc端的解决思路就是在弹出遮罩层的时候取消已经存在的滚动条,达到无法滚动的效果. 也就是说给body添加overflow:hidden属性即可,IE6.7下不会生效,需要给html增加 ...

  3. python day09

    内存空间管理 1.空间引用计数,垃圾回收机制的依据 --变量的值被引用,该值的引用计数加1 --变量解除绑定,该值的引用计数减1 --如果该值的引用计数为0,就会被自动回收 2.引用计数会出现的循环问 ...

  4. IdentityServer4实战 - JWT Issuer 详解

    一.前言 本文为系列补坑之作,拖了许久决定先把坑填完. 下文演示所用代码采用的 IdentityServer4 版本为 2.3.0,由于时间推移可能以后的版本会有一些改动,请参考查看,文末附上Demo ...

  5. Python--day11(函数的参数)

    今日主要内容 1.  函数的参数 2.  函数的嵌套调用 1.  形参与实参 1.  参数介绍: 函数为什么要有参数:因为内部的函数体需要外部的数据 怎样定义函数的参数:在定义函数阶段,函数名在后面( ...

  6. 一入OI深似海 4 —— 纪念我最后一次PJ(中)

    不知道怎么回事,直到比赛前10分钟才放我们进考场. 考场在体育馆里面,很大很壮观. 我匆匆忙忙地找到位子,屁股还没坐热,被老师告知不能带水. what?! 于是我只好把水放在统一放私人物品的地方. 电 ...

  7. Java静态代码块、构造代码块执行顺序问题

    package com.zxl.staticdemo; public class BlockTest { static { System.out.println("BlockTest静态代码 ...

  8. cordova的常用命令

    常用命令 npm install -g cordova // 加载cordovecordova create MyApp //创建一个新的文件夹cd MyApp //找到当前目录cordova pla ...

  9. mysql和mariadb备份工具xtrabackup和mariabackup(mariadb上版本必须用这个)

    简介 xtraBackup(PXB) 工具是 Percona 公司用 perl 语言开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle).Percona Server ...

  10. list遍历时删除的坑

    1.测试代码如下: public class StrTest { public static void main(String[] args) { ArrayList<String> li ...