Reputation: 487
Everything works fine when I use ejs-loader
and html-loader
separately:
<body>
<%= require('./header.html')({x:1}) %>
</body>
// compiles to:
<body>
<header><div>1</div></header>
</body>
But when I chain them, I'm getting js code instead of html:
module.exports = function (obj) {
obj || (obj = {});
var __t, __p = '';
with (obj) {
__p += '\n<body>\n ' +
((__t = ( require('./header.html')({x:1}) )) == null ? '' : __t) +
'\n</body>';
}
return __p
}
What is happening and how can I fix it?
Here is my config:
const config = {
//...
module: {
rules: [
{
test: /\.html$/,
use: ['html-loader', 'ejs-loader']
}
]
},
//...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
})
]
}
Upvotes: 4
Views: 3282
Reputation: 360
I am now struggling with the same problem and found the answer.
First, we need to understand how loaders work. In short: they take whatever file types as input, but output from a loader is always JS, which webpack then executes to get final output.
Both ejs-loader and html-loader expect html code as their input. When we chain loaders, the second loader receives not HTML, but javascript which was returned by the first loader. So we need to make HTML from that JS. To do so I wrote a simple loader which needs to be put between html- and ejs- loader.
Let's call it 'loader.js':
module.exports = function (source) {
let x = eval(source);
let z = x();
return z;
}
Webpack config then will be:
module: {
rules: [
{
test: /\.html$/,
use: ['html-loader', path.resolve('loader.js'), 'ejs-loader']
}
]
},
Important note: The order or loaders matter. If i swap ejs and html loaders in the chain, then eval fails because html-loader returns js code which has other imports which eval cannot resolve. However ejs-loader returns pure self-contained code which evaluates with eval() successfully.
So, because loaders get executed in reverse order, we put ejs first (meaning - at the end of array), then our intermediate loader, and the html-loader goes last (at the beginning of array)
UPDATE: There is a ready-to-use loader which does this job, called extract-loader
. Simple eval
will fail in many cases while extract-loader
always works fine.
Upvotes: 5