Reputation: 426
Using handlebars-loader, I'm looking to compile and then call the template function, so I can pass the generated HTML to other loaders, however whatever I try it seems I can only manage to get the templating function itself. For example
{
test: /\.hbs$/,
loaders: [
{
loader: 'file-loader',
options: {
name: '[name].html'
}
},
'extract-loader',
'html-loader',
'handlebars-loader'
],
enforce: 'pre'
},
Would be great, generate HTML, pass it through html-loader to get webpack's require goodness, and then extract the HTML to it's own files (example based on Webpacks html-loader documentation). However, if for example I run index.hbs into this, the output into index.html is
var Handlebars = require("<dir>/node_modules/handlebars/runtime.js");
function __default(obj) { return obj && (obj.__esModule ? obj["default"] : obj); }
module.exports = (Handlebars["default"] || Handlebars).template({"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
var stack1;
return ((stack1 = container.invokePartial(require("<dir>/src/pages/partials/head.hbs"),depth0,{"name":"head","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
+ "<main>\n<p>"
+ container.escapeExpression(container.lambda((depth0 != null ? depth0.formatMessage : depth0), depth0))
+ "</p>\n</main>\n"
+ ((stack1 = container.invokePartial(require("<dir>/src/pages/partials/content-info.hbs"),depth0,{"name":"content-info","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
},"usePartial":true,"useData":true});
Note that I am also using babel-loader to load a file, which calls require(./index.hbs)
.
What I'd like to get is a normal HTML file, not the Handlebars function
Any suggestion for a direction to investigate would be great!
Upvotes: 1
Views: 4484
Reputation: 609
Solved a similar problem using two separate build config:
new HandlebarsPlugin({
// path to hbs entry file(s). Also supports nested directories if write path.join(process.cwd(), "app", "src", "**", "*.hbs"),
entry: path.join(process.cwd(), "handlebars", "*.hbs"),
// output path and filename(s). This should lie within the webpacks output-folder
// if ommited, the input filepath stripped of its extension will be used
output: path.join(process.cwd(), "html", "[name].html"),
// you can also add a [path] variable, which will emit the files with their relative path, like
// output: path.join(process.cwd(), "build", [path], "[name].html"),
// globbed path to partials, where folder/filename is unique
partials: [
path.join(process.cwd(), "handlebars", "partials", "**", "*.hbs")
],
})
module.exports = {
module: {
rules: [
{
test: /\.html$/i,
loader: 'html-loader',
include: [
path.resolve(__dirname, "html"),
],
},
{
test: /\.css$/i,
type: 'asset/resource',
include: [
path.resolve(__dirname, "css"),
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'html/index.html',
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
};
Upvotes: 1
Reputation: 2622
If I read your question correctly, you want to combine handlebars-loader
HTML processing together with html-loader
ability to detect dependencies from the HTML file.
The point is that handlebars need to be evaluated in a context, since it references external variables. That's why extracting content and using a file loader won't work; you need an intermediate loader or plugin that renders the handlebars.
You could require the HBS template file in your JS file, and then evaluate it there, as it's done in Handlebars Loader examples, but then again you don't have a file.
What I think is close to what you want, is to use the handlebars files as a templates for HTML Webpack Plugin. You could use an HTML Loader followed by Extract Loader and then Handlebars Loader, but you would be feeding handlebars entities to the HTML Loader, which is not very stable I suppose. Luckily, there is a plugin that combines the three, Handlebars Template Loader (npm install --save-dev handlebars handlebars-template-loader
) and you can set it up as follows:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
hash: false,
inject: false,
template: './src/index.hbs',
}),
// ...
],
module: {
{
test: /\.hbs$/,
use: ['handlebars-template-loader'],
},
// ...
]
}
};
Now the HTML Webpack plugin will request the HBS file, which will be loaded through the Handlebars Template Loader, which will parse the HTML file and detect further dependencies, and then rendered in context by the HTML Webpack Plugin.
Upvotes: 2