html-plugin-webpack模板内容高度定制化
使用html-plugin-webpack时一般都会设置template
属性配置html模板。 但这存在缺点: 在团队拥有多个项目时, html格式的模板内容无法做到通用功能的统一和针对特定项目的扩展。所以如果将模板内容的配置为js内容,获取js的完全编码能力, 既可以封装团队中项目通用模板内容, 有保证较高的定制能力.
本文中使用的是 html-plugin-webpack版本是v3版本。v4版本支持更多的选项支持本文的内容,而不是通过插件实现。下文就以html模板中常用改用为js代码怎么配置.
页面标题
如果不配置html-webpack-plugin的
template
选项, 配置title
选项时, 生成的html文件中将会有标题:module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
title: '测试',
}),
],
};
生成的文件中:
测试 - 锐客网
图标
设置
favicon
选项, html-plugin-webpack会自动将图片文件复制到output
目录下, 然后使用, 会自动添加上publicPath
.module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
favicon: './build/favicon.ico',
}),
],
};
生成的html代码中:
对于移动端应用, 图标配置推荐使用 favicons-webpack-plugin.设置meta信息
html文件中通常需要设置许多
meta
信息, 通过html-webpack-html的meta
选项, 可以生成这些meta信息, 如:module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
meta: {
author: 'xxx前端团队',
},
}),
],
};
如果需要配置
http-equiv
相关, 需要以下语法:{
meta: {
pragma: { 'http-equiv': 'pragma', 'content': 'no-cache' },
},
}
如果需要对同一个
http-equiv
属性设置多次值, 需要为:{
meta: {
cacheControl1: { 'http-equiv': 'cache-control', content: 'no-cache' },
cacheControl2: { 'http-equiv': 'cache-control', content: 'no-siteapp' },
cacheControl3: { 'http-equiv': 'cache-control', content: 'no-transform' },
},
}
一个较完整的配置:
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
meta: {
author: 'xxx前端团队',
cacheControl1: { 'http-equiv': 'cache-control', content: 'no-cache' },
cacheControl2: { 'http-equiv': 'cache-control', content: 'no-siteapp' },
cacheControl3: { 'http-equiv': 'cache-control', content: 'no-transform' },
expires: { 'http-equiv': 'expires', content: '0' },
compatible: { 'http-equiv': 'X-UA-Compatible', content: 'IE=edge,chrome=1' },
},
}),
],
};
生成的html代码:
额外的资源
html中通常需要一些额外的资源, 如一些库(jquery, vue)全局提供, 一些
polyfill
资源等,推荐使用html-webpack-tags-plugin)来处理。html-webpack-tags-plugin只是在模板中添加一些额外的资源标签, 不会对目标资源文件做任何其他操作,需要配合copy-webpack-plugin一起使用, copy-webpack-plugin能够把额外的资源文件(可能在node_modules中)复制到webpack配置中的
output
目录下.这里以导入的谷歌分析文件为例, 假如在项目根目录下有谷歌分析单页面应用插件
autotrack
:|--assets
|--autotrack.min.js
|--autotrack.min.js.map
配置:
module.exports = {
// ...
output: {
// ...
path: path.resolve(__dirname, 'dist')
},plugins: [
// 需要开启HtmlWebpackPlugin插件
new HtmlWebpackPlugin({
title: '测试',
}),
new CopyWebpackPlugin([{
from: './assets',
to: './dist',
toType: 'dir',
}]),
new HtmlWebpackTagsPlugin({
tags: [{
path: 'autotrack/autotrack.js',
attributes: {
async: 'true',
},
}],
scripts: [{
path: 'https://www.google-analytics.com/analytics.js',
attributes: {
type: 'text/javascript',
async: 'true',
},
append: false,
}],
}),
],
};
生成的dist目录:
|--dist
|--autotrack
|--autotrack.min.js
|--autotrack.min.js.map
|--bundle.js
|--index.html
html
代码内容:
测试 - 锐客网
两外也可以使用html-webpack-tags-plugin的增强库 html-webpack-deploy-plugin内联js代码或者其他直接在html中引用的js代码
实际开发过程中通常还需要在
html
文件中包含一些内联的js代码或者引用第三方代码, 如配置谷歌分析调用的代码。可以使用webpack-concat-plugin:))进行额外的js资源的导入。
webpack-concat-plugin比html-webpack-tags-plugin的好处是支持对导入的js文件进行压缩.webpack-concat-plugin对于目标js资源, 会自动复制到当前webpack配置
output
目录下, 所以不需要配合[copy-webpack-plugin]使用.假如需要在单页面应用的
index.html
导入google-analytics-starter.js
内容:;
((function(){
window.ga = window.ga || function () { (ga.q = ga.q || []).push(arguments) };
ga.l = +new Date;
ga('create', 'UA-63187412-4', 'auto');
ga('require', 'eventTracker');
ga('require', 'outboundLinkTracker');
ga('require', 'urlChangeTracker');
ga('send', 'pageview');
})());
此时需要在webpack配置:
module.exports = {
// ...
output: {
// ...
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
title: '测试',
}),new WebpackConcatPlugin({
uglify: false,
sourceMap: false,
name: 'google-analytics-starter',
outputPath: 'static',
fileName: '[name].[hash:8].js',
filesToConcat: [path.resolve(__dirname, './google-analytics-starter.js')],
}),
],
};
生成的html:
测试 - 锐客网
对于内联代码, 建议抽取为一个一个js文件, 通过webpack-concat-plugin引用外链.对于可能造成的资源请求过多, webpack-concat-plugin可以配置
filesToConcat
为一个目录(多个目录也行), 会整体打成一个包.其他逻辑追加
在html模板中, 通常还需要设置一些其他的内容, 比如供渲染框架挂载的dom元素.
这种框架暂时还未在社区找到, 不过可以编写一个简单的html-plugin-webpack插件实现:
const _ = require('lodash');
function resetOptionToFn(option) {
if (_.isArray(option)) {
return (tags) => {
tags.push(...option);
};
}
if (_.isPlainObject(option)) {
if (option.before || option.after) {
return (tags) => {
tags.unshift(...[].concat(option.before || []));
tags.push(...[].concat(option.after || []));
};
}
return (tags) => {
tags.push(option);
};
}
return () => {};
}module.exports = class HtmlCodePlugin {
constructor({
body,
head,
} = {}) {
this.body = resetOptionToFn(body);
this.head = resetOptionToFn(head);
}apply(_compiler) {
const compiler = _compiler;
compiler.hooks.compilation.tap(this.constructor.name, (compilation) => {
compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync(this.constructor.name, async (data, cb) => {
try {
this.body(data.body);
this.head(data.head);
cb(null, data);
} catch (error) {
cb(error, null);
}
});
});
}
};
然后就可以在webpack中配置:
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
title: '测试',
}),
new MyPlugin({
body: {
tagName: 'div',
selfClosingTag: false,
voidTag: false,
attributes: {
id: 'app',
},
},
}),
],
};
生成的html代码:
测试 - 锐客网
对于其他的如注释代码, HTML中IE判断语句
if !IE
都可以实现类似html-webpack-plugin的插件。案例代码中已经发布了一个可以使用的npm库: webpack-plugin-html-append-tag。写在最后
上文中列举了许多html模板中的内容怎么用js去配置, 这对使用统一构建工具构建多个项目的团队非常有用. 利用js的编程能力, 可以把团队通用的模板配置内容封装在构建工具内, 并提供对项目中对模板内容定制提供api, 提供封装和扩展能力.
【html-plugin-webpack模板内容高度定制化】由于当时在开发时,html-plugin-webpack@3还不支持更多的内容定制,只能通过插件去实现。但随着v4版本的到来,很多内容已经通过配置属性即可支持,无需像本文一样使用一些插件来支持。
推荐阅读
- opencv|opencv C++模板匹配的简单实现
- web网页模板|如此优秀的JS轮播图,写完老师都沉默了
- Filecoin挖矿投资报告
- 联机共读11期-6.2-汤亚萍|联机共读11期-6.2-汤亚萍 “好的内容+多的流量=知名的品牌”
- Python专栏|数据分析的常规流程
- 内容平台做电商的三个优势
- 误删/清空.bashrc文件/内容
- 通过复盘快速成长(附模板)
- 1-Java基础知识
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