Mastering EJS: Building Dynamic Web Applications with Embedded JavaScript


Introduction
Dynamic and interactive web applications have become essential in modern development. EJS (Embedded JavaScript) is a powerful templating language that bridges the gap between server-side data processing and rendering dynamic HTML. Its simplicity, flexibility, and seamless integration with Node.js make it a go-to tool for building server-rendered applications.
This guide covers everything you need to know about EJS, including its features, syntax, setup, and implementation, along with a practical example application.
What is EJS?
EJS (Embedded JavaScript) is a templating engine that enables developers to:
Embed JavaScript logic directly within HTML templates.
Dynamically render server-side data on the client.
Create modular, reusable components for streamlined development.
EJS is lightweight, easy to learn, and ideal for applications requiring server-side rendering with Node.js.
Key Features of EJS
Dynamic HTML Rendering: Generate dynamic web pages with ease by embedding JavaScript within your templates.
Simple Syntax: Use intuitive tags like
<%= %>
to output data or<% %>
for inline JavaScript logic.Reusable Templates: Modularize your views using includes and layouts for consistent design.
Seamless Integration: Works out-of-the-box with Node.js frameworks like Express.
Performance: Minimal overhead ensures fast rendering of dynamic content.
How to Set Up EJS
Before diving into examples, let’s set up EJS in a Node.js project.
Prerequisites
Ensure you have Node.js and npm installed. If not, download and install them from Node.js.
Installation
Initialize a new Node.js project and install EJS:
npm init -y
npm install ejs
Configuring EJS with Express
Step 1: Setting Up Express
Create a basic Express server and configure EJS as the view engine:
import express from "express";
const app = express();
// Set EJS as the view engine
app.set("view engine", "ejs");
// Define the views directory
app.set("views", "views");
// Sample route
app.get("/", (req, res) => {
res.render("index", { title: "Welcome to EJS!", message: "Hello, World!" });
});
// Start the server
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
This setup allows Express to locate .ejs
files in the views
folder and render them dynamically.
Folder Structure
Your project should follow this structure:
/project
/views
index.ejs
server.js
package.json
EJS Syntax and Examples
EJS offers a simple and intuitive syntax for embedding logic and data into HTML templates.
1. Outputting Data
Escaped Output: Safely outputs HTML-escaped data.
<%= data %>
Example:
<h1>Welcome, <%= username %>!</h1>
Output:
Welcome, John!
Unescaped Output: Outputs raw HTML (use cautiously to avoid XSS vulnerabilities).
<%- htmlContent %>
2. JavaScript Logic
EJS allows inline JavaScript logic:
Conditionals:
<% if (isLoggedIn) { %> <p>You are logged in.</p> <% } else { %> <p>Please log in.</p> <% } %>
Loops:
<ul> <% items.forEach(item => { %> <li><%= item %></li> <% }); %> </ul>
3. Including Templates
Reuse components by including partials:
<%- include("partials/header") %>
<h1>Main Content</h1>
<%- include("partials/footer") %>
Building an Example Application
Let’s create a simple secrets-sharing app with the given code snippets.
Application Overview
Functionality:
Users can register, log in, and view a "secret" page.
Templates dynamically render data and share common layouts.
Folder Structure:
/project /views /partials header.ejs footer.ejs home.ejs login.ejs register.ejs secrets.ejs server.js
Code Implementation
1. Home Page Template (home.ejs
)
<%- include('partials/header') %>
<div class="jumbotron centered">
<div class="container">
<h1 class="display-3">Secrets</h1>
<p class="lead">Don't keep your secrets, share them anonymously!</p>
<a class="btn btn-light btn-lg" href="/register">Register</a>
<a class="btn btn-dark btn-lg" href="/login">Login</a>
</div>
</div>
<%- include('partials/footer') %>
2. Login Page (login.ejs
)
<%- include('partials/header') %>
<div class="container mt-5">
<h1>Login</h1>
<form action="/login" method="POST">
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-dark">Login</button>
</form>
</div>
<%- include('partials/footer') %>
3. Register Page (register.ejs
)
<%- include('partials/header') %>
<div class="container mt-5">
<h1>Register</h1>
<form action="/register" method="POST">
<div class="form-group">
<label for="email">Email</label>
<input type="email" class="form-control" name="username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password">
</div>
<button type="submit" class="btn btn-dark">Register</button>
</form>
</div>
<%- include('partials/footer') %>
4. Secrets Page (secrets.ejs
)
<%- include('partials/header') %>
<div class="jumbotron text-center">
<h1>You've Discovered My Secret!</h1>
<p class="secret-text">This is a hidden message.</p>
<a class="btn btn-light btn-lg" href="/logout">Log Out</a>
</div>
<%- include('partials/footer') %>
5. Header and Footer Templates
header.ejs
:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Secrets</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"> </head> <body>
footer.ejs
:</body> </html>
Server Logic
import express from "express";
const app = express();
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(express.urlencoded({ extended: true }));
// Routes
app.get("/", (req, res) => res.render("home"));
app.get("/login", (req, res) => res.render("login"));
app.get("/register", (req, res) => res.render("register"));
app.get("/secrets", (req, res) => res.render("secrets"));
// Start Server
app.listen(3000, () => {
console.log("Server running on http://localhost:3000");
});
Conclusion
EJS empowers developers to build robust, dynamic web applications using familiar JavaScript syntax. By integrating seamlessly with Node.js and Express, EJS simplifies server-side rendering while promoting code reuse and maintainability.
Try implementing the example application to explore the versatility of EJS in action!
Subscribe to my newsletter
Read articles from Mohammed Shakeel directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Mohammed Shakeel
Mohammed Shakeel
I'm Mohammed Shakeel, an aspiring Android developer and software engineer with a keen interest in web development. I am passionate about creating innovative mobile applications and web solutions that are both functional and aesthetically pleasing.