Express (Harry)

1/1/1970

Express (Harry)

Express JS Tutorial in Hindi πŸ”₯✌

Express is a Fast, unopinionated, minimalist web framework for Node.js it is a backend framework like Flask , Django

Resources


Setup Express

Open your project Directory in Terminal and initialize the NodeJS project.

npm init # Interactive project setup.
npm init -y # Quick setup with defaults.

A package.json will be Created. Now Create Index.js , that would be entry point.

project
β”œβ”€β”€ index.js
└── package.json

Install express

npm install express --save # `--save` is optional now

The --save flag in npm install express --save was used to add the installed package (express in this case) to the dependencies section of your package.json file.

To install all the modules if node_modules folder got deleted, just use npm i As of npm version 5 this flag is no longer necessary.

Uninstall express

npm uninstall express

Why Express is important, Why we can't simply made HTTP server in Nodejs ??

Open index.js and Start Coding:

Build A Basic HTTP Server in NodeJS

// Importing the createServer function from the 'node:http' module
const { createServer } = require('node:http');
 
const hostname = '127.0.0.1';
const port = 3000;
 
// Creating the server instance using createServer function
const server = createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});
 
// createServer().listen()
server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

Note:

res & req

In Express We Can Do the Similar thing ⭐

const express = require('express')
const app = express()
const port = 3000
 
app.get('/', (req, res) => {
  res.send('Hello World!')
})
 
app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

Import

require: in Node.js, require() is a built-in function used to import modules, JSON, and local files into your application

const express = require('express')

import: this is alternative way to import. This Model is useful if you're working with modern Javascript and want to take advantage of ES Module features.

import express from 'express'

Express is used so that, We no more need to use if else for Creating different different endpoints. for example \about, \contacts ⭐

Create Instance of React Express

const app = express()

Routes Handler

localhost:3000 will show 'Hello World!' as Response at the Page

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

localhost:3000/about will show 'Introduction' as Response at the Page

app.get('/about', (req, res) => {
  res.send('Introduction')
})

localhost:3000/contacts will show 'List of Contacts' as Response at the Page

app.get('/contacts', (req, res) => {
  res.send('List of Contacts')
})

Note: In Express, Inspect Network, You will see it will automatically send Status Code like 404. Without Express, we have to write custom codes for Status Codes manually Express is a Framework to save your time : ) ⭐


Lets Start

Import Modules

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

Send Response

// Route Handler
app.get('/', (req, res) => {
  res.send('Hello World!')
})

Sending HTML as Response

// Route Handler
app.get('/about', (req, res) => {
  res.sendFile(path.join(__dirname, 'index.html' ))
})

Custom Status Code

// Route Handler
app.get('/contacts', (req, res) => {
	res.status(500) // 500: internal error
	res.send('List of Contacts')
})

Note: res.status() and res.send() ordered matter ⭐

Run Server

app.listen(port, () => {
  console.log(`app listening at http://localhost:${port}`)
})

Note:


More

Send JSON

app.get('/about', (req, res) => {
  res.json({"gaurav" : 169})
})

Note:- You can install chrome extension JSON Formatter if you want to see, the JSON sent in a formatted way. (Useful for big JSON files)

Use html files inside Public Folder

project
β”œβ”€β”€ node_modules
β”œβ”€β”€ index.js
└── public
       └── index.html
const path = require('path')
// All other Imports
 
// Middleware
app.use(express.static(path.join(__dirname, "public")))

Note:- Now it will start Serving Public Folder as Static Folder Express Middleware are Functions that will keep Access of Request and Response Objects, and can change it. ⭐


Middleware

Example to Create your own Middleware

// Create Middleware
const gauravMiddleware = (req, res) =>{
	console.log(req)
}
// use Middleware
app.use(gauravMiddleware)

In general, there is not need to create Middleware, we only use them : )

Note:

Types of Middleware:

  1. Application-Level Middleware: Defined using app.use() or app.METHOD().
  2. Router-Level Middleware: Defined for specific routers.
  3. Built-in Middleware: Middleware provided by Express, such as express.json() for parsing JSON request bodies.
  4. Third-Party Middleware: Middleware from external packages (e.g., morgan for logging, cors for handling cross-origin requests).
  5. Error-Handling Middleware: Special middleware used for catching and handling errors.

