Node.js CRUD Operations w/ Express.js and Pug (Templating Engine)

In this tutorial, we will set up a simple HTTP web server with Express.js, a Node.js framework, and use an HTML templating engine called Pug, which earlier was known as Jade.

node.js + express.js + pug

Create a working directory for your project, say, /node-project.

Inside /node-project, we will create the package.json file for our Node.js + Express.js application typing the below command.

				
				$ npm init
				
			
node.js npm init

Fill the name, version, description and other such fields with your own values. Now there is one field called entry point where you can give a name to your main file (.js file). The default suggested name is server.js. If you want some other name, like app.js, you can do the naming here. It will be created after the author and license fields are over.

Express.js

Next, we will install Express.js.

					
					$ npm install express --save
					
				

The following code sets up a simple HTTP server with Express.js.

					
					const express = require('express');
					const app = express();
					const port = 3000;

					app.get('/', (req, res) => {
						res.status(200).send('Hello, World!');
					});

					app.listen(port, () => {
						console.log(`Server started at port ${port}`);
					});
					
				

The method get() attached to the express instance is one of the many route methods in Express.js, along with post(), put(), delete(), all(), etc. The full list of route methods can be found here. The path / passed to app.get() is the root of our project.

Start the application.

					
					$ npm start
					
				

In your terminal console, the below message will get printed

					
					Server started at port 3000
					
				

Navigate to http://localhost:3000 in your browser and you will see the page load as follows:

node.js expressjs hello world

Load an HTML File

Loading an HTML file is just a small change: use the sendFile() method instead. Here we load the below index.html file. __dirname is the directory name of the current module.

					
						<!DOCTYPE html>
						<html>
						<head>
							<title>Node.js + Express.js</title>
						</head>
						<body>
							<h1>Hello, Node.js + Express.js</h1>
						</body>
						</html>
					
				
					
					const express = require('express');
					const app = express();
					const port = 3000;

					app.get('/', (req, res) => {
						res.status(200).sendFile(__dirname + '/index.html');
					});

					app.listen(port, () => {
						console.log(`Server started at port ${port}`);
					});
					
				

It gets rendered as shown below.

node.js expressjs html

Also, we can keep track of the paths we are accessing by printing them in console using the use() method. The wildcard character * passed to the get() route method handles the unspecified or non-existent paths.

					
					const express = require('express');
					const app = express();
					const port = 3000;

					app.use((req, res, next) => {
						console.log(`URL: ${req.url}`);
						next();
					});

					app.get('/', (req, res) => {
						res.status(200).sendFile(__dirname +  '/index.html');
					});

					app.get('*', (req, res, next) => {
						res.status(200).send('Sorry, requested page not found.');
						next();
					});

					app.listen(port, () => {
						console.log(`Server started at port ${port}`);
					});
					
				

The first argument supposed to be passed to the use() method actually is a path, which defaults to /. You can check the various examples on using path here. So we can also rewrite the above use() method as below. It will have the same effect.

					
					app.use('/', (req, res, next) => {
						console.log(`URL: ${req.url}`);
						next();
					});
					
				

Route Parameters

URL segments can be named to pass parameters at the very position in the URL. The values can then be accessed from the req.params object. In the following script, we specify the parameter name in the path of the route.

					
					const express = require('express');
					const app = express();
					const port = 3000;

					app.use((req, res, next) => {
						console.log(`URL: ${req.url}`);
						next();
					});

					app.get('/', (req, res) => {
						res.status(200).sendFile(__dirname +  '/index.html');
					});

					app.get('/member/:name', (req, res) => {
						res.end(`Requested member with name: ${req.params.name}`);
					});

					app.get('*', (req, res, next) => {
						res.status(200).send('Sorry, page not found');
						next();
					});

					app.listen(port, () => {
						console.log(`Server started at port ${port}`);
					});
					
				
rocket raccoon Rocket Raccoon by Ryan C. CC BY-SA 2.0 . Background: HD188553, NASA/JPL-Caltech

We pass the value Rocket in place of the :name parameter: http://localhost:3000/member/Rocket

node.js expressjs route single parameter

And of course, we can make it work for two parameters as well.

