Express Template Engines

Aug 28, 2020

Template engines allow you to configure Express to work seamlessly with popular templating engines, like Pug, Mustache, and others. In this tutorial, you'll learn how to add Pug as a template engine, as well as how to write your own minimal template engine that enables Express to work with Vue's server-side rendering.

Using Pug

Pug (formerly known as Jade) is one of the most popular templating engines for Express. Pug is a whitespace-sensitive HTML templating language that supports loops and conditionals. For example, below is some valid Pug code:

h1
  | Hello, #{name}!

Suppose the above code is in the views/test.pug file. Below is how you can use Express to render test.pug for you. Note the app.set('view engine', 'pug') call is how you tell Express to use Pug for templating. The string 'pug' refers to the npm module you want to use as your template engine.

const express = require('express');

const app = express();
// Use `pug` to preprocess all calls to `res.render()`.
app.set('view engine', 'pug');

app.get('*', (req, res) => {
  // Assuming the Pug code is in `views/test.pug`
  res.render('test', { name: 'World' });
});

const server = await app.listen(3000);

// Example of using the server
const axios = require('axios');

const res = await axios.get('http://localhost:3000');
res.data; // '<h1>Hello, World!</h1>'

Using Vue Server Renderer

Not all templating languages work with Express by default. Thankfully, it is easy to write your own template engine to glue your favorite templating language with Express. For example, suppose you have the below Vue template:

<h1>Hello, {{name}}</h1>

If you try to call app.set('engine', 'vue-server-renderer'), Express will throw a Module "vue-server-renderer" does not provide a view engine error. You need to add some glue code to tell Express how to call Vue server renderer.

To tell Express how to handle Vue templates, you should use the app.engine() function. The app.engine() function takes two parameters: a string name that tells Vue the name of this template engine, and a templateEngine function that loads and compiles a given template. Below is how you can write a templateEngine() function that uses Vue server renderer:

const Vue = require('vue');
const express = require('express');
const { renderToString } = require('vue-server-renderer').createRenderer();
const { promisify } = require('util');

const app = express();
// Tell Express how to pre-process '.template' files using Vue server renderer.
app.engine('template', function templateEngine(filePath, options, callback) {
  (async function() {
    const content = await promisify(fs.readFile).call(fs, filePath, 'utf8');
    const app = new Vue({ template: content, data: options });
    const html = await renderToString(app);

    callback(null, html);
  })().catch(err => callback(err));
});
app.set('view engine', 'template');

app.get('*', (req, res) => {
  // Assuming the Vue code is in `views/test.template`
  res.render('test', { name: 'World' });
});

const server = await app.listen(3000);

// Example of using the server
const axios = require('axios');

const res = await axios.get('http://localhost:3000');
res.data; // '<h1 data-server-rendered="true">Hello, World</h1>'

Want to become your team's Express expert? There's no better way to really grok a framework than to write your own clone from scratch. In 15 concise pages, this tutorial walks you through how to write a simplified clone of Express called Espresso. Get your copy!

Espresso supports:
  • Route handlers, like `app.get()` and `app.post()`
  • Express-compatible middleware, like `app.use(require('cors')())`
  • Express 4.0 style subrouters
As a bonus, Espresso also supports async functions, unlike Express.

Get the tutorial and master Express today!

More Express Tutorials