Node.js
Installation
- Download and Install: Visit the official Node.js website and download the installer for your operating system.
- Verify Installation:
node -v npm -v
Modules
Modules are reusable blocks of code in Node.js. They help in organizing code into manageable pieces.
CommonJS Modules
Node.js uses the CommonJS module system.
-
Exporting Modules:
// math.js function add(a, b) { return a + b; } module.exports = { add }; -
Importing Modules:
// app.js const math = require('./math'); console.log(math.add(2, 3)); // Output: 5
ES Modules
As of Node.js v12+, ES Modules are supported using the .mjs extension or by setting "type": "module" in package.json.
-
Exporting Modules:
// math.mjs export function add(a, b) { return a + b; } -
Importing Modules:
// app.mjs import { add } from './math.mjs'; console.log(add(2, 3)); // Output: 5
Built-in Modules
Node.js comes with several built-in modules to perform various tasks.
File System (fs)
Handles file operations.
-
Reading a File:
const fs = require('fs'); fs.readFile('example.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); }); -
Writing to a File:
fs.writeFile('example.txt', 'Hello, World!', (err) => { if (err) throw err; console.log('File written successfully'); });
Path (path)
Utilities for handling and transforming file paths.
-
Joining Paths:
const path = require('path'); const fullPath = path.join(__dirname, 'folder', 'file.txt'); console.log(fullPath); -
Resolving Paths:
const resolvedPath = path.resolve('folder/file.txt'); console.log(resolvedPath);
HTTP (http)
Creates HTTP servers and handles HTTP requests.
- Creating a Server:
const http = require('http'); const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello, World!\n'); }); server.listen(3000, () => { console.log('Server running at http://localhost:3000/'); });
Asynchronous Programming
Node.js is inherently asynchronous, allowing non-blocking operations.
Callbacks
Functions passed as arguments to handle asynchronous operations.
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
return;
}
console.log(data);
});Promises
Promises represent the eventual completion (or failure) of an asynchronous operation.
- Using Promises:
const fs = require('fs').promises; fs.readFile('example.txt', 'utf8') .then(data => console.log(data)) .catch(err => console.error(err));
Async/Await
Syntactic sugar over Promises for cleaner asynchronous code.
const fs = require('fs').promises;
async function readFile() {
try {
const data = await fs.readFile('example.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
}
readFile();Creating a Basic Server
Using the http module to create a simple server.
const http = require('http');
const server = http.createServer((req, res) => {
// Set response header
res.writeHead(200, { 'Content-Type': 'text/plain' });
// Send response body
res.end('Hello, Node.js!\n');
});
const PORT = 3000;
server.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});Package Management with npm
npm (Node Package Manager) is used to manage project dependencies.
Initializing a Project
Create a package.json file.
npm initFollow the prompts or use -y to accept defaults.
npm init -yInstalling Packages
-
Local Installation:
npm install express -
Global Installation:
npm install -g nodemon -
Saving as a Dependency:
npm install lodash --save -
Saving as a Dev Dependency:
npm install jest --save-dev
package.json
Defines project metadata and dependencies.
{
"name": "my-app",
"version": "1.0.0",
"description": "A sample Node.js application",
"main": "app.js",
"scripts": {
"start": "node app.js",
"dev": "nodemon app.js",
"test": "jest"
},
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.20",
"jest": "^29.0.0"
},
"author": "Your Name",
"license": "ISC"
}Express.js
Introduction
Express.js is a minimal and flexible Node.js web application framework that provides robust features for building single and multi-page, and hybrid web applications.
Installation
Install Express locally within your project.
npm install expressCreating an Express App
// app.js
const express = require('express');
const app = express();
const PORT = 3000;
// Define a route
app.get('/', (req, res) => {
res.send('Hello, Express!');
});
// Start the server
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});Middleware
Middleware functions are functions that have access to the request (req) and response (res) objects, and the next function in the request-response cycle.
Built-in Middleware
-
express.json(): Parses incoming JSON requests.app.use(express.json()); -
express.urlencoded(): Parses incoming requests with URL-encoded payloads.app.use(express.urlencoded({ extended: true }));
Third-party Middleware
-
morgan: HTTP request logger middleware.npm install morganconst morgan = require('morgan'); app.use(morgan('dev')); -
cors: Enables Cross-Origin Resource Sharing.npm install corsconst cors = require('cors'); app.use(cors());
Custom Middleware
// Custom logging middleware
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});Routing
Routing defines how an application responds to client requests for specific endpoints.
Basic Routing
app.get('/about', (req, res) => {
res.send('About Page');
});
app.post('/submit', (req, res) => {
res.send('Form Submitted');
});Route Parameters
Parameters captured in the URL.
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.send(`User ID: ${userId}`);
});Query Parameters
Parameters sent in the query string.
app.get('/search', (req, res) => {
const query = req.query.q;
res.send(`Search Query: ${query}`);
});Handling Requests and Responses
Request (req) Object
Contains information about the HTTP request.
-
Accessing Body:
app.post('/data', (req, res) => { const data = req.body; res.json(data); }); -
Accessing Headers:
app.get('/headers', (req, res) => { const userAgent = req.headers['user-agent']; res.send(`User-Agent: ${userAgent}`); });
Response (res) Object
Methods to send responses to the client.
-
res.send(): Sends a response of various types.res.send('Hello World'); -
res.json(): Sends a JSON response.res.json({ message: 'Hello, JSON' }); -
res.status(): Sets the HTTP status for the response.res.status(404).send('Not Found'); -
res.redirect(): Redirects to a different URL.res.redirect('/login');
Error Handling
Proper error handling is crucial for building robust applications.
Error-handling Middleware
Error-handling middleware has four arguments: err, req, res, and next.
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});Serving Static Files
Serve static assets like HTML, CSS, JavaScript, and images.
app.use(express.static('public'));
// Now, files in the 'public' directory can be accessed directly.
// e.g., http://localhost:3000/images/logo.pngUsing Routers
Organize routes using express.Router.
// routes/users.js
const express = require('express');
const router = express.Router();
// Define routes
router.get('/', (req, res) => {
res.send('User List');
});
router.get('/:id', (req, res) => {
res.send(`User ID: ${req.params.id}`);
});
module.exports = router;// app.js
const express = require('express');
const app = express();
const userRoutes = require('./routes/users');
app.use('/users', userRoutes);
app.listen(3000, () => {
console.log('Server running on port 3000');
});Template Engines
Render dynamic HTML pages.
Using Pug
-
Installation:
npm install pug -
Setup:
app.set('view engine', 'pug'); app.set('views', './views'); -
Creating a View:
// views/index.pug html head title= title body h1 Hello, #{name}! -
Rendering the View:
app.get('/', (req, res) => { res.render('index', { title: 'Home', name: 'John' }); });
Using EJS
-
Installation:
npm install ejs -
Setup:
app.set('view engine', 'ejs'); app.set('views', './views'); -
Creating a View:
<!-- views/index.ejs --> <!DOCTYPE html> <html> <head> <title><%= title %></title> </head> <body> <h1>Hello, <%= name %>!</h1> </body> </html> -
Rendering the View:
app.get('/', (req, res) => { res.render('index', { title: 'Home', name: 'Jane' }); });
Environment Variables
Use environment variables to manage configuration.
-
Installation:
npm install dotenv -
Setup:
require('dotenv').config(); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); -
.envFile:PORT=4000 DB_URI=mongodb://localhost:27017/mydb
Integration with Databases
Connect your Express app to a database for data persistence.
Using Mongoose with MongoDB
-
Installation:
npm install mongoose -
Setup and Connection:
const mongoose = require('mongoose'); mongoose.connect(process.env.DB_URI, { useNewUrlParser: true, useUnifiedTopology: true, }) .then(() => console.log('MongoDB connected')) .catch(err => console.error(err)); -
Defining a Schema and Model:
const userSchema = new mongoose.Schema({ name: String, email: String, password: String, }); const User = mongoose.model('User', userSchema); -
CRUD Operations:
// Create a new user app.post('/users', async (req, res, next) => { try { const user = new User(req.body); await user.save(); res.status(201).json(user); } catch (err) { next(err); } }); // Read all users app.get('/users', async (req, res, next) => { try { const users = await User.find(); res.json(users); } catch (err) { next(err); } });
Additional Topics
Security
Enhance the security of your Express applications.
-
Helmet: Helps secure Express apps by setting various HTTP headers.
npm install helmetconst helmet = require('helmet'); app.use(helmet()); -
Rate Limiting: Prevents brute-force attacks.
npm install express-rate-limitconst rateLimit = require('express-rate-limit'); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs }); app.use(limiter);
Logging
Implement logging to monitor application behavior.
-
Morgan: HTTP request logger.
const morgan = require('morgan'); app.use(morgan('combined')); -
Winston: General-purpose logging.
npm install winstonconst winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); // In development, log to console as well if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format.simple(), })); } app.use((req, res, next) => { logger.info(`${req.method} ${req.url}`); next(); });
Testing
Ensure your application works as expected through testing.
-
Jest: JavaScript testing framework.
npm install --save-dev jest-
Example Test:
// sum.js function sum(a, b) { return a + b; } module.exports = sum;// sum.test.js const sum = require('./sum'); test('adds 1 + 2 to equal 3', () => { expect(sum(1, 2)).toBe(3); }); -
Run Tests:
npm test
-
-
Supertest: HTTP assertions for testing Express routes.
npm install --save-dev supertest// app.test.js const request = require('supertest'); const app = require('./app'); // Your Express app describe('GET /', () => { it('responds with Hello, Express!', (done) => { request(app) .get('/') .expect(200) .expect('Hello, Express!', done); }); });