5

I have come across plenty of resources online for this but haven't been able to find one that is straight forward enough for me to understand.

At the moment, I have multiple massive <script> tags in an HTML document that has handlebars content. The server sends this HTML document to the client where the client then renders the page with data from an AJAX call. I'd like to move this entire process server-side so that all the server has to do is send a static file and re-render the page when data is updated. Data changes a few times per day - which is why it isn't hard coded in and I would like to run the handlebars compiler on the HTML document when data is updated.

Is it possible to simply put the HTML document with handlebars templating in <script> tags through a function to generate a new HTML file with data filled in?

Here is the code I have within my app.js file that is runned the Node server that does not do what I want it to:

function registerHelpers(callback){
  Handlebars.registerHelper('equal', function(lvalue, rvalue, options) {
    if (arguments.length < 3)
        throw new Error("Handlebars Helper equal needs 2 parameters");
    if( lvalue!=rvalue ) {
        return options.inverse(this);
    } else {
        return options.fn(this);
    }

  });

  Handlebars.registerHelper('trim', function(text) {
    text = text.replace(/ /g, '');
    return new Handlebars.SafeString(text);
  });

  callback();
}

function buildHomePage() {
  var source = require(__dirname + '/public/home.handlebars');
  var template = Handlebars.precompile(source);
  var collection = db.get('datalist'); //Monk call to MongoDB
  collection.find({}, function (err, docs){
    var result = template(docs);
    console.log(result)
    var fs = require('fs');
        fs.writeFile("test.html", result, function(err) {
        if(err) {
          console.log(err);
        }
    });
  });
};

registerHelpers(buildHomePage);
4
  • If I follow properly, what you are describing is to render the initial page on the server and send the HTML down to the client and then rerender the whole page in the client when data is updated. That seems overly complicated as you have to support two full render paths and pieces of code. I'd suggest you either render initially server-side and then insert updates/modifications surgically in the client (rather than rerendering the whole page) or always render in the client, both initially and when you get updates. Commented Feb 6, 2018 at 2:47
  • You can save the initial ajax call by putting the data into the initial page as Javascript data in a <script> tag and your initial render can use the data from there. Then, there's only one type of rendering ever. When the page is first rendered, it is rendered from the Javascript data went with the page. When the page is re-rendered later, the same rendering mechanism is used, but it gets the data from another source (Ajax call or webSocket message presumably). Commented Feb 6, 2018 at 2:50
  • Also, why would your server ever be writing test.html to the file system? You can't do that (render a hard-code filename as part of a request handler) for a server that handles more than one user. Multiple requests from multiple users will tromp on each other's data. Normally, you would render into a Javascript string (which you already do) and then send that string as the http response. No need to put the data into the file system. Commented Feb 6, 2018 at 2:52
  • @jfriend00 I think I may have just worded this question poorly. I would like to generate a static HTML file from my handlebars template. Then the server would serve the static HTML file without any of the handlebars templating. It would generate this HTML file once, then serve this HTML file until it creates a new one. Hopefully this makes more sense? Commented Feb 6, 2018 at 3:16

1 Answer 1

13

The following can render handlebars to static html. Run node example.js. You may need to run npm install --save handlebars prior.

var fs = require('fs');
var Handlebars = require('handlebars');

function render(filename, data)
{
  var source   = fs.readFileSync(filename,'utf8').toString();
  var template = Handlebars.compile(source);
  var output = template(data);
  return output;
}

var data = JSON.parse(fs.readFileSync("./data/strings.json", 'utf8'));

var result = render('./templates/somefile.html', data);

console.log(result);

If your handlebars templates are simple, with only string replacement, you can do this with underscore.js. Assume this example is named 'generate.js'

var fs = require('fs');
var _ = require('underscore');
_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;

function render(filename, data)
{
  var source   = fs.readFileSync(filename,'utf8').toString();
  var compiled = _.template(source);
  return compiled(data);
}

var data = JSON.parse(fs.readFileSync("./data/strings.json", 'utf8'));

var result = render('./templates/somefile.html', data);

console.log(result);

Then run node generate.js to output the rendered template to the console. You may need to do npm install --save underscore prior.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.