Common Built in Middleware

If we have more than one middleware, we use next() function, so that next middleware run after current running middleware ⭐

// Create Middleware
const gauravMiddleware = (req, res, next) =>{
	console.log(req)
	next() // pass control to the next middleware function in the stack.
}
// use Middleware
app.use(gauravMiddleware)

Parameters in Routes/Endpoints

// name parameter
app.get('/hello/:name', (req, res) => {
	res.send('Hello World! ' + req.params.name)
})
 
// url -> localhost:3000/hello:Gaurav
// response -> Hello World! Gaurav

We can fetch blogposts from website, fetch key value pair from your database. You get this by sending the Parameters

static / public folder

template folder


express.Router().get() vs express().get()

express().get()

const express = require('express');
const app = express();
 
app.get('/hello', (req, res) => {
  res.send('Hello from App!');
});
 
app.listen(3000, () => console.log('Server is running on port 3000'));

express.Router().get()

const express = require('express');
const app = express();
const router = express.Router(); 
 
// express.Router().get()
router.get('/hello', (req, res) => {
	res.send('Hello from Router!');
});
 
// Router use `app.use()`
app.use('/api', router); // Mounting router at '/api'
 
app.listen(3000, () => console.log('Server is running on port 3000'));
Feature express().Router().get() express().get()
Scope Local to the router instance. Global to the app.
Reusability Highly reusable in modular apps. Not reusable; app-specific.
Mounting Required Yes, using app.use(). No, directly available.
Preferred Use Case For modular route management. For simple apps or global routes.

Express Production app Structure ( Example blog app)

Create the Files

public or Static Directory Contains static files that are served directly to the client. template Directory

project
β”œβ”€β”€ node_modules
β”œβ”€β”€ index.js
β”œβ”€β”€ routes
β”‚      └── blogRoute.js
β”œβ”€β”€ static
|       
β”œβ”€β”€ templates
|       └── index.html
|       └── blogHome.html   
|       └── blogPage.html 
└── data
         └── blogData.js 

static Middleware:- Used to serve static files from a specified director ex:- app.use(express.static('public')); ⭐

Template Rendering:-Used to dynamically generate HTML pages on the server side using template engines.


Create index.js

//index.js
const express = require('express')
const path = require('path')
const app = express()
const port = 3000
 
app.use(express.static(path.join(__dirname, "static"))) // path.join()⭐ & __dirname
 
app.use('/', require(path.join(__dirname, `routes/blogRoute.js` )))
 
app.listen(port, () => {
  console.log(`Blog app listening at http://localhost:${port}`)
})
  1. The app.use(express.static(path.join(__dirname, "static"))) line in an Express.js application sets up middleware to serve static files from a directory. Here’s a breakdown of what each part does:

  2. require(path.join(__dirname, 'routes/blogRoute.js')): This loads the router module from the routes/blogRoute.js file. The path.join(__dirname, 'routes/blogRoute.js') constructs the absolute path to the blogRoute.js file. __dirname is a global variable representing the directory name of the current module. ⭐

  3. path.join(__dirname, 'routes/blogRoute.js'): Joins the __dirname (current directory) with the routes/blogRoute.js path, ensuring the path is correctly constructed based on the operating system.

  4. We will separate our other routes from index.js into separate routes files, because it will become complex to write multiple routes into single, index.js. let the routes be routes/blog.js

  5. '/' is the base path where you want to mount your router, require('./routes/blogRoute.js') is the router module that contains the routes and Together, they define that all routes inside blogRoute.js will be mounted at the root path ('/'). ⭐

Note: To ensure your CSS and JavaScript files are applied correctly to your index.html, configure Express to serve static files using app.use('/static', express.static(path.join(__dirname, 'static')));, and use absolute paths in your HTML, such as <link rel="stylesheet" href="/static/style.css" /> and <script src="/static/script.js"></script>. This setup will correctly link your styles and scripts regardless of the file's location.

Create Index.html

...
<body>
This is my Home Page
</body>
...

Create blogRoute.js

// blogRoute.js
const express = require('express')
 
// router function
const router = express.Router()
// routes
router.get('/', (req, res)=>{
	res.sendFile(path.join(__dirname, 'templates/index.html' ))
})
 
// Export router
module.exports = router ⭐

Note:

router.get() vs app.get()⭐