http://localhost:3000/member/Rocket/planet/Halfworld

					
					const express = require('express');
					const app = express();
					const port = 3000;

					app.use((req, res, next) => {
						console.log(`URL: ${req.url}`);
						next();
					});

					app.get('/', (req, res) => {
						res.status(200).sendFile(__dirname +  '/index.html');
					});

					app.get('/member/:name/planet/:home', (req, res) => {
						res.end(`Requested member with name: ${req.params.name} 
								from planet: ${req.params.home}`);
					});

					app.get('*', (req, res, next) => {
						res.status(200).send('Sorry, page not found');
						next();
					});

					app.listen(port, () => {
						console.log(`Server started at port ${port}`);
					});
					
				
node.js expressjs route two parameters

Express + Pug

install pug ... index.pug

					
					doctype=html
					html 
						head 
							title Blog with Mongo   

						body 
							h1 Welcome to my Blog

							block content
					
				
					
					const express = require('express');
					const app = express();

					const port = 3000;
					const host = 'localhost';

					app.set('views', './views');
					app.set('view engine', 'pug');

					app.get('/', (req, res, next) => {
						res.render('index');
					});

					app.listen(port, host, () => {
						console.log(`Server started at ${host} port ${port}`);
					});
					
				

... localhost:3000/pugdemo

values through URLs.

					
					doctype
					html
					  head
					    title Pug Demo
					  body
					    h1 Hello, Pug!
					    div User ID: #{userid}
					    p Dept: #{department}
					
				
					
					const express = require('express');

					const app = express();
					const port = process.env.PORT || 3000;
					const www = process.env.WWW || './';


					const urlLog = (req, res, next) => {
						console.log(`URL: ${req.url}`);
						next();
					}

					// set the view directory
					// set the view engine

					app.set('view engine', 'pug');

					app.use(urlLog);

					app.get('/user/:id/dept/:deptment', (req, res, next) => {
						//res.end(`Requested user with id: ${req.params.id} in dept ${req.params.department}`);
						const userDetails = {
							userid: req.params.id,
							department: req.params.deptment
						}

						res.render('index', userDetails);
					});

					app.get('/pugdemo', (req, res, next) => {
						res.render('index')
					});

					app.get('*', (req, res, next) => {
						res.status(200).send('

Sorry, page not found

'); next(); }); app.listen(port, () => { console.log(`Server started at port ${port}`); });

.. PUG ul li

UL LI

Create a new directory called /views just inside the root directory of the project. We create a PUG template called galaxy.pug.

					
					extends index
					block content
						ul
							each g in gotg
								li Member: {g.name}, 
								   Species: {g.species}									
					
				
					
					const express = require('express');
					const app = express();

					const port = 3000;
					const host = 'localhost';

					let gotg = [
						{
							name: "Star Lord", 
							species: "Human x Spartoi"			
						},
						{
							name: "Drax", 
							species: "Human"
						},
						{
							name: "Gamora", 
							species: "Zen-Whoberis"
						},
						{
							name: "Rocket Raccoon", 
							species: "Zen-Whoberis"
						},
						{
							name: "Groot", 
							species: "Flora Colossus"
						}
					];

					app.set('views', './views');
					app.set('view engine', 'pug');

					app.get('/', (req, res, next) => {
						res.render('index');
					});

					app.get('/guardians-list', (req, res, next) => {
						res.render('guardians', {gotg});
					});

					app.listen(port, host, () => {
						console.log(`Server started at ${host} port ${port}`);
					});
					
				

singlePost.pug

					
					extends index

					block content
						div.card
							div.card-header ID: #{post.id} 
							div.card-title Title: #{post.title}
							p Body: #{post.body}
					
				

...

					
					const express = require('express');
					const app = express();

					const PORT = 3000;
					const HOST = 'localhost';

					let blogPosts = [
						{
							id: 1, title: "Post 1", body: "This is the first blog post"
						},
						{
							id: 2, title: "Post 2", body: "This is the second blog post"
						}
					];

					app.set('views', './views');
					app.set('view engine', 'pug');

					app.get('/', (req, res, next) => {
						res.render('index');
					});

					app.get('/posts', (req, res, next) => {
						res.render('posts', {blogPosts});
					});

					app.get('/posts/:id', (req, res, next) => {
						let id = req.params.id;
						let post = blogPosts.find(post => id == post.id);
						res.render('singlePost', {post});
					});

					app.listen(PORT, HOST, () => {
						console.log(`Server started at ${HOST} port ${PORT}`);
					});