Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading precompiled templates server side (Node JS) #955

Closed
RozzyNoder opened this issue Feb 5, 2015 · 12 comments
Closed

Loading precompiled templates server side (Node JS) #955

RozzyNoder opened this issue Feb 5, 2015 · 12 comments

Comments

@RozzyNoder
Copy link

Every time I try to load precompiled templates like below:
var compiledTemplate = handlebars.templates['hello'];
I get a cannot read property 'hello' of undefined.

whereas the compile works fine like below:
var uncompiledTemplate = handlebars.compile(template);

So what is the protocol or configuration for loading these compiled templates so they get read in from the templates directory/file ?
I checked my configuration, file names, the handlebar is version (2.0 beta) and compiler version is six.

Thanks.

@kpdecker
Copy link
Collaborator

kpdecker commented Feb 5, 2015

This isn't enough information to reproduce. Can you provide an full example of what you are trying to do?

@RozzyNoder
Copy link
Author

Sure, here we go.

var template = fs.readFileSync(“./hello.html", "utf8");
var data = {message : "Hello world!"};

var compileTemplate = handlebars.compile(template);
var finalPageHTML = compileTemplate(data);

// Simply trying to replace the last two lines above with the two below but get error

/* var preCompiledTemplate =  handlebars.templates['hello'];
    var finalPageHTML = preCompiledTemplate(data);
*/

**** hello.html ****

<html>
    <head>
        <title>Example</title>
    </head>
    <body>
        <p>Oh look, it's a message: {{message}}</p>
    </body>
</html>

I renamed the file above as hello.handlebars and compiled it to hello.js, put it in a directory called “templates” below my “js” directory.

So simply trying to load "precompiled" template to produce dynamic pages on server side.

@kpdecker
Copy link
Collaborator

kpdecker commented Feb 6, 2015

Precompiled templates need to be compiled at some point and generally are not intended for use on servers as they require additional steps to work with them. Your first version is the recommended route, although I believe you can do something like

var template = require('./hello.handlebars');

@kpdecker kpdecker closed this as completed Feb 6, 2015
@RozzyNoder
Copy link
Author

Pardon me I don't understand "Precompiled templates need to be compiled". Precompiled means they are already compiled. Right ?

Handlebar templates get compiled to a .js file and then that is filled with db data or context to generate the final page. Correct ?

So I am just trying to precompile for speed so I can dynamically generate page off course feeding them with my db data at run time on the server side for final transmission.as "text/html" to client browser.

My question simply is how to load the 'hello' template from hello.js created from hello,handlebar so I have a compiled template object ? Or say another template called "hello2" from a aggregate templates.js file containing all my compiled templates. By the way I tried require, but that does not work.

Apologize, if I being senile.

@kpdecker
Copy link
Collaborator

kpdecker commented Feb 6, 2015

Precompiled means that they are precompiled by you for your clients. They are not made available automatically to node consumers.

Your example using readFileSync is the easiest and likely the best way to load the templates, so you are on the right path there.

@ekskimn
Copy link

ekskimn commented Nov 18, 2015

@RozzyNoder Hi I'm trying to do something similar to this. Did you manage to make it work? Every time I take the outputted precompiled templates to a file and then later try to read them into a variable the json parsing fails because json technically isn't supposed to have functions in them but of course the hbs templates are functions.

I've also tried a dead simple example, one from the handlebars site itself

 var templateSpec = Handlebars.precompile('{{foo}}');
 var template = Handlebars.template(templateSpec);
 template({});

and i get an error like:
throw new _Exception2['default']('Unknown template object: ' + typeof temp
^
Error: Unknown template object: string
at Object.template (/project/node_modules/handlebars/dist/cjs/handlebars/runtime.js:48:11)
at HandlebarsEnvironment.hb.template (/project/node_modules/handlebars/dist/cjs/handlebars.runtime.js:46:20)

incidentally, this is run via gulp 3.9.0, and handlebars 3.0.3.

I would love any and all insight you might have. I'm really stuck and I need this to work very soon (like as in tomorrow)

Thanks in advance.

@xpepermint
Copy link

@kpdecker I try to achieve the same as described by @ekskimn . I generate HTML code in a loop so I guess precompiling a template would speed up the process. What do you suggest? I should also mention that I found a post somewhere (can't remember where) saying that we need to precompile templates to ensue XSS security on the server in case we need to handle templates provided by the user (user-input).

@nknapp
Copy link
Collaborator

nknapp commented Nov 26, 2015

@xpepermint if you have a loop, from what I know, it should be performant to do something like:

var template = Handlebars.compile("{{title}}\n{{text}}");
largeArray.map(function(element) {
  return template(element);
});

Just compile the template before the loop and call the compiled function inside the loop.

@xpepermint
Copy link

@nknapp thx

@sido420
Copy link

sido420 commented Feb 18, 2018

Did anyone manage to use precompiled templates server side?

@ldgarcia
Copy link

ldgarcia commented Apr 29, 2018

@sido420

I also wanted to use precompiled templates server side.

I am using a lambda function to send emails with HTML content, so I wanted to minimize my function's execution time and package size (handlebars/runtime is smaller) as much as possible.

I have a script that generates precompiled templates (mjml -> html -> handlebars precompiled).

It is something like:

const Handlebars = require('handlebars')
const precompiledContent = Handlebars.precompile('<b>{{ message }}</b>')
fs.writeFileSync('xyz/template.js', `module.exports = ${precompiledContent}`, 'utf8')

Then you can use the template like this:

const Handlebars = require('handlebars/runtime')
const message = 'Hi'
const template = require('./template.js')
const content = Handlebars.template(template)({ message })

@amruta-pani
Copy link

@RozzyNoder @ekskimn I managed to make this work but with a slight change. Instead of your reference to hello.js in your below code snippet,

var preCompiledTemplate = handlebars.templates['hello']; var finalPageHTML = preCompiledTemplate(data);

refer the actual hbs file that is used to generate the .js file, i.e.

var preCompiledTemplate = handlebars.templates['hello.hbs']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants