在html-loader文档中有这个例子
require("html?interpolate=require!./file.ftl");
<#list list as list>
<a href="${list.href!}" />${list.name}</a>
</#list>
<img src="${require(`./images/gallery.png`)}">
<div>${require('./components/gallery.html')}</div>
“名单”来自哪里?如何为插值范围提供参数?
我想做template-string-loader之类的事情:
var template = require("html?interpolate!./file.html")({data: '123'});
然后在file.html中
<div>${scope.data}</div>
但它不起作用。我试图将模板字符串加载器与html-loader混合,但它不起作用。我只能使用template-string-loader,但HTML中的图像不会被webpack转换。
有什么想法吗?谢谢
答案 0 :(得分:6)
我找到了另一个解决方案,使用html-loader
interpolate
选项。
https://github.com/webpack-contrib/html-loader#interpolation
{ test: /\.(html)$/,
include: path.join(__dirname, 'src/views'),
use: {
loader: 'html-loader',
options: {
interpolate: true
}
}
}
然后在html页面中你可以导入部分html和javascript变量。
<!-- Importing top <head> section -->
${require('./partials/top.html')}
<title>Home</title>
</head>
<body>
<!-- Importing navbar -->
${require('./partials/nav.html')}
<!-- Importing variable from javascript file -->
<h1>${require('../js/html-variables.js').hello}</h1>
<!-- Importing footer -->
${require('./partials/footer.html')}
</body>
唯一的缺点是你不能像HtmlWebpackPlugin
那样从<%= htmlWebpackPlugin.options.title %>
导入其他变量(至少我找不到导入它们的方法)但是对我来说它和&#0}} #39;不是问题,只需在你的html中写标题或使用单独的javascript文件来处理变量。
旧答案
不确定这是否适合您,但我会分享我的工作流程(在Webpack 3中测试)。
您可以使用此插件github.com/bazilio91/ejs-compiled-loader代替html-loader
:
{ test: /\.ejs$/, use: 'ejs-compiled-loader' }
将.html
和.ejs
中的HtmlWebpackPlugin
文件更改为指向右侧.ejs
模板:
new HtmlWebpackPlugin({
template: 'src/views/index.ejs',
filename: 'index.html',
title: 'Home',
chunks: ['index']
})
您可以在.ejs
个文件中导入部分,变量和资源:
src/views/partials/head.ejs
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
src/js/ejs_variables.js
:
const hello = 'Hello!';
const bye = 'Bye!';
export {hello, bye}
src/views/index.ejs
:
<% include src/views/partials/head.ejs %>
<body>
<h2><%= require("../js/ejs_variables.js").hello %></h2>
<img src=<%= require("../../assets/sample_image.jpg") %> />
<h2><%= require("../js/ejs_variables.js").bye %></h2>
</body>
注意,当您包含部分路径时,路径必须相对于项目的根目录。
答案 1 :(得分:2)
mustache-loader为我做了工作:
var html = require('mustache-loader!html-loader?interpolate!./index.html')({foo:'bar'});
然后在您的模板中,您可以使用{{foo}}
,甚至可以插入其他模板
<h1>{{foo}}</h1>
${require('mustache-loader!html-loader?interpolate!./partial.html')({foo2: 'bar2'})}
答案 2 :(得分:1)
如果您部分使用htmlWebpackPlugin
中的模板引擎,则可以这样使用:
<!-- index.html -->
<body>
<div id="app"></div>
<%= require('ejs-loader!./partial.gtm.html')({ htmlWebpackPlugin }) %>
</body>
<!-- partial.gtm.html -->
<% if (GTM_TOKEN) { %>
<noscript>
<iframe
src="https://www.googletagmanager.com/ns.html?id=<%= GTM_TOKEN %>"
height="0"
width="0"
style="display:none;visibility:hidden"
></iframe>
</noscript>
<% } %>
// webpack.config.json
{
plugins: [
new webpack.DefinePlugin({
GTM_TOKEN: process.env.GTM_TOKEN,
}),
],
}
需要npm i ejs-loader
答案 3 :(得分:1)
将html-loader
与interpolate
配合使用,您可以使用webpack.config.js
从DefinePlugin
导入变量。
// webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.html$/,
loader: 'html-loader',
options: {
interpolate: true
}
}
],
},
plugins: [
new DefinePlugin({
VARNAME: JSON.stringify("here's a value!")
})
]
};
// index.html
<body>${ VARNAME }</body>
html-loader
的插值可以接受任何JavaScript表达式,但是默认情况下,不会使用您的任何配置选项来填充这些表达式的求值范围。 DefinePlugin
将值添加到该全局范围。 EnvironmentPlugin
也可用于填充process.env
中的值。
答案 4 :(得分:0)
您可能会笑,但是使用HTMLWebpackPlugin随附的默认加载程序,可以对HTML部分文件进行字符串替换。
只需使用HTMLWebpackPlugin中提供的默认ejs模板
new HtmlWebpackPlugin({
template: 'src/views/index.ejs',
filename: 'index.html',
title: 'Home',
chunks: ['index'],
templateParameters(compilation, assets, options) {
return {
foo: 'bar'
}
}
})
这是我的顶级ejs文件
// index.html
<html lang="en" dir="ltr">
<head>
<title><%=foo%></title>
</head>
<body>
<%
var template = require("html-loader!./file.html");
%>
<%= template.replace('${foo}',foo); %>
</body>
</html>
这是file.html,html-loader
导出为字符串。
// file.html
<h1>${foo}</h1>
答案 5 :(得分:0)
我认为上面的Potench's的answer应该是可以接受的,但是需要注意的是:
警告::答案将替换htmlWebpackPlugin.options
默认对象。建议增加而不是替换
function templateParametersGenerator (compilation, assets, options) {
return {
compilation: compilation,
webpack: compilation.getStats().toJson(),
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: options,
// your extra parameters here
}
};
}
来源: 1-https://github.com/jantimon/html-webpack-plugin/blob/8440e4e3af94ae5dced4901a13001c0628b9af87/index.js#L719-L729 2-https://github.com/jantimon/html-webpack-plugin/issues/1004#issuecomment-411311939
答案 6 :(得分:0)
您可以自己制作: 在html-loader插件文件夹(在index.js中)中,用此代码替换
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
var htmlMinifier = require("html-minifier");
var attrParse = require("./lib/attributesParser");
var loaderUtils = require("loader-utils");
var url = require("url");
var assign = require("object-assign");
var compile = require("es6-templates").compile;
function randomIdent() {
return "xxxHTMLLINKxxx" + Math.random() + Math.random() + "xxx";
}
function getLoaderConfig(context) {
var query = loaderUtils.getOptions(context) || {};
var configKey = query.config || 'htmlLoader';
var config = context.options && context.options.hasOwnProperty(configKey) ? context.options[configKey] : {};
delete query.config;
return assign(query, config);
}
module.exports = function(content) {
this.cacheable && this.cacheable();
var config = getLoaderConfig(this);
var attributes = ["img:src"];
if(config.attrs !== undefined) {
if(typeof config.attrs === "string")
attributes = config.attrs.split(" ");
else if(Array.isArray(config.attrs))
attributes = config.attrs;
else if(config.attrs === false)
attributes = [];
else
throw new Error("Invalid value to config parameter attrs");
}
var root = config.root;
var links = attrParse(content, function(tag, attr) {
var res = attributes.find(function(a) {
if (a.charAt(0) === ':') {
return attr === a.slice(1);
} else {
return (tag + ":" + attr) === a;
}
});
return !!res;
});
links.reverse();
var data = {};
content = [content];
links.forEach(function(link) {
if(!loaderUtils.isUrlRequest(link.value, root)) return;
if (link.value.indexOf('mailto:') > -1 ) return;
var uri = url.parse(link.value);
if (uri.hash !== null && uri.hash !== undefined) {
uri.hash = null;
link.value = uri.format();
link.length = link.value.length;
}
do {
var ident = randomIdent();
} while(data[ident]);
data[ident] = link.value;
var x = content.pop();
content.push(x.substr(link.start + link.length));
content.push(ident);
content.push(x.substr(0, link.start));
});
content.reverse();
content = content.join("");
if (config.interpolate === 'require'){
var reg = /\$\{require\([^)]*\)\}/g;
var result;
var reqList = [];
while(result = reg.exec(content)){
reqList.push({
length : result[0].length,
start : result.index,
value : result[0]
})
}
reqList.reverse();
content = [content];
reqList.forEach(function(link) {
var x = content.pop();
do {
var ident = randomIdent();
} while(data[ident]);
data[ident] = link.value.substring(11,link.length - 3)
content.push(x.substr(link.start + link.length));
content.push(ident);
content.push(x.substr(0, link.start));
});
content.reverse();
content = content.join("");
}
if(typeof config.minimize === "boolean" ? config.minimize : this.minimize) {
var minimizeOptions = assign({}, config);
[
"removeComments",
"removeCommentsFromCDATA",
"removeCDATASectionsFromCDATA",
"collapseWhitespace",
"conservativeCollapse",
"removeAttributeQuotes",
"useShortDoctype",
"keepClosingSlash",
"minifyJS",
"minifyCSS",
"removeScriptTypeAttributes",
"removeStyleTypeAttributes",
].forEach(function(name) {
if(typeof minimizeOptions[name] === "undefined") {
minimizeOptions[name] = true;
}
});
content = htmlMinifier.minify(content, minimizeOptions);
}
if(config.interpolate && config.interpolate !== 'require') {
// Double escape quotes so that they are not unescaped completely in the template string
content = content.replace(/\\"/g, "\\\\\"");
content = content.replace(/\\'/g, "\\\\\'");
content = JSON.stringify(content);
content = '`' + content.substring(1, content.length - 1) + '`';
//content = compile('`' + content + '`').code;
} else {
content = JSON.stringify(content);
}
var exportsString = "module.exports = function({...data}){return ";
if (config.exportAsDefault) {
exportsString = "exports.default = function({...data}){return ";
} else if (config.exportAsEs6Default) {
exportsString = "export default function({...data}){return ";
}
return exportsString + content.replace(/xxxHTMLLINKxxx[0-9\.]+xxx/g, function(match) {
if(!data[match]) return match;
var urlToRequest;
if (config.interpolate === 'require') {
urlToRequest = data[match];
} else {
urlToRequest = loaderUtils.urlToRequest(data[match], root);
}
return ' + require(' + JSON.stringify(urlToRequest) + ') + ';
}) + "};";
}