Create blogData.js:

// blogData.js
{
	blogs:[
		{
			title: "How to get started with Python",
			content: "This is content",
			slug: "python-learn"
		},
		{
			title: "How to get started with JS",
			content: "This is content"
		},
			slug: "javascript-learn"
		{
			title: "How to get started with Django",
			content: "This is content"
		},
			slug: "python-django-learn"
	]
}
 
// export the file
module.exports blogs;

Update blogRouter.js:

const express = require('express')
const router = express.Router()
 
// inport built in `path` module
const path = require('path')
 
// import blogData.js file
const blogs = require('../data/blogs')
 
router.get('/', (req, res)=>{
	res.sendFile(path.join(__dirname, `templates/index.html`))
})
 
// +++++++++++++++++++++++++++++++++++++++++++++++
router.get('/blog', (req, res)=>{
	// print each blog title in console
	blogs.forEach(elem =>{
		console.log(elem.title) ⭐
	});
	// route '/blog' to 'blogHome.html'
	 res.sendFile(path.join(__dirname, `templates/blogHome.html` ))
})
// ++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module.exports = router

Note:

If there is a singl Create blogHome.html

<body>
This is my blog Homepage
</body>

Create blogPage

<body>
Python Blog
</body>

Update blogRoute.js

// blogRoute.js
const express = require('express')
const router = express.Router()
const path = require('path')
const blogs = require('../data/blogs')
 
router.get('/', (req, res)=>{
	res.sendFile(path.join(__dirname, `../templates/index.html` ))
})
 
router.get('/blog', (req, res)=>{
	blogs.forEach(elem =>{
		console.log(elem.title)
	});
	 res.sendFile(path.join(__dirname, `../templates/blogHome.html` ))
})
 
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
// Individual post routing through Parameter
router.get('/blogpost/:slug', (req, res)=>{
	// JS function to Filter the blogs array to find the blog with the matching slug
	myBlog = blogs.filter((elem)=>{
		return elem.slug == req.params.slug
	})
	 res.sendFile(path.join(__dirname, `../templates/blogPage.html` ))
});
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
module.exports = router

There our basic routing is done, we can Create design and add contents etc.

Note:


We can also use mongoose to connect to the MongoDB Database : )


Handlebars

Handlebars.js is a templating engine for Node.js that can be used with Express to render web pages from server-side data to the client side. Handlebars expressions are the basic unit of a Handlebars template, and are enclosed by double curly braces, {{}} ⭐. For example, the following template uses a variable, firstname, enclosed by double curly braces:

template:Β <p>{{firstname}} {{lastname}}</p>

Note: Handlebar is like Jinja2 python template engine. more template engines for express - EJS, Pug

HBS HBS (Express-HBS): A specialized package for using Handlebars within the Express framework, making integration with Express easier and more streamlined.

Express-Handlebars

Express-Handlebars** A specialized wrapper for using Handlebars with Express.js, offering better integration and configuration options.

Install express-handlebar: ⭐

npm install express-handlebars

Directory Structure:

.
β”œβ”€β”€ app.js
└── views
    β”œβ”€β”€ home.handlebars
    └── layouts
        └── main.handlebars

2 directories, 3 files

app.js:

Creates a super simple Express app which shows the basic way to register a Handlebars view engine using this package.

import express from 'express';
import { engine } from 'express-handlebars'; // import express-handlebars ⭐
 
const app = express();
 
 
app.engine('handlebars', engine()); // Registers Handlebars as the template engine for Express.
app.set('view engine', 'handlebars'); // Sets Handlebars as the default view engine for rendering templates.
app.set('views', './views');
 
app.get('/', (req, res) => {
    res.render('home');
});
 
app.listen(3000);

res.render('home'): This tells Express to render the home view template (in this case, a file named home.handlebars, or whatever your configured view engine is using).

views/layouts/main.handlebars: The main layout is the HTML page wrapper which can be reused for the different views of the app. {{{body}}} ⭐ is used as a placeholder for where the main content should be rendered

...
<body>
	{{{body}}}
</body>
...

Note:

views/home.handlebars: The content for the app's home view which will be rendered into the layout'sΒ {{{body}}}.

<h1>Example App: Home</h1>

