I'm trying to register a partial, which according to the docs should be done like this:
var partialString = fs.readFileSync(filename), {encoding: 'utf8'})
var compiledPartial = handlebars.precompile(partialString)
var template = handlebars.template(compiledPartial)
handlebars.registerPartial('stuff', template)
However the .template()
method produces this error:
Error: Unknown template object: string
I can see that the compiledPartial
above is indeed a string that looks like an object:
{"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
return "<div>Stuff</div>\n";
},"useData":true}
WTF?
Node 0.10.25, Handlebars 2.0.0
The precompiler
method is intended for serializing the template and then the template
method is used to restore it on the client. If you are trying to evaluate the template in the same process then you should use Handlebars.compile
directly.
Thanks for the answer. It seems the docs are more geared towards using Handlebars in the client side, since it is possible to pass just the uncompiled partial string to the registerPartial()
method, if you're only using Handlebars on the server side.
I am writing a server-side application that needs to be able to both precompile templates (and then deliver them to the client in case they need to be re-rendered with new context) and also render them to HTML (for less noticeable flicker/delay on the client + improved SEO). It seems I either need to call both precompile
and compile
separately or I need to eval
the serialized precompiler output. Neither of those approaches feels very elegant, so am I missing something or is my application just unusual? (BTW, this application is written in Java but using the built-in [Rhino/Nashorn] JavaScript engine for the templating portion; hopefully that doesn't matter.)
In case anyone else got confused by the documentation for precompile and wound up here, I've written an example to illustrate what is going on. (Actually, I wrote it because I was trying to figure it out what I was doing wrong.)
var templateSources = {
hi: "Hi, {{name}}.",
bye: "Goodbye, {{name}}."
};
var compiledTemplates = {};
var serializedTemplates = {};
var deserializedTemplates = {};
Object.keys(templateSources).forEach(function(name) {
// Use compile method to generate actual executable template (function)
compiledTemplates[name] = Handlebars.compile(templateSources[name]);
// Use precompile method to generate serialized JS (string)
serializedTemplates[name] = Handlebars.precompile(templateSources[name]);
// If we really want, we can deserialize these
deserializedTemplates[name] = Handlebars.template(evalPrecompiledTemplate(serializedTemplates[name]));
});
// (Yes, I know eval is dangerous)
function evalPrecompiledTemplate(s) {
return eval("(function(){return " + s + "}());");
}
// Quick demonstration that these template functions work the same
var context = {
name: "John Smith"
};
// Output:
// Rendering template named hi with context: Object {name: "John Smith"}
// Hi, John Smith.(compiled)
// Hi, John Smith.(precompiled/deserialized)
// Rendering template named bye with context: Object {name: "John Smith"}
// Goodbye, John Smith.(compiled)
// Goodbye, John Smith.(precompiled/deserialized)
Object.keys(templateSources).forEach(function(name) {
console.log("Rendering template named " + name + " with context:", context);
console.log(compiledTemplates[name](context) + "(compiled)");
console.log(deserializedTemplates[name](context) + "(precompiled/deserialized)");
});
@jacobq you'll want to call compile and precompile. The generated code for the two is very different and I wouldn't presume that trying to toString or similar will work with the compile output, etc.
Most helpful comment
I am writing a server-side application that needs to be able to both precompile templates (and then deliver them to the client in case they need to be re-rendered with new context) and also render them to HTML (for less noticeable flicker/delay on the client + improved SEO). It seems I either need to call both
precompile
andcompile
separately or I need toeval
the serialized precompiler output. Neither of those approaches feels very elegant, so am I missing something or is my application just unusual? (BTW, this application is written in Java but using the built-in [Rhino/Nashorn] JavaScript engine for the templating portion; hopefully that doesn't matter.)In case anyone else got confused by the documentation for precompile and wound up here, I've written an example to illustrate what is going on. (Actually, I wrote it because I was trying to figure it out what I was doing wrong.)