Is there any way to use multiple view engines with Express + Node.js
Asked Answered
I

4

31

Scenario: I had developed some transactional pages using Node.js, Express + Handlebars as view engine and MongoDB.

Now the issue is during module integration I got some of the pages which are built on Express + Jade as view engine.

Question: How to integrate pages built on Handlebars & some on Jade?

Ize answered 25/2, 2013 at 8:57 Comment(2)
Can you show how you dealt with identifying the pages?Burgess
@Lion789: You can check this from notes of consolidate.js documentation. "use cons.hogan for hogan.js, cons.jade for jade, etc. console.log(cons) for the full list of identifiers."Ize
W
24
  1. Add both engines and consolidate.js in your package.json
  2. In yourapp.js

    var engines = require('consolidate');

    app.engine('jade', engines.jade);

    app.engine('handlebars', engines.handlebars);

More info here

Wrightson answered 25/2, 2013 at 10:5 Comment(5)
Is it possible to add a custom template engine? expressjs.com/advanced/developing-template-engines.htmlIdeography
This didn't seem to work for me. Express 4 always seems to render all files with the same engine, even if the file extension matches a different engine.Abeyant
@WayneBloss sounds to me like you have a default template engine hidden in your code. If you generated the app or started from a template/followed a guide/etc your app likely has a default render specified at some point.Grapher
How do you then implement the views and render them exactly ... here is my question on SO #36395162Burgess
if this snippet had ever worked, now it doesn't work. If you do not specify the engine with app.set('view engine', ...) then the app crashes. If you specify one, the other gets ignoredPatterman
T
22

Express 4.0 and up solution (until it changes again)

  1. NPM install the engines you need.

    // some examples
    npm install ejs
    npm install pug
    npm install handlebars
    
  2. Set the engines to use in your app.js.

    app.set('view engine', 'pug');
    app.set('view engine', 'ejs');
    
  3. Render your template, be sure to set the file extension.

    // forces usage of the respective render engine by setting the file extension explicitly.
    res.render( 'about.ejs', { title: 'About' } );
    res.render( 'about.pug', { title: 'About' } );
    
  4. Documentation for more usage examples.

Tangency answered 26/2, 2018 at 4:57 Comment(0)
S
2

EDIT

After discussing with Amol M Kulkarni below comments, I came back and analyzed these again.

And turns out, it was fairly easier than I thought that I have to get back here and share my solution. Using consolidate, do it like this:

First do the require.

var engines = require('consolidate');

Then you can either remove or set engine and view engine...
I have tried removing all app.engine and app.set('view engine', '...'); and it did work. However, setting it other than 'html' will only work for one engine. So I just have set it to be sure.
I have set it like so:

app.engine('html', engines.swig); // take note, using 'html', not 'ejs' or 'pug'..
app.set('view engine', 'html'); // also 'html' here.

And then later on when you do the app.render, just make sure it has the file extension and it will just work nicely.

res.render( 'theme.ejs', {}); // will render with ejs
res.render( 'theme.pug', {}); // will render with pug

Just make sure have these engines (pug, ejs, etc..) are installed and consolidate will do the rest.


Old answer.
with relation to @Sergii answer, it did not work for me 100%. There are times when an error is raised in the templates I'm using. But with a wrong error message that says failed to look up this template in this directory.

I tried @azariah solution but still did not work.

app.set('view engine', 'pug'); // does not make sense.
app.set('view engine', 'ejs'); // overriding the last .set()

what worked for me is using consolodate.js as mentioned.
Added app.set('view engine', 'pug'); as usual.
And then, in every time I will call render, I set the 'view engine'.

like so:

req.app.set('view engine', 'ejs');
res.render( 'theme', theme );

My worries with this is that when more simultaneous users will visit page with different engines, not sure if this will collide and be back with the error look up that I'm having.

But I guess that the render is so fast, that it should be done by the time another req.app.set is called.

Salvadorsalvadore answered 2/11, 2018 at 14:1 Comment(3)
I'm using it... just that you can only use 1, for example, pug, app.set('view engine', 'pug'); and that's your view engine...Salvadorsalvadore
As I mentioned above, calling app.set twice will not make sense.. you are setting the view engine only at the last call...Salvadorsalvadore
I am talking about @Sergii's answer (not be be mistaken as azariah's). You can check this from notes of consolidate.js documentation. use cons.hogan for hogan.js, cons.jade for jade, etc. console.log(cons) for the full list of identifiers."Ize
K
0

I found this as more accurate and this is my personal practice. We should have a default template engine set, so that all all views should process through at-least one template engine, it will save the file from being exposed to end user, in case you have html as default engine.

therefore, start with installing consolidate.js to the directory.

npm install consolidate

Later, we need to add the installed module to the application file.

var consoengines = require('consolidate');

Now setting the default view engine, (choosing pug because of its popularity)

app.set('view engine', 'pug');

After setting the default template engine. now I need to install the additional template engine, for my case, I mostly need EJS, because it allows almost all Javascript, which comes handy, to make anything in template. but you are good to choose any template engine. All you would have to do is, install your template engine

npm install ejs

Now add this to consolidate instance and then put back to main template engines list.

app.engine('ejs', engines.ejs);

Now each time, you render a template, if you don't give extension in your router, this will call it with the default set template engine (here it is PUG), otherwise it will call the template engine according to the extension mentioned in the router call.

Kant answered 28/12, 2022 at 17:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.