Allenph
Allenph

Reputation: 2015

Adding Values to HTML Without a Template Engine in Express?

I have taken over development of a site that runs on Node with Express. I should note that this is my first time using Node or Express. For some reason, the original developer must not have liked template engines since he's completely removed them. We're using Angular and Firebase on the front end for basically everything, so I understand why we wouldn't be injecting data to the page on the server side that often. It would still be nice to be able to, though.

The original never installed a template engine. Instead he instructed Node to treat the views folder as a static directory. He then renders the files as plain static files. For example:

Excerpt From App.js File:

app.use(express.static(path.join(__dirname, 'views')));

Excerpt From Route File:

router.get("/", function(request, response) {
    response.render("index.html");
});

I don't really want to add a template engine and mess with the routes at this point. Although I seriously doubt that I will need to inject data from the server-side often, if at all, I would like to know how I would do that.

The only thing I can think of is something like this...

router.get("/", function(request, response) {
    var data = request.query.someVariable;
    var fileContents = fs.readFileSync('../views/index.html', 'utf8')
    fileContents = fileContents.replace("$SomeDelim", data);
    response.send(fileContents);
});

That's not really that pretty. Is there a better way to do this without using template engines?

Upvotes: 3

Views: 5066

Answers (1)

Erik Duindam
Erik Duindam

Reputation: 349

I don't think there is a right answer to your question, but let me give you my opinion as a heavy Express/Node (and Angular) user.

It seems like you don't want to use a template engine, because your templates are almost static, but not entirely. The latter is extremely common with Angular projects, because 99.9% of the view logic happens in the front-end. I do agree that you sometimes have the necessity of introducing variables in your main Angular bootstrapped page or in e-mail templates.

Your suggestion of doing a replace on the file contents is not necessarily bad, but the fs.readFileSync is. This will block your function and block the execution of your script, waiting for the file system. I would use fs.readFile instead, with a callback function. This way Node's event loop can continue doing other things while the file system is opening the file.

I also want to note that doing a replace on the entire file causes Node to load the entire file into memory (perhaps twice because of the replace), which should be avoided for bigger files. You would then want to do it line-by-line. I don't think this is a real concern for you now.

My suggestion would be to add a simple template engine. Why? Because it works well, because it's documented, because programmers know how to use it, because it's easy to implement and because some of the smaller template engines do exactly what you are suggesting.

Personally I would recommend Hogan.js, which is a simple template engine, known by programmers from various languages, doing primarily some simple replacements like you want. Hogan basically replaces variables like this: <div>{{variable}}</div>. It has a very simple way of switching "if/else" and some simple loops. That's basically all.

You can change your Express app to include the following (and you would remove your existing static 'views' declaration):

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hjs');

With Hogan, your view files will get an .hjs file extension.

views/index.hjs

<section>
    <div>{{variable}}</div>
</section>

routes/index.js

route.get(function (req, res) {
    res.render('index', {
        variable: 'example',
    });
});

There's nothing dirty about adding this template engine, and it's not going to impact your performance, compared to your own type of solution.

If you care about performance, put a reverse-proxy/webserver like nginx in front of your Node app, and let it serve all the static files. Additionally, set the right http caching headers in the main template route to avoid getting hit too much on Node.

Upvotes: 6

Related Questions