
Server-side template rendering using Handlebars.
npm install handlebars-webpack-plugin --save-dev
Usage
In your webpack config register and setup the handlebars plugin
const path = require("path");
const HandlebarsPlugin = require("handlebars-webpack-plugin");
const webpackConfig = {
plugins: [
new HandlebarsPlugin({
entry: path.join(process.cwd(), "app", "src", "*.hbs"),
output: path.join(process.cwd(), "build", "[name].html"),
data: require("./app/data/project.json"),
data: path.join(__dirname, "app/data/project.json"),
partials: [
path.join(process.cwd(), "app", "src", "components", "*", "*.hbs")
],
helpers: {
nameOfHbsHelper: Function.prototype,
projectHelpers: path.join(process.cwd(), "app", "helpers", "*.helper.js")
},
onBeforeSetup: function (Handlebars) {},
onBeforeAddPartials: function (Handlebars, partialsMap) {},
onBeforeCompile: function (Handlebars, templateContent) {},
onBeforeRender: function (Handlebars, data, filename) {},
onBeforeSave: function (Handlebars, resultHtml, filename) {},
onDone: function (Handlebars, filename) {}
})
]
};
Partial ids are registered by parentFolder/filename
(without file extensions)
Use handlebars in your main and partials like, i.e.
<body>
{{> partialFolder/partialName}}
{{> header/header title="page title"}}
{{> partial/content}}
</body>
Options
target filepaths
Per default, the generated filepath of the html-results is defined by the output
-property in the plugin-options. To changed the output folder and name, you can pass your custom filepath-helper to the plugin-options like
{
getTargetFilepath: function getTargetFilepath(filepath, outputTemplate, rootFolder) {
const fileName = path.basename(filepath).replace(path.extname(filepath), "");
return outputTemplate.replace("[name]", fileName);
};
}
You can find the default implementation in utils/getTargetFilepath.
partial ids
Per default, partials are identified with folder/filename
in a hbs-template. e.g. a file in app/partials/page/header.hbs
will be registered under page/header
and can be included with
{{> page/header title="page title"}}
To change the partial's id you can pass a custom partial-generator to the plugin-options like
{
getPartialId: function (filePath) {
return filePath.match(/\/([^/]+\/[^/]+)\.[^.]+$/).pop();
}
}
Html Webpack Plugin
Use the html-webpack-plugin to generate partials, that are
dynamically registered to the handlebars-webpack-plugin
- the
HtmlWebpackPlugin
should be placed before the HandlebarsWebpackPlugin - multiple HtmlWebpackPlugins may be used
- per default, the partials get registered to
html/<outputfilename>
, i.e. a filename /dist/partials/head.hbs
will be registered as html/head
to handlebars
plugins: [
new HtmlWebpackPlugin({
title: "Generic Head Title",
template: path.join(__dirname, "src", "generatedpartial", "head.hbs"),
filename: path.join(__dirname, "dist", "partials", "head.hbs"),
inject: "head"
}),
new HandlebarsWebpackPlugin({
htmlWebpackPlugin: {
enabled: true,
prefix: "html",
HtmlWebpackPlugin
},
entry: path.join(process.cwd(), "src", "hbs", "*.hbs"),
output: path.join(process.cwd(), "dist", "[name].html"),
partials: [
path.join(process.cwd(), "html", "*", "*.hbs"),
path.join(process.cwd(), "src", "hbs", "*", "*.hbs")
]
})
]
Utilities
Merging input-data
In case you have several json-files that need to be passed to handlebars-compilation, you can build this within your webpack-configuration file. A simple helper can be found in utils/mergeJSON.js,
which finds all json files and build a dataObject with { <filename>: <data> }
. Example:
const mergeJSON = require('handlebars-webpack-plugin/utils/mergeJSON');
const projectData = mergeJSON(path.join(__dirname, "data/**/*.json"));
new HandlebarsPlugin({
data: projectData
});
For custom merge behaviour you can add your own merge-helper, following the implementation from utils/mergeJSON.js.
Contributors