Express.js: Serving Static Files and Templating with EJS and Pug
Express.js is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications. One of the key capabilities it offers is serving static files and handling templating, allowing for dynamic web content generation. In this article, we'll delve into each component by exploring how to serve static files and work with two popular templating engines: EJS and Pug.
Serving Static Files
Static files such as images, CSS, and JavaScript files are essential for proper rendering and user interaction on a web page. In Express.js, serving these files efficiently can be accomplished using the built-in middleware express.static
.
Setting Up express.static
const express = require('express');
const app = express();
// Serve static files from the 'public' directory
app.use(express.static('public'));
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
In the above example, any files stored in the public
directory (e.g., public/images/logo.png
, public/css/style.css
) can be accessed directly via URLs like http://localhost:3000/images/logo.png
or http://localhost:3000/css/style.css
.
Serving Multiple Directories
If you need to serve files from multiple directories, simply call express.static
multiple times.
// Serve static files from 'public' and 'assets' directories
app.use(express.static('public'));
app.use(express.static('assets'));
Using Absolute Paths
You can also serve files from an absolute path if needed.
app.use(express.static(__dirname + '/public'));
Customizing the Static Cache Control
To improve performance, you can customize the cache control headers sent to clients.
app.use(express.static('public', {
maxAge: '1d' // Cache files for one day in the browser
}));
EJS Templating Engine
EJS (Embedded JavaScript Templates) is a simple and unopinionated templating language for generating HTML markup with plain JavaScript. EJS extends HTML with templating capabilities, making it an easy-to-use choice for dynamic content.
Setting Up EJS
First, install EJS via npm.
npm install ejs
Next, configure Express.js 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');
app.get('/', (req, res) => {
res.render('index', { title: 'Welcome', message: 'Hello World!' });
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
Creating EJS Templates
Create an index.ejs
file in the views
directory.
<!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>
</body>
</html>
In the template, <%= title %>
and <%= message %>
are placeholders that will be replaced with the values passed from the res.render
method.
EJS Tags
EJS provides several types of tags to include dynamic content and logic in templates:
<%= %>
: Outputs the escaped HTML.<%- %>
: Outputs the unescaped HTML.<% %>
: Executes the JavaScript code.<%# %>
: Comment block.<%%>
: Outputs a literal<%
.<%_ %>
: Whitespace-trimmed code block.<%-_%>
: Whitespace-trimmed unescaped code block.
Example with Conditionals and Loops
<!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>
<ul>
<% users.forEach(user => { %>
<li><%= user.name %> - <%= user.email %></li>
<% }) %>
</ul>
</body>
</html>
In the Express route:
app.get('/', (req, res) => {
const users = [
{ name: 'John Doe', email: 'john@example.com' },
{ name: 'Jane Smith', email: 'jane@example.com' }
];
res.render('index', { title: 'Welcome', message: 'Hello World!', users: users });
});
Pug Templating Engine
Pug (formerly known as Jade) is a high-performance templating engine for Node.js that simplifies HTML creation by allowing for a more concise syntax. It generates HTML from the template files, enabling you to write HTML in a cleaner and simpler manner.
Setting Up Pug
Start by installing Pug.
npm install pug
Next, configure Express.js to use Pug as the templating engine.
const express = require('express');
const app = express();
// Set Pug as the templating engine
app.set('view engine', 'pug');
app.get('/', (req, res) => {
res.render('index', { title: 'Welcome', message: 'Hello World!' });
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
Creating Pug Templates
Create an index.pug
file in the views
directory.
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0")
title= title
body
h1= message
In the template, title= title
and h1= message
are placeholders that will be replaced with the values passed from the res.render
method.
Pug Tags and Syntax
Pug syntax eliminates the need for closing tags and indentation has a significant meaning, which makes it more concise and easier to read.
Conditional Statements
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0")
title #{title}
body
if message
h1 #{message}
else
h1 No Message
Loops
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport" content="width=device-width, initial-scale=1.0")
title #{title}
body
ul
each user in users
li #{user.name} - #{user.email}
In the Express route:
app.get('/', (req, res) => {
const users = [
{ name: 'John Doe', email: 'john@example.com' },
{ name: 'Jane Smith', email: 'jane@example.com' }
];
res.render('index', { title: 'Welcome', message: 'Hello World!', users: users });
});
Conclusion
Express.js provides built-in support for serving static files and offers flexibility in choosing templating engines. We covered how to use express.static
to serve static files and explored the basics of both EJS and Pug templating engines. By incorporating these features into your Express.js applications, you can create dynamic and visually appealing web pages efficiently.
Examples: Setting Route, Running Application, and Data Flow with Express.js for Serving Static Files and Templating (EJS & Pug)
Express.js is a powerful Node.js framework that simplifies the process of web development by providing a robust set of features to handle server-side logic efficiently. One of these features includes serving static files (such as images, CSS, and JavaScript) and using template engines like EJS or Pug to render dynamic content. Let's walk through an example step-by-step to understand how to implement these features.
Step 1: Setting Up Your Project
First, you need to initialize a new Node.js project. Open your terminal and run the following commands to create a new directory, navigate into it, and initialize your project:
mkdir express-static-templates
cd express-static-templates
npm init -y
This will create a package.json
file with default values.
Step 2: Installing Required Packages
You will need to install express
, ejs
, and pug
. Run the following command to install these packages:
npm install express ejs pug
Step 3: Creating the Server File
Create a new file named server.js
in your project directory. This file will contain the setup for the Express server.
const express = require('express');
const path = require('path');
// Create an Express application
const app = express();
// Define port number
const PORT = 3000;
// Set path for static files (like images, css, js)
app.use(express.static(path.join(__dirname, 'public')));
// Set the view engine to EJS
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views/ejs'));
// Optionally, set the view engine to Pug
// app.set('view engine', 'pug');
// app.set('views', path.join(__dirname, 'views/pug'));
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
In this example, we've set up Express to serve static files from the public
directory and use EJS as the templating engine. If you prefer using Pug, you can uncomment the Pug configuration lines and comment out the EJS lines.
Step 4: Adding Static Files
Create a public
directory at the root level of your project. Inside public
, add some static files, such as CSS and JavaScript files, or any images you want to display. For example, create a CSS file:
mkdir public
touch public/styles.css
Edit styles.css
with some basic styling:
/* public/styles.css */
body {
background-color: lightblue;
font-family: Arial, sans-serif;
}
h1 {
color: navy;
margin-left: 20px;
}
This CSS file will be served statically and linked in the HTML templates.
Step 5: Setting Up Views with EJS and Pug
Create a views
directory with subdirectories for EJS and Pug templates:
mkdir -p views/ejs views/pug
EJS Template
In the views/ejs
directory, create a file named index.ejs
:
<!-- views/ejs/index.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<h1>Welcome to the Express.js app with EJS!</h1>
<p>This page is rendered using <strong>EJS</strong> template engine.</p>
</body>
</html>
Pug Template
Similarly, in the views/pug
directory, create a file named index.pug
:
// views/pug/index.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Home
link(rel="stylesheet", href="/styles.css")
body
h1 Welcome to the Express.js app with Pug!
p This page is rendered using #[strong Pug] template engine.
Step 6: Defining Routes
Next, we'll define routes in server.js
to handle incoming requests and render the appropriate views.
For EJS:
// Serve the EJS homepage
app.get('/', (req, res) => {
res.render('index'); // No extension needed as the view engine is set to EJS
});
For Pug:
Comment out the existing app.get()
route for EJS and add a new route for Pug:
// Serve the Pug homepage
app.get('/', (req, res) => {
res.render('index'); // Ensure that the views folder points to the correct engine
});
If you decide to use Pug, make sure to adjust the app.set()
configurations for views to point to the views/pug
directory instead of views/ejs
.
Step 7: Running the Application
In your terminal, run the following command to start the server:
node server.js
Once the server is running, open your web browser and visit http://localhost:3000
. Depending on your currently configured view engine (EJS or Pug), you should see a styled welcome message.
Understanding the Data Flow
- Request is Made: A client makes a request to
http://localhost:3000
. - Server Receives Request: The Express server listens for requests on port 3000.
- Route Handling: The defined route handler (
app.get('/')
) is triggered. - View Rendering:
- If using EJS, the
index.ejs
file is located inviews/ejs
and rendered to HTML. - If using Pug, the
index.pug
file is located inviews/pug
and compiled to HTML.
- If using EJS, the
- Response Sent: The server responds with the rendered HTML.
- Static Files Served: Any references to static files (like
styles.css
) are resolved and served from thepublic
directory.
Conclusion
By following these steps, you have successfully created an Express.js application that serves static files and uses both EJS and Pug as templating engines. You learned how to set up routes, serve static assets, and manage view rendering according to different templating engines. This foundation allows for further enhancements and more complex applications.