Learn how to integrate EJS (Embedded JavaScript) with Express.js to create dynamic, server-side rendered HTML pages. This tutorial guides you through setting up EJS, creating templates, and passing data from Express to EJS for efficient content rendering.
What is EJS?
EJS (Embedded JavaScript) is a templating language for JavaScript that allows you to embed JavaScript directly in HTML files, making it easier to generate dynamic content. When used with Express.js, EJS can render HTML on the server, giving you the flexibility to customize content based on data passed from the backend.
Install Express and EJS
To get started, ensure Node.js is installed. Then, create a new Express project and add the necessary dependencies:
npm init -y
npm install express ejs
Configure EJS as the View Engine in Express
In your main server file (usually app.js
or server.js
), configure Express to use EJS as the templating engine:
const express = require('express');
const app = express();
// Set EJS as the templating engine
app.set('view engine', 'ejs');
// Optional: Specify a custom directory for EJS views
app.set('views', __dirname + '/views');
Create an EJS Template File
Inside the views
directory, create an .ejs
file to serve as your HTML template. EJS files resemble regular HTML files but allow embedded JavaScript for dynamic content:
<!-- views/app.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
<h1><%= message %></h1>
<p>This is a dynamic page rendered with EJS and Express.js.</p>
</body>
</html>
EJS Syntax Rules
EJS uses specific tags for embedding content and logic:
<%= %>
: Outputs HTML with characters escaped:<h1><%= title %></h1>
<%- %>
: Outputs unescaped HTML:<%- htmlContent %>
<% %>
: For JavaScript logic:<% if (user) { %> <p>Welcome, <%= user.name %></p> <% } %>
Pass Data from Express to EJS
Use res.render()
in Express to send data to your EJS template. You can pass an object containing data, which can then be accessed in EJS using <%= %>
for values or <% %>
for logic:
// Define a route
app.get('/', (req, res) => {
res.render('app', { title: 'Welcome', message: 'Dynamic content with EJS and Express!' });
});
Using JavaScript Logic in EJS
EJS allows JavaScript code, like loops and conditionals, directly in your templates, making it easy to display lists and handle conditions dynamically:
app.get('/items', (req, res) => {
const items = ['Laptop', 'Smartphone', 'Headphones'];
res.render('items', { items });
});
In the items.ejs
file:
<!-- views/items.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Items List</title>
</head>
<body>
<h1>Items:</h1>
<ul>
<% items.forEach(item => { %>
<li><%= item %></li>
<% }) %>
</ul>
</body>
</html>
Including Partials
EJS makes it easy to reuse code by allowing you to include "partials" — separate template files for reusable components like headers, footers, or navigation bars. This helps keep your code clean and manageable, especially for larger applications.
Creating Partials
To make the header and footer reusable, create two separate .ejs
files in a partials
directory under views
.
Header Partial (header.ejs
):
<!-- views/partials/header.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
Footer Partial (footer.ejs
):
<!-- views/partials/footer.ejs -->
<footer>
<p>© 2024 Your Company</p>
</footer>
</body>
</html>
Using Partials in Main Templates
To include a partial in a main EJS template, use the <%- include('partials/partialName') %>
syntax. The <%- %>
tag lets you insert unescaped HTML, which is useful for partials.
<!-- views/main.ejs -->
<%- include('partials/header') %>
<h1>Main Content</h1>
<p>Welcome to our dynamic page rendered with EJS and Express.js.</p>
<%- include('partials/footer') %>
With this setup, your header.ejs
and footer.ejs
partials are loaded automatically into any page that includes them, keeping your templates organized and your code more maintainable.
Complete Example
Let's bring everything together with a full example that includes routes, templates, and partials to create a simple product catalog. This example demonstrates how to structure your code, use partials, and pass data from Express to EJS.
Setting Up app.js
Start by creating an Express server in app.js
. Here, we'll set up EJS as the templating engine, define sample data, and create a route to display a list of products.
// app.js
const express = require('express');
const app = express();
// Set up EJS as the templating engine
app.set('view engine', 'ejs');
app.set('views', './views');
// Sample product data
const products = [
{ id: 1, name: 'Laptop', price: 75000 },
{ id: 2, name: 'Mobile', price: 25000 },
{ id: 3, name: 'Tablet', price: 35000 }
];
// Route to render the products page
app.get('/products', (req, res) => {
res.render('products', {
title: 'Product Catalog',
products: products
});
});
// Start the Express app
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
Creating the products.ejs
Template
In the views
folder, create a products.ejs
file to display the product catalog. Use partials for the header and footer to keep the template organized.
<!-- views/products.ejs -->
<%- include('partials/header') %>
<main>
<h1><%= title %></h1>
<div class="products">
<% products.forEach(product => { %>
<div class="product">
<h2><%= product.name %></h2>
<p>Price: ₹<%= product.price %></p>
</div>
<% }) %>
</div>
</main>
<%- include('partials/footer') %>
Conclusion
In this tutorial, you've learned how to set up and configure EJS as a templating engine in Express.js, create and render dynamic HTML pages, pass data from Express to EJS, and use JavaScript logic in EJS templates for loops, conditionals, and partials. With this knowledge, you can now build data-driven, server-side rendered applications with flexible and customizable content.