Note: There will be a main.handlebars in /views/layouts directory, that will contain html syntax, and will be reused for different pages like home.handlebars, blogs.handlebars in /view directory. Including common Content on main.handlebars, This prevent us from making, header, footer and other components copy paste for different pages.


Now Continue our Express Application with Handlebars

Update index.js

//index.js
const express = require('express')
// import handlebars
var exphbs = require('express-handlebars')
 
const path = require('path')
const app = express()
const port = 3000
 
 
app.engine('handlebars', engine());
app.set('view engine', 'handlebars');
app.use(express.static(path.join(__dirname, "static")))
app.use('/', require(path.join(__dirname, `routes/blogRoute.js` )))
 
app.listen(port, () => {
  console.log(`Blog app listening at http://localhost:${port}`)
})

Update blogRoute.js

// blogRoute.js
const express = require('express')
const router = express.Router()
const path = require('path')
const blogs = rquire('../data/blogs')
 
router.get('/', (req, res)=>{
	// handle bar syntax to render `home.handlebars`
	res.render('home');
})
 
router.get('/blog', (req, res)=>{
	// handle bar syntax to render `blogHome.handlebars`
	res.render('blogHome', {
	// <key used in the Handlebars template> : <variable from your Express application containing the data>
	blogs: blogs
	});
})
 
 
router.get('/blogpost/:slug', (req, res)=>{
	myBlog = blogs.filter((elem)=>{
		return elem.slug == req.params.slug
	})
	// +++++++++++++++++++++++
	res.render('blogPage', {
		title: myBlog[0].title,
		content: myBlog[0].content})
		// myBlog is array so used myBlog[0] to send only one blogPost.
	 //+++++++++++++++++++++
});
 
module.exports = router```
 
Create main.handlebars,
```handlebars
...
<body>
	</nav>
	...
	<a href="/blog"> Blog </a>
	...
	</nav>
	{{{body}}}
</body>
...

We added links to route to /blog

Create home.handlebars

this is home.handlebars.

Create blogHome.handlebars

{{#each blogs}}
	<div class="blog">
		<a href="/blogpost/{{this.slug}}"></a>
		<h2> {{this.title}}</h2>
	</div>
	{{/each}}

Note: the variables in .handlebars, like blog , this etc are javascript variable comes from the express app

Note: Helpers in Handlebars are custom functions that you can use within your templates to perform operations or transformations on data. They help keep templates clean by moving logic into reusable functions. (e.g., {{#if}}, {{#each}}).

Create blogPage.handlebars (Page for Each Posts)

<h2>{{title}}</h2>
<p>
	{{content}}
</p>

This was the Basic Structure of the blog post

Final blog App, File Directory Structures

project
β”œβ”€β”€ index.js
β”œβ”€β”€ routes
β”‚      └── blogRoute.js
└── views
    β”œβ”€β”€ home.handlebars
    β”œβ”€β”€ bloghome.handlebars
    β”œβ”€β”€ blogPage.handlebars
    └── layouts
        └── main.handlebars

Additionally , We can use mongoose to connect to the MongoDB Database : )


Remaining video is on hosting

Host on DigitalOcean

DigitalOcean is a cloud computing service provider that offers scalable virtual servers known as Droplets. Droplets are customizable virtual private servers (VPS) used for hosting applications, websites, and databases. DigitalOcean provides a user-friendly platform with features like pre-configured server images, managed databases, and scalable resources.

Hosting Express/Nodejs

  1. Create a Droplet:

    • Sign up for DigitalOcean and create a Droplet with your desired specifications (e.g., OS, size).
  2. Set Up Your Server:

    • SSH into your Droplet using the credentials provided.
    • Update the server and install Node.js and npm.
    • Transfer your Express app code to the server (e.g., using scp, Git, or FTP).
  3. Install Dependencies:

    • Navigate to your app directory and run npm install to install dependencies.
  4. Run Your Express App:

    • Start your app using node app.js or a process manager like PM2 (pm2 start app.js).
  5. Configure a Reverse Proxy (optional but recommended):

    • Install and configure Nginx to act as a reverse proxy for better performance and security.
  6. Set Up a Domain and SSL (optional):

    • Point your domain to your Droplet’s IP and set up SSL for secure connections (e.g., using Certbot).

Benefits of Hosting on DigitalOcean

This setup allows you to deploy and manage your Express application on a reliable cloud platform.


βœ… Completed