Node.js
Node.js
js
Introduction to Express.js
• Node.js requires writing a lot of code for basic tasks like extracting the
body of an incoming request or handling routing.
• Express.js is a third-party framework that simplifies these tasks,
allowing developers to focus on business logic (the core functionality of
the application).
• It provides a rule set and utility functions to write cleaner and more
efficient code.
3. Routing:
o Express.js allows developers to define routes for
different URLs or paths without writing multiple if statements.
o Example:
app.get('/about', (req, res) => {
res.send('About Page');
});
Key Vocabulary
• Node.js: A runtime environment for executing JavaScript on the server.
• Express.js: A web application framework for Node.js.
• Middleware: Functions that process requests before they reach the final
route handler.
• Routing: Defining how an application responds to client requests for
specific endpoints (URLs).
• Business Logic: The core functionality of an application, such as
processing data or handling user interactions.
Summary
• Express.js is a powerful framework built on top of Node.js that
simplifies web development by handling common tasks like routing,
request/response handling, and serving static files.
• It uses middleware to modularize code and provides tools to focus
on business logic.
• By using Express.js, developers can write cleaner, more maintainable,
and efficient code.
Notes on Express.js
What is Express.js?
• Express.js is a framework for Node.js that simplifies server-side logic.
• It helps developers avoid writing complex code for tasks like parsing
incoming requests (e.g., extracting the body of a request).
• Without Express.js, developers would need to manually handle events
like data and end, create buffers, and convert data to strings.
Alternatives to Express.js
• Vanilla Node.js: Can be used for simpler applications or for developers
seeking more control.
• Other Frameworks:
o Adonis.js: Inspired by Laravel (PHP framework).
o Koa: A lightweight alternative to Express.js.
o Sails.js: A framework for building data-driven APIs.
• Express.js is the most popular and widely used framework for Node.js.
Key Vocabulary
• Express.js: A web application framework for Node.js.
• Framework: A set of tools, helper functions, and rules for building
applications.
• Business Logic: The core functionality that defines an application’s
unique features.
• Request Parsing: Extracting and processing data from incoming HTTP
requests.
• Third-Party Packages: External libraries or tools that can be integrated
into a project.
2. Basic Setup:
Javascript:
const express = require('express');
const app = express();
Summary
• Express.js simplifies server-side development by handling repetitive
tasks and providing a structured way to build applications.
• It allows developers to focus on business logic while outsourcing low-
level details like request parsing and routing.
• Express.js is flexible, extensible, and supported by a large ecosystem of
third-party packages.
• While alternatives exist, Express.js remains the most popular framework
for Node.js.
Installing and Setting Up Express.js
Installation of Express.js
1. Command: Install as a production dependency (essential for
deployment):
Bash:
npm install --save express
o Why --save? Express.js is a core part of the application, not just a
development tool.
o Updates dependencies in package.json.
Setting Up Express.js
1. Importing:
Javascript:
const express = require('express');
const app = express(); // Initialize the Express app
o express exports a function that initializes the framework.
o The app constant manages Express.js logic (e.g., routing,
middleware).
2. Code Organization:
o Separate imports for clarity (optional but recommended):
javascript
// Core Node.js modules
const http = require('http');
// Third-party packages
const express = require('express');
// Custom modules (if any)
// const myModule = require('./myModule');
Key Concepts
1. Request Handler:
o The app object is a valid request handler and can be passed
to http.createServer():
Javascript:
const server = http.createServer(app);
server.listen(3000);
2. Initial Behavior:
o Without defined routes, the app responds with no content but sets
up Express.js’s request-handling pipeline.
Example Code
Javascript:
const express = require('express');
const app = express();
Summary
• Express.js is installed as a production dependency with npm install --
save express.
• Initialize the app with const app = express();, which creates a request
handler for managing server logic.
• The app object simplifies server creation (via app.listen()) and defines
Express.js’s structure for handling requests.
• No routes or logic are added initially, but Express.js sets up its
foundational request-handling workflow.
Key Vocabulary
• Production Dependency: A package required for the application to run
in production.
• Request Handler: Code that processes incoming HTTP requests
(e.g., app in Express.js).
• Express.js Pipeline: The structured flow of middleware and routes for
handling requests.
Express.js Middleware
2. Arguments in Middleware:
o req: The request object (contains data about the incoming
request).
o res: The response object (used to send back data).
o next: A function that passes the request to the next middleware in
line.
3. Critical Rules:
o Call next() to allow the request to proceed to the next middleware.
o Send a response (e.g., res.send()) if you don’t
call next() (otherwise, the request hangs).
// Middleware 2
app.use((req, res, next) => {
console.log('Middleware 2');
res.send('Response sent!'); // End the request here
});
• Result:
o Request passes through Middleware 1, then Middleware 2.
o res.send() in Middleware 2 stops further processing.
Key Vocabulary
• Middleware: Functions that process requests in Express.js.
• app.use(): Method to register middleware.
• next(): Function to pass control to the next middleware.
• Request Pipeline: The sequential flow of middleware functions.
Common Pitfalls
• Not calling next():
o The request stalls indefinitely unless a response is sent.
o Example of a blocking middleware:
Javascript:
app.use((req, res, next) => {
console.log('This blocks the request!');
// No call to next() or res.send() →
request hangs
});
Summary
• Middleware is central to Express.js, enabling modular and organized
request handling.
• Use app.use() to add middleware, next() to forward requests,
and res.send() to terminate processing.
• Middleware executes top-to-bottom; order matters.
• Always ensure a response is sent or next() is called to avoid hanging
requests.
Sending Responses in Express.js Middleware
Key Concepts
1. Middleware Execution Flow:
o Requests travel through middleware functions top-to-bottom.
o Use next() to pass control to the next middleware.
o If no next() is called and no response is sent, the request stalls
indefinitely.
2. Sending Responses:
o Use res.send() to send a response and terminate the request.
o res.send() automatically sets the Content-Type header based on
the response body (e.g., text/html for HTML).
o Example:
javascript
app.use((req, res) => {
res.send('<h1>Hello from Express</h1>');
});
Middleware Behavior
1. Terminating Middleware:
o If a middleware sends a response (e.g., res.send()), subsequent
middleware will not execute.
o Example:
Javascript:
app.use((req, res) => {
res.send('Response sent!'); // Terminates the
request
});
2. Non-Terminating Middleware:
o Use next() to pass control to the next middleware.
o Example:
Javascript:
app.use((req, res, next) => {
console.log('Middleware 1');
next(); // Pass to Middleware 2
});
Example Code
Javascript:
const express = require('express');
const app = express();
// Middleware 1
app.use((req, res, next) => {
console.log('Middleware 1');
next(); // Pass to Middleware 2
});
// Middleware 2
app.use((req, res) => {
res.send('<h1>Hello from Express</h1>'); //
Terminates the request
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• Middleware: Functions that process requests in Express.js.
• res.send(): Method to send a response and terminate the request.
• next(): Function to pass control to the next middleware.
• Content-Type: HTTP header indicating the type of response data.
Summary
• Middleware functions process requests in a top-to-bottom sequence.
• Use res.send() to send responses and terminate requests; it automatically
sets Content-Type.
• Call next() to pass control to the next middleware; otherwise, the request
stalls.
• res.send() simplifies response handling compared to manual methods
like res.write() and res.end().
Express.js Internals and Code Optimization
o Use app.listen():
Javascript:
app.listen(3000, () => {
console.log('Server running on port
3000');
});
2. Benefits:
o Reduces boilerplate code.
o Improves readability and maintainability.
Example Code
Javascript:
const express = require('express');
const app = express();
// Middleware example
app.use((req, res, next) => {
console.log('Middleware executed');
next();
});
// Route handler
app.use((req, res) => {
res.send('<h1>Hello from Express</h1>');
});
// Start server
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• res.send(): Express.js method to send responses with automatic Content-
Type handling.
• app.listen(): Simplified method to start an Express.js server.
• Middleware: Functions that process requests in a sequence.
• Content-Type: HTTP header indicating the type of response data.
Summary
• Express.js Internals:
o res.send() automatically sets Content-Type based on the response
data.
o app.listen() simplifies server setup by internally
calling http.createServer().
• Code Optimization:
o Use app.listen() to reduce boilerplate and improve readability.
• Middleware:
o Requests flow through middleware functions top-to-bottom.
o Use next() to pass control or res.send() to terminate the request.
Next Steps:
• Learn how to handle different routes (e.g., /message, /home).
• Simplify reading incoming request data.
Routing and Middleware in Express.js
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Concepts
1. Path Filtering:
o The path in app.use(path, callback) matches the starting part of
the URL.
o Example: /add-product matches /add-product, /add-product/123,
etc.
3. Sending Responses:
o Use res.send() to send a response and terminate the request.
o Avoid calling next() after sending a response to prevent errors.
Common Pitfalls
1. Overlapping Paths:
o Ensure specific routes are placed before general routes to avoid
unintended matches.
o Example:
Javascript:
app.use('/add-product', (req, res) => {
res.send('<h1>Add Product Page</h1>');
});
2. Multiple Responses:
o Sending more than one response per request results in an error.
o Example of incorrect usage:
Javascript:
app.use((req, res) => {
res.send('First response');
res.send('Second response'); // Error!
});
Key Vocabulary
• Middleware: Functions that process requests in Express.js.
• app.use(path, callback): Method to filter requests by URL path.
• next(): Function to pass control to the next middleware.
• Path Filtering: Matching requests based on the starting part of the URL.
Summary
• Use app.use(path, callback) to handle specific routes (e.g., /add-
product).
• Middleware executes top-to-bottom; order matters for routing and
functionality.
• Send one response per request using res.send() and avoid
calling next() afterward.
• Place general middleware at the top and specific routes below to ensure
proper request handling.
Next Steps:
• Learn how to handle dynamic routes (e.g., /products/:id).
• Simplify reading incoming request data (e.g., query parameters, request
body).
Handling Incoming Requests in Express.js
o Configure body-parser:
Javascript:
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended:
false }));
o req.body will contain the parsed form data as a JavaScript object
(e.g., { title: 'Book' }).
// Default route
app.use('/', (req, res) => {
res.send('<h1>Hello from Express</h1>');
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Concepts
1. Form Handling:
o Use <form> tags to create HTML forms.
o Set action to the URL where the form data should be sent.
o Set method to POST for form submissions.
2. Request Body Parsing:
o body-parser middleware parses form data and
populates req.body.
o req.body contains key-value pairs based on the form inputs (e.g., {
title: 'Book' }).
o
3. Redirecting Responses:
o Use res.redirect(path) to redirect users to another route.
Common Pitfalls
1. Missing Body Parser:
o Without body-parser, req.body will be undefined.
o Ensure body-parser is configured before route handlers.
3. Order of Middleware:
o Place body-parser middleware before route handlers to ensure
request bodies are parsed.
Key Vocabulary
• body-parser: Middleware to parse incoming request bodies.
• req.body: Object containing parsed form data.
• res.redirect(path): Method to redirect users to another route.
• Form Handling: Managing user input via HTML forms and processing
submissions.
Summary
• Use res.send() to return HTML forms and handle user input.
• Install and configure body-parser to parse form data into req.body.
• Use res.redirect() to redirect users after processing form submissions.
• Ensure middleware order is correct (e.g., body-parser before route
handlers).
Next Steps:
• Learn how to handle JSON data and file uploads in Express.js.
• Explore route-specific middleware for more advanced routing.
Filtering Requests by HTTP Method in Express.js
2. Solution:
o Use app.get() and app.post() to filter requests by HTTP method.
o app.get(path, callback): Executes only for GET requests.
o app.post(path, callback): Executes only for POST requests.
3. Example:
Javascript:
// Handle GET requests to /product
app.get('/product', (req, res) => {
res.send('This is a GET request to /product');
});
2. Method-Specific Middleware:
o app.get(): Filters for GET requests.
o app.post(): Filters for POST requests.
o app.use(): Executes for all HTTP methods.
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• app.get(): Middleware for handling GET requests.
• app.post(): Middleware for handling POST requests.
• HTTP Methods: Actions like GET, POST, DELETE, PATCH, PUT.
• body-parser: Middleware to parse incoming request bodies.
Summary
• Use app.get() and app.post() to filter requests by HTTP method.
• app.use() executes for all HTTP methods,
while app.get() and app.post() are method-specific.
• Combine body-parser with app.post() to handle form submissions and
parse request bodies.
• Ensure proper routing by placing method-specific middleware before
general middleware.
Next Steps:
• Explore handling DELETE, PATCH, and PUT requests for APIs.
• Learn how to serve static files (e.g., CSS, images) in Express.js.
Organizing Routes with Express Router
module.exports = router;
2. routes/shop.js:
javascript:
const express = require('express');
const router = express.Router();
// GET request to /
router.get('/', (req, res) => {
res.send('<h1>Hello from Express</h1>');
});
module.exports = router;
3. app.js:
javascript:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// Use routes
app.use(adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Concepts
1. Express Router:
o A pluggable mini app for defining routes in separate files.
o Use router.get(), router.post(), etc., to define method-specific
routes.
2. Route Organization:
o Store related routes in separate files (e.g., admin.js, shop.js).
o Export routers and import them into the main app.
3. Order of Middleware:
o The order in which routes are registered (app.use()) matters.
o Exact matching is enforced by router.get(), router.post(), etc.
Key Vocabulary
• Express Router: A feature to define and organize routes in separate files.
• router.get(): Method to handle GET requests in a router.
• router.post(): Method to handle POST requests in a router.
• Middleware Order: The sequence in which middleware and routes are
registered.
Summary
• Use Express Router to split routes into separate files for better
organization.
• Define routes using router.get(), router.post(), etc., and export the router.
• Import and use routers in the main app with app.use().
• Pay attention to the order of middleware and route registration to ensure
proper request handling.
Next Steps:
• Explore route prefixes (e.g., /admin/add-product) for better route
organization.
• Learn how to handle 404 errors and other edge cases in Express.js.
Handling 404 Errors in Express.js
2. Solution:
o Add a catch-all middleware at the bottom of the middleware
stack to handle unhandled routes.
o Use app.use() without a path filter to match all requests.
Key Concepts
1. Middleware Execution Order:
o Requests are funneled through middleware top-to-bottom.
o If no middleware handles the request, it reaches the catch-all
middleware.
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// Use routes
app.use(adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• Catch-all Middleware: Middleware that handles all unhandled requests.
• res.status(code): Method to set the HTTP status code (e.g., 404 for "Not
Found").
• res.send(): Method to send a response to the client.
• Middleware Execution Order: The sequence in which middleware
processes requests.
Summary
• Add a catch-all middleware at the bottom of the middleware stack to
handle unhandled routes.
• Use res.status(404) to set the status code to 404 and res.send() to return
a custom error page.
• Ensure the catch-all middleware is placed after all other routes to avoid
overriding valid routes.
Next Steps:
• Explore serving static files (e.g., CSS, images) for a more polished 404
page.
• Learn how to handle 500 errors (server errors) in Express.js.
Route Prefixing with Express Router
Route Prefixing
1. Problem:
o Routes in a file often share a common starting
path (e.g., /admin/add-product, /admin/edit-product).
o Repeating the prefix (e.g., /admin) in every route is redundant.
2. Solution:
o Use route prefixing to define a common starting path in the main
app file (e.g., app.js).
o Example:
Javascript:
app.use('/admin', adminRoutes);
o This ensures all routes in adminRoutes are prefixed with /admin.
Key Concepts
1. Route Prefixing:
o Adds a common starting path to all routes in a router file.
o The prefix is stripped when matching routes in the router file.
2. How It Works:
o A request to /admin/add-product is matched to /add-product in
the adminRoutes file.
o The /admin prefix is ignored during route matching in the router
file.
3. Benefits:
o Reduces redundancy by avoiding repetition of the common path
in every route.
o Improves code organization and readability.
module.exports = router;
2. app.js:
javascript:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• Route Prefixing: Adding a common starting path to all routes in a router
file.
• app.use(path, router): Method to apply a prefix to all routes in a router.
• Stripped Prefix: The prefix is ignored during route matching in the
router file.
Summary
• Use route prefixing to avoid repeating a common starting path in every
route.
• Define the prefix in the main app file (e.g., app.use('/admin',
adminRoutes)).
• The prefix is stripped when matching routes in the router file
(e.g., /admin/add-product becomes /add-product).
• Improves code organization and reduces redundancy.
Next Steps:
• Explore nested routers for more complex route structures.
• Learn how to handle dynamic routes (e.g., /products/:id) in Express.js.
Serving HTML Files in Express.js
2. Solution:
o Store HTML files in a views folder (or any folder of your choice).
o Use res.sendFile() to serve these files in response to requests.
Key Concepts
1. Folder Structure:
o Create a views folder to store HTML files (e.g., shop.html, add-
product.html).
o This aligns with the MVC (Model-View-Controller) pattern,
where views represent the user interface.
2. HTML Files:
o add-product.html: Contains a form for adding products.
o shop.html: Displays a list of products (to be populated
dynamically later).
3. Serving Files:
o Use res.sendFile() to send HTML files as responses.
o Example:
Javascript:
res.sendFile(path.join(__dirname, 'views',
'shop.html'));
2. views/add-product.html:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-
width, initial-scale=1.0">
<title>Add Product</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="/">Shop</a></li>
<li><a href="/add-product">Add
Product</a></li>
</ul>
</nav>
</header>
<main>
<form action="/add-product" method="POST">
<input type="text" name="title"
placeholder="Product Title">
<button type="submit">Add Product</button>
</form>
</main>
</body>
</html>
Run HTML
3. views/shop.html:
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-
width, initial-scale=1.0">
<title>Shop</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="/">Shop</a></li>
<li><a href="/add-product">Add
Product</a></li>
</ul>
</nav>
</header>
<main>
<h1>My Products</h1>
<!-- Product list will be added dynamically
later -->
</main>
</body>
</html>
Run HTML
4. routes/admin.js:
javascript:
const express = require('express');
const path = require('path');
const router = express.Router();
module.exports = router;
5. routes/shop.js:
javascript
const express = require('express');
const path = require('path');
const router = express.Router();
// GET request to /
router.get('/', (req, res) => {
res.sendFile(path.join(__dirname,
'../views/shop.html'));
});
module.exports = router;
6. app.js:
javascript:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// Use routes
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• views Folder: Stores HTML files representing the user interface.
• res.sendFile(): Method to send an HTML file as a response.
• MVC Pattern: A design pattern separating an application
into Model, View, and Controller.
Summary
• Store HTML files in a views folder for better organization.
• Use res.sendFile() to serve HTML files in response to requests.
• Align your folder structure with the MVC pattern for scalability.
• Serve add-product.html and shop.html for their respective routes.
Next Steps:
• Add styling to the HTML files using CSS.
• Learn how to use templating engines (e.g., EJS, Pug) for dynamic
content.
Serving HTML Files in Express.js
Key Concepts
1. Folder Structure:
o Store HTML files in a views folder (e.g., shop.html, add-
product.html).
o Example:
project/
├── views/
│ ├── shop.html
│ └── add-product.html
├── routes/
│ ├── admin.js
│ └── shop.js
└── app.js
2. Serving Files:
o Use res.sendFile() to send HTML files as responses.
o Example:
javascript
res.sendFile(path.join(__dirname,
'../views/shop.html'));
3. Path Construction:
o Use path.join() to build file paths that work on
both Linux and Windows.
o __dirname: A global variable in Node.js that provides the absolute
path to the current file's directory.
o Use ../ to navigate up one directory level.
// GET request to /
router.get('/', (req, res) => {
res.sendFile(path.join(__dirname,
'../views/shop.html'));
});
module.exports = router;
2. routes/admin.js:
javascript:
const express = require('express');
const path = require('path');
const router = express.Router();
module.exports = router;
3. app.js:
javascript:
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
// Use routes
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• views Folder: Stores HTML files representing the user interface.
• res.sendFile(): Method to send an HTML file as a response.
• path.join(): Method to construct file paths compatible across operating
systems.
• __dirname: Global variable providing the absolute path to the current
file's directory.
Summary
• Store HTML files in a views folder for better organization.
• Use res.sendFile() to serve HTML files in response to requests.
• Construct file paths using path.join() and __dirname for cross-platform
compatibility.
• Serve shop.html and add-product.html for their respective routes.
Next Steps:
• Add a 404 error page (e.g., 404.html) and serve it for unhandled routes.
• Add styling to the HTML files using CSS.
• Learn how to use templating engines (e.g., EJS, Pug) for dynamic
content.
Serving a 404 Error Page in Express.js
2. Solution:
o Create a 404.html file in the views folder.
o Use res.sendFile() to serve this file for unhandled routes.
o Set the HTTP status code to 404 using res.status(404).
Key Concepts
1. 404 Error Page:
o A custom HTML page displayed when a requested resource is not
found.
o Example:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-
scale=1.0">
<title>Page Not Found</title>
</head>
<body>
<h1>Page Not Found</h1>
</body>
</html>
Run HTML
2. views/404.html:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-
width, initial-scale=1.0">
<title>Page Not Found</title>
</head>
<body>
<h1>Page Not Found</h1>
</body>
</html>
Run HTML
3. app.js:
javascript
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// Use routes
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Key Vocabulary
• 404 Error Page: A custom HTML page displayed when a requested
resource is not found.
• res.sendFile(): Method to send an HTML file as a response.
• res.status(code): Method to set the HTTP status code (e.g., 404 for "Not
Found").
• path.join(): Method to construct file paths compatible across operating
systems.
Summary
• Create a 404.html file in the views folder to handle unhandled routes.
• Use res.sendFile() to serve the 404.html file for unhandled routes.
• Set the HTTP status code to 404 using res.status(404).
• Construct the file path using path.join() and __dirname for cross-
platform compatibility.
Next Steps:
• Add styling to the 404.html page using CSS.
• Explore serving static files (e.g., CSS, images) in Express.js.
• Learn how to use templating engines (e.g., EJS, Pug) for dynamic
content.
Path Management in Express.js
2. Solution:
o Create a helper function to dynamically determine the root
directory path.
o Use path.dirname() and process.mainModule.filename to get the
root directory path.
Key Concepts
1. Root Directory Path:
o The path to the root folder of the project (where app.js is located).
o Use process.mainModule.filename to get the path to the file that
started the application (e.g., app.js).
o Use path.dirname() to get the directory name of a file path.
2. Helper Function:
o Create a util/path.js file to export the root directory path.
o Example:
javascript
const path = require('path');
module.exports =
path.dirname(process.mainModule.filename);
3. Using the Helper Function:
o Import the root directory path in route files
(e.g., shop.js, admin.js).
o Use it to construct paths to files in the views folder.
2. util/path.js:
javascript:
const path = require('path');
module.exports =
path.dirname(process.mainModule.filename);
3. routes/shop.js:
javascript:
const express = require('express');
const path = require('path');
const rootDir = require('../util/path');
const router = express.Router();
// GET request to /
router.get('/', (req, res) => {
res.sendFile(path.join(rootDir, 'views',
'shop.html'));
});
module.exports = router;
4. routes/admin.js:
javascript:
const express = require('express');
const path = require('path');
const rootDir = require('../util/path');
const router = express.Router();
module.exports = router;
Key Vocabulary
• Root Directory: The main folder of the project (e.g., where app.js is
located).
• process.mainModule.filename: Global variable providing the path to the
file that started the application.
• path.dirname(): Method to get the directory name of a file path.
• Helper Function: A reusable function to simplify repetitive tasks (e.g.,
path construction).
Summary
• Use process.mainModule.filename and path.dirname() to dynamically
determine the root directory path.
• Create a helper function in util/path.js to export the root directory path.
• Import and use the root directory path in route files to construct paths to
the views folder.
• This approach ensures cleaner and more maintainable code.
Next Steps:
• Add styling to the HTML files using CSS.
• Explore serving static files (e.g., CSS, images) in Express.js.
• Learn how to use templating engines (e.g., EJS, Pug) for dynamic
content.
Adding CSS Styling to Express.js Applications
Key Concepts
1. External CSS Files:
o Store CSS styles in a public/css folder (e.g., main.css).
o Example:
css
/* main.css */
body {
font-family: sans-serif;
margin: 0;
padding: 0;
}
.main-header {
width: 100%;
height: 3.5rem;
background-color: #ffd700;
padding: 0 1.5rem;
}
.main-header__nav {
height: 100%;
display: flex;
align-items: center;
}
.main-header__item-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
.main-header__item {
margin: 0 1rem;
}
.main-header__item a {
text-decoration: none;
color: black;
}
.main-header__item a:hover,
.main-header__item a:active {
color: #800080;
}
.main-header {
width: 100%;
height: 3.5rem;
background-color: #ffd700;
padding: 0 1.5rem;
}
.main-header__nav {
height: 100%;
display: flex;
align-items: center;
}
.main-header__item-list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
.main-header__item {
margin: 0 1rem;
}
.main-header__item a {
text-decoration: none;
color: black;
}
.main-header__item a:hover,
.main-header__item a:active {
color: #800080;
}
3. app.js:
javascript:
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
// Import routes
const adminRoutes = require('./routes/admin');
const shopRoutes = require('./routes/shop');
// Use routes
app.use('/admin', adminRoutes);
app.use(shopRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});
4. views/shop.html:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-
width, initial-scale=1.0">
<link rel="stylesheet" href="/css/main.css">
<title>Shop</title>
</head>
<body>
<header class="main-header">
<nav class="main-header__nav">
<ul class="main-header__item-list">
<li class="main-header__item"><a href="/"
class="active">Shop</a></li>
<li class="main-header__item"><a
href="/admin/add-product">Add Product</a></li>
</ul>
</nav>
</header>
<main>
<h1>My Products</h1>
</main>
</body>
</html>
Run HTML
Key Vocabulary
• Static Files: Files like CSS, images, and JavaScript that don’t change
dynamically.
• express.static(): Middleware to serve static files in Express.js.
• External CSS: CSS styles stored in separate files for better organization
and reusability.
Summary
• Move CSS styles to external files (e.g., main.css) for better
maintainability.
• Use express.static() to serve static files (e.g., CSS, images) from
the public folder.
• Link external CSS files in the HTML <head> section using <link>.
• This approach ensures cleaner code and better scalability.
Next Steps:
• Add JavaScript functionality to the application.
• Explore using templating engines (e.g., EJS, Pug) for dynamic content.
• Learn how to handle file uploads and user authentication in Express.js.
Serving Static Files in Express.js
Key Concepts
1. Static Files:
o Files like CSS, JavaScript, and images that don’t change
dynamically.
o Store in a public folder (conventionally named).
2. express.static() Middleware:
o Built-in Express.js middleware to serve static files.
o Syntax:
Javascript:
app.use(express.static(path.join(__dirname,
'public')));
o public folder becomes accessible to clients
(e.g., /css/main.css maps to public/css/main.css).
3. Path Handling:
o Use path.join() to construct OS-agnostic paths.
o Example:
Javascript:
const path = require('path');
app.use(express.static(path.join(__dirname,
'public')));
Example Code
1. Folder Structure:
project/
├── public/
│ └── css/
│ ├── main.css
│ └── product.css
├── views/
│ ├── shop.html
│ ├── add-product.html
│ └── 404.html
└── app.js
o In add-product.html:
html
<head>
<link rel="stylesheet"
href="/css/main.css">
<link rel="stylesheet"
href="/css/product.css">
</head>
Run HTML
Key Vocabulary
• express.static(): Middleware to serve static files (CSS, JS, images).
• Static Files: Non-dynamic files served directly to clients.
• public Folder: Directory for static files accessible to users.
Summary
• Use express.static() to serve static files from the public folder.
• Link external CSS/JS files in HTML using relative paths
(e.g., /css/main.css).
• Improves code maintainability and scalability by separating static
assets.
Express.js Fundamentals
2. Middleware:
o Middleware functions process incoming requests and responses.
o Key components:
▪ req: The request object (incoming data).
▪ res: The response object (outgoing data).
▪ next: A function to pass control to the next middleware.
o Rules:
▪ Call next() to forward the request to the next middleware.
▪ Do not call next() if sending a response (e.g.,
using res.send()).
3. Request Filtering:
o Use app.use(path, callback) to filter requests by path.
o Use app.get(), app.post(), etc., to filter requests by HTTP
method.
o Exact matching: app.get() matches paths exactly,
while app.use() matches the beginning of the path.
4. Express Router:
o Use express.Router() to split routes into multiple files.
o Export the router and use it in the main app with app.use().
o Example:
Javascript:
const router = express.Router();
router.get('/path', (req, res) => { ... });
module.exports = router;
Key Vocabulary
• Middleware: Functions that process requests and responses in Express.js.
• req: The request object containing incoming data.
• res: The response object used to send data back to the client.
• next: Function to pass control to the next middleware.
• express.Router(): A mini Express app for organizing routes into separate
files.
• express.static(): Middleware to serve static files (e.g., CSS, JS, images).
Summary
• Express.js is a Node.js framework that simplifies web development
with middleware and routing.
• Middleware processes requests and responses, with next() forwarding
control to the next middleware.
• Use app.use(), app.get(), and app.post() to filter requests
by path and HTTP method.
• Organize routes with express.Router() for better code structure.
• Serve static files (e.g., CSS, JS) using express.static().
Next Steps:
• Learn to render dynamic content using templating engines (e.g., EJS,
Pug).
• Explore database integration (e.g., MongoDB, MySQL) for storing and
retrieving data.
• Implement user authentication and session management.
• Handle file uploads and data validation.