Dans la documentation html-loader il y a cet exemple
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>
D'où vient la "liste"? Comment puis-je fournir des paramètres à l'étendue d'interpolation?
Je voudrais faire quelque chose comme template-string-loader fait:
var template = require("html?interpolate!./file.html")({data: '123'});
puis dans file.html
<div>${scope.data}</div>
Mais ça ne marche pas. J'ai essayé de mélanger le template-string-loader avec le html-loader mais cela ne fonctionne pas. Je n'ai pu utiliser que le template-string-loader mais les images dans le HTML ne sont pas transformées par webpack.
Des idées? Je vous remercie
J'ai trouvé une autre solution en utilisant html-loader
avec l'option interpolate
.
https://github.com/webpack-contrib/html-loader#interpolation
{ test: /\.(html)$/,
include: path.join(__dirname, 'src/views'),
use: {
loader: 'html-loader',
options: {
interpolate: true
}
}
}
Et puis dans la page html, vous pouvez importer des variables partielles html et 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>
Le seul inconvénient est que vous ne pouvez pas importer d'autres variables de HtmlWebpackPlugin
comme ceci <%= htmlWebpackPlugin.options.title %>
(au moins je ne trouve pas de moyen de les importer) mais pour moi ce n'est pas un problème, écrivez simplement le titre dans votre html ou utilisez un fichier javascript séparé pour gérer les variables.
Ancienne réponse
Je ne sais pas si c'est la bonne solution pour vous, mais je vais partager mon flux de travail (testé dans Webpack 3).
Au lieu de html-loader
vous pouvez utiliser ce plugin github.com/bazilio91/ejs-compiled-loader :
{ test: /\.ejs$/, use: 'ejs-compiled-loader' }
Change ton .html
fichiers dans .ejs
et votre HtmlWebpackPlugin
pour pointer vers la droite .ejs
modèle:
new HtmlWebpackPlugin({
template: 'src/views/index.ejs',
filename: 'index.html',
title: 'Home',
chunks: ['index']
})
Vous pouvez importer des partiels, des variables et des actifs dans .ejs
des dossiers:
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>
Remarque: lorsque vous incluez un partiel, le chemin doit être relatif à la racine de votre projet.
moustache-chargeur a fait le travail pour moi:
var html = require('mustache-loader!html-loader?interpolate!./index.html')({foo:'bar'});
Ensuite, dans votre modèle, vous pouvez utiliser {{foo}}
, et même insérer d'autres modèles
<h1>{{foo}}</h1>
${require('mustache-loader!html-loader?interpolate!./partial.html')({foo2: 'bar2'})}
Vous pourriez rire, mais en utilisant les chargeurs par défaut fournis avec HTMLWebpackPlugin, vous pouvez effectuer un remplacement de chaîne sur le fichier HTML partiel.
Utilisez simplement le modèle ejs par défaut fourni dans HTMLWebpackPlugin
new HtmlWebpackPlugin({
template: 'src/views/index.ejs',
filename: 'index.html',
title: 'Home',
chunks: ['index'],
templateParameters(compilation, assets, options) {
return {
foo: 'bar'
}
}
})
Voici mon fichier ejs de niveau supérieur
// 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>
Voici file.html, qui html-loader
exporte sous forme de chaîne.
// file.html
<h1>${foo}</h1>
si vous utilisez le moteur de modèle de htmlWebpackPlugin
en partie, vous pouvez utiliser comme ceci:
<!-- 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,
}),
],
}
avoir besoin npm i ejs-loader
En utilisant html-loader
Avec interpolate
, vous pouvez importer des variables depuis votre webpack.config.js
En utilisant 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>
Les interpolations de html-loader
Acceptent toute expression JavaScript, mais la portée dans laquelle ces expressions sont évaluées n'est remplie par aucune de vos options de configuration par défaut. DefinePlugin
ajoute des valeurs à cette portée globale. EnvironmentPlugin
peut également être utilisé pour remplir des valeurs dans process.env
.
Vous pouvez le faire vous-même: dans le dossier du plugin html-loader (dans index.js), remplacez le code par ce
/*
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) + ') + ';
}) + "};";
}
Je pense que Potench's 's answer ci-dessus devrait être accepté, mais il est accompagné d'une mise en garde:
Avertissement: la réponse remplace htmlWebpackPlugin.options
objet par défaut. Suggérer d'augmenter, pas de remplacer
function templateParametersGenerator (compilation, assets, options) {
return {
compilation: compilation,
webpack: compilation.getStats().toJson(),
webpackConfig: compilation.options,
htmlWebpackPlugin: {
files: assets,
options: options,
// your extra parameters here
}
};
}
Source (s): 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