Using Template Engines
1. Setting View Engine
| Engine | Setup |
|---|---|
| EJS | app.set("view engine", "ejs") |
| Pug | app.set("view engine", "pug") |
| Handlebars | app.engine("hbs", engine()) + app.set("view engine", "hbs") |
| Custom | app.engine(ext, (path, opts, cb) => ...) |
2. Configuring Views Directory
Example: Multiple view paths
app.set("views", [
path.join(__dirname, "views"),
path.join(__dirname, "shared/views") // shared partials
]);
3. Rendering Templates
| Form | Effect |
|---|---|
res.render(view) | Render with locals only |
res.render(view, locals) | Pass data |
res.render(view, locals, cb) | Get HTML in callback (skip auto-send) |
app.render(view, ...) | Render without sending |
4. Passing Data to Views
Example: Locals merging
app.locals.appName = "Acme"; // every render
res.locals.user = req.user; // every render in this request
res.render("dashboard", { stats }); // template-specific
| Source | Precedence (lowest → highest) |
|---|---|
app.locals | 1 |
res.locals | 2 |
render(view, locals) | 3 |
5. Using EJS Templates
Example: EJS syntax
<!-- views/profile.ejs -->
<%- include("partials/header") %>
<h1>Hello, <%= user.name %></h1>
<ul>
<% for (const post of posts) { %>
<li><%= post.title %></li>
<% } %>
</ul>
| Tag | Purpose |
|---|---|
<%= %> | Escaped output |
<%- %> | Raw HTML |
<% %> | JS control flow |
<%# %> | Comment |
6. Using Pug Templates
Example: Pug indentation
doctype html
html
head
title= title
body
h1 Hello, #{user.name}
ul
each post in posts
li= post.title
| Pug Feature | Detail |
|---|---|
| Whitespace-significant | Indentation = nesting |
#{var} | Interpolation (escaped) |
!{var} | Raw |
extends layout | Inheritance |
block name | Override-able sections |
7. Using Handlebars
Example: express-handlebars setup
import { engine } from "express-handlebars";
app.engine("hbs", engine({
extname: ".hbs",
defaultLayout: "main",
helpers: { uppercase: (s) => s.toUpperCase() }
}));
app.set("view engine", "hbs");
| Syntax | Purpose |
|---|---|
{{var}} | Escaped output |
{{{var}}} | Raw HTML |
{{#each}} | Loop |
{{#if}}/{{else}} | Conditional |
{{> partial}} | Include partial |
8. Creating Partials and Layouts
Example: EJS partial
<!-- views/partials/nav.ejs -->
<nav>
<a href="/">Home</a>
<% if (user) { %><a href="/logout">Logout</a><% } %>
</nav>
<!-- views/page.ejs -->
<%- include("partials/nav") %>
| Engine | Layout Mechanism |
|---|---|
| EJS | express-ejs-layouts |
| Pug | Built-in extends/block |
| Handlebars | defaultLayout option |
9. Setting Global Template Variables
Example: app.locals helpers
app.locals.appName = "Acme";
app.locals.formatDate = (d) => new Intl.DateTimeFormat("en-US").format(d);
app.locals.currency = (n) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(n);
10. Using Helpers and Filters
| Engine | Helper Pattern |
|---|---|
| EJS | Functions on app.locals or passed in render |
| Pug | JS expressions inline; helpers via locals |
| Handlebars | helpers: { name: fn } in engine config |
Warning: Never render user-controlled HTML with raw output (
<%- %>, {{{ }}}) — XSS risk. Always escape unless you've sanitized.