MEAN Ebook - CodeWithRandom
MEAN Ebook - CodeWithRandom
Part – 1 MongoDB
Part – 2 Express.js
Part – 3 Angular.js
Part – 4 Node.js
In these Four Parts you will learn about the every Basic to Advance
concepts of MEAN. And we also use some real world example in
this e-book to understand the concepts briefly.
I Know very well this e-book will not give you fully knowledge
by the one read, you do almost 3-4 read with example study and do
example in you lappy to understand the concepts. Am damn sure
you will become a pro in MEAN – because 100% takes a time. So
Give Your Best for Study MEAN.
MongoDB
Modules
1. Data Model
2. Scalability
3. Schema
4. Query Language
SQL: SQL databases use the SQL query language for data
manipulation and retrieval, which is powerful but can be complex for
certain tasks.
2. Download MongoDB
3. Installation
4. Starting MongoDB
6. Create a Database
# Download MongoDB
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-
4.4.6.tgz
mv mongodb-linux-x86_64-4.4.6 /usr/local/mongodb
# Connect to MongoDB
/usr/local/mongodb/bin/mongo
Documents
- json
"_id": 1,
"age": 30,
"address": {
"city": "Anytown",
"zipcode": "12345"
Collections
- json
// Products Collection
"_id": ObjectId("5fd453fb4e0c103f9cb7f97c"),
"name": "Smartphone",
"price": 599.99,
"category": "Electronics",
"manufacturer": "Apple",
"reviews": [
"user_id": ObjectId("5fd453fb4e0c103f9cb7f97d"),
"rating": 5
},
"user_id": ObjectId("5fd453fb4e0c103f9cb7f97e"),
"text": "Excellent camera",
"rating": 4
// Users Collection
"_id": ObjectId("5fd453fb4e0c103f9cb7f97d"),
"name": "Alice",
"email": "[email protected]",
"purchased_products": [
"product_id": ObjectId("5fd453fb4e0c103f9cb7f97c"),
"purchase_date": ISODate("2022-05-10T14:30:00Z"),
"quantity": 1
In this example:
The "products" collection uses embedded documents for
"reviews" and "ratings," reducing the need for JOINs and
improving query performance.
The "users" collection stores a reference to purchased products
using their ObjectId, allowing you to retrieve product details
with a separate query when needed.
CRUD stands for Create, Read, Update, and Delete, and these
operations allow you to manage data within MongoDB.
- javascript
db.products.insertOne({
name: "Laptop",
price: 999.99,
category: "Electronics"
});
- javascript
db.products.insertMany([
name: "Keyboard",
price: 49.99,
},
name: "Mouse",
price: 19.99,
]);
3.2 Reading Documents
The Read operation in MongoDB involves retrieving documents from
a collection. You can use the “find()” method to query documents in
a collection.
- javascript
db.products.find();
// Find documents and project only specific fields (e.g., name and
price)
- javascript
db.products.updateOne(
{ name: "Laptop" },
);
- javascript
db.products.updateMany(
{ category: "Electronics" },
{ $set: { price: 0.9 * price } }
);
- javascript
- javascript
- javascript
- javascript
db.products.find({
$or: [
{ category: "Electronics" },
{ price: { $lt: 50 } }
]
});
Array Operators: You can query arrays using operators like “$in”,
“$nin”, “$all”, and “$elemMatch”:
- javascript
- javascript
// Find products with names containing "laptop" (case-insensitive)
// Find products and include only the "name" and "price" fields
in the results
- javascript
Example:
"_id": ObjectId("5fd453fb4e0c103f9cb7f97d"),
"name": "Alice",
"email": "[email protected]",
"age": 28
},
"_id": ObjectId("5fd453fb4e0c103f9cb7f97e"),
"name": "Bob",
"email": "[email protected]",
"age": 32
},
"_id": ObjectId("5fd453fb4e0c103f9cb7f97f"),
"name": "Charlie",
"email": "[email protected]",
"age": 24
}
]
Create:
- javascript
db.users.insertOne({
name: "David",
email: "[email protected]",
age:
30
});
Read:
- javascript
db.users.find();
Retrieve users younger than 30:
- javascript
Update:
javascript
db.users.updateOne(
{ name: "Bob" },
{ $set: { age: 33 } }
);
```
Delete:
- javascript
- javascript
Find users older than 25 and sort them by age in descending order:
- javascript
4. Support for Sorting: Indexes can be used for sorting query results,
improving the efficiency of queries that involve sorting.
- javascript
- javascript
- javascript
You can view existing indexes, drop indexes, or rebuild them using
MongoDB's index management methods:
- javascript
db.products.getIndexes();
// Drop an index
db.products.dropIndex("name_1");
db.products.reIndex();
- javascript
Covered Queries
- javascript
- javascript
db.products.find().limit(10);
db.products.find().skip(5).limit(10);
Index Hinting
You can use the `hint()` method to explicitly specify which index to
use for a query. This can be useful when you want to ensure a
specific index is utilized.
- javascript
- javascript
db.products.aggregate([
$group: {
_id: "$category",
},
{
$project: {
category: "$_id",
_id: 0,
avgPrice: 1
]);
In this example:
Example:
"_id": ObjectId("5fd453fb4e0c103f9cb7f981"),
"customer_id": ObjectId("5fd453fb4e0c103f9cb7f97d"),
"order_date": ISODate("2022-01-15T09:30:00Z"),
"total_amount": 200.0
},
"_id": ObjectId("5fd453fb4e0c103f
9cb7f982"),
"customer_id": ObjectId("5fd453fb4e0c103f9cb7f97e"),
"order_date": ISODate("2022-02-20T14:15:00Z"),
"total_amount": 150.0
},
"_id": ObjectId("5fd453fb4e0c103f9cb7f983"),
"customer_id": ObjectId("5fd453fb4e0c103f9cb7f97d"),
"order_date": ISODate("2022-03-10T17:45:00Z"),
"total_amount": 300.0
To find the total value of orders placed by each customer, you can
use the Aggregation Framework:
- javascript
db.orders.aggregate([
$group: {
_id: "$customer_id",
},
$lookup: {
from: "customers",
localField: "_id",
foreignField: "_id",
as: "customer_info"
}
},
$project: {
customer_id: "$_id",
totalOrderValue: 1,
]);
In this example:
This query yields a result that shows the total order value for each
customer along with their names.
5
Data Modeling in MongoDB
Embedded Documents
- json
{
"_id": 1,
"name": "Alice",
"email": "[email protected]",
"address": {
"city": "Anytown",
"zipcode": "12345"
Referenced Documents
- json
// Products Collection
"_id": 101,
"name": "Laptop",
"price": 999.99
}
// Orders Collection
"_id": 201,
"user_id": 1,
Data Normalization
- json
// Customers Collection
"_id": 1,
"name": "Alice",
"email": "[email protected]"
// Orders Collection
"_id": 101,
"customer_id": 1,
"total_amount": 200.0
Data De-normalization
- json
"_id": 1,
"name": "Alice",
"email": "[email protected]",
"orders": [
"_id": 101,
"total_amount": 200.0
},
"_id": 102,
"total_amount": 150.0
One-to-One Relationship
- json
"_id": 1,
"username": "alice",
"profile": {
"first_name": "Alice",
"last_name": "Smith",
"age": 28
}
}
One-to-Many Relationship
- json
"_id": 101,
"content": "..."
"comments": [
"_id": 1,
"user_id": 2,
},
"_id": 2,
"user_id": 3,
"text": "Very informative."
Many-to-Many Relationship
- json
// Students Collection
"_id": 1,
"name": "Alice",
// Courses Collection
"_id": 101,
"name": "Math"
}
Example:
- json
"_id": 1,
"name": "Alice",
"email": "[email protected]",
"orders": [
"_id": 101,
"total_amount": 200.0
},
{
"_id": 102,
"total_amount": 150.0
In this example:
In this module we will explore the features that enable you to work
with specialized data types and perform advanced querying and
analysis.
- json
{
"_id": 1,
"location": {
"type": "Point",
- javascript
- javascript
db.locations.find({
location: {
$near: {
$geometry: {
type: "Point",
},
});
- json
"_id": 1,
"name": "Laptop",
To perform a text search, create a text index and use the “$text”
operator:
- javascript
- javascript
Compound Queries
You can combine multiple search terms using logical operators like
“$and”, “$or”, and “$not”. For example, to find products containing
both "laptop" and "powerful" in the description:
- javascript
Phrase Search
- javascript
- javascript
"_id": 1,
"timestamp": ISODate("2023-01-15T09:30:00Z"),
"temperature": 25.5
- javascript
- javascript
db.sensor_data.find({
sensor_id: 101,
timestamp: {
$gte: ISODate("2023-01-15T00:00:00Z"),
$lt: ISODate("2023-01-16T00:00:00Z")
});
Example:
- json
"_id": 1,
"location": {
"type": "Point",
"category": "Park"
- javascript
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
},
});
Within your project, click the "Clusters" tab and then click the "Build
a New Cluster" button. You'll be prompted to select various
configuration options for your cluster, including:
- javascript
if (err) {
return;
const db = client.db("mydatabase");
client.close();
});
Select the region or data center location where you want to deploy
your MongoDB cluster. Consider factors like latency and data
residency requirements when making your choice.
Example Code:
- javascript
const uri =
"mongodb+srv://<username>:<password>@clustername.mongodb.n
et/test?retryWrites=true&w=majority";
if (err) {
const db = client.db("mydatabase");
client.close();
});
In this example:
Authentication in MongoDB
- javascript
use admin
db.createUser({
user: "myuser",
pwd: "mypassword",
});
In this example:
Authorization in MongoDB
- javascript
db.createRole({
role: "customReadOnly",
privileges: [
actions: ["find"]
}
],
roles: []
});
db.createUser({
user: "customUser",
pwd: "userpassword",
});
In this example:
- javascript
db.createRole({
role: "customDbAdmin",
privileges: [
actions: ["listCollections"]
},
actions: ["createCollection"]
],
roles: []
});
In this example:
Once the role is defined, you can assign it to specific users or grant it
to other roles.
Example:
- javascript
if (err) {
const db = client.db("mydatabase");
client.close();
});
In this example:
Backup Example:
- shell
Restore Example:
- shell
2. Filesystem Snapshots
1. mongorestore
Example:
- shell
2. Atlas Restore
If you are using MongoDB Atlas, you can restore data directly from
the Atlas interface. Atlas provides a user-friendly interface for
selecting and restoring snapshots of your data. You can choose the
specific point-in-time snapshot you want to restore, and Atlas will
handle the process.
3. Filesystem Snapshots
Example Code:
Backup:
- shell
- shell
In these commands:
Example:
- javascript
db.sales.aggregate([
]);
In this example, the “$match” stage filters sales documents for the
year 2022.
Example:
- javascript
db.sales.aggregate([
{ $group: { _id: "$product", totalSales: { $sum: "$quantity" } } }
]);
This stage groups sales by product and calculates the total quantity
sold for each product.
Example:
- javascript
db.sales.aggregate([
]);
Here, the `$project` stage calculates the revenue for each sale and
includes only the "product" and "revenue" fields in the output.
Example:
- javascript
db.sales.aggregate([
{ $sort: { revenue: -1 } }
]);
5. $limit and $skip: These stages allow you to limit the number of
documents returned in the result set and skip a specified number of
documents.
Example:
- javascript
db.sales.aggregate([
{ $sort: { revenue: -1 } },
{ $limit: 5 },
{ $skip: 2 }
]);
Arithmetic Operations:
- javascript
db.sales.aggregate([
$project: {
total: {
]);
- javascript
db.students.aggregate([
$project: {
passed: {
]);
Here, the “$eq” operator checks if the "score" field is equal to 100.
String Manipulation
- javascript
db.contacts.aggregate([
$project: {
fullName: {
$concat: ["$firstName", " ", "$lastName"]
]);
Conditional Expressions
- javascript
db.orders.aggregate([
$project: {
status: {
$cond: {
then: "Shipped",
else: "Pending"
}
}
]);
Date Operations
- javascript
db.events.aggregate([
$project: {
formattedDate: {
]);
In this module we will explore the MongoDB drivers and APIs, which
are essential components for interacting with MongoDB databases
using various programming languages. MongoDB offers official
drivers and community-supported libraries for many programming
languages, making it accessible and versatile for developers.
Ruby: Ruby developers can use the Ruby driver (MongoDB Ruby
Driver) for MongoDB integration.
PHP: PHP developers can use the MongoDB PHP driver for building
web applications with MongoDB.
Scala: The Scala driver (MongoDB Scala Driver) is available for Scala
applications.
Swift: For iOS and macOS app development, the official MongoDB
Swift driver provides seamless integration.
Kotlin: Kotlin developers can use the official Kotlin driver (KMongo)
for MongoDB.
Rust: The Rust programming language has the official MongoDB Rust
driver for building efficient and safe applications.
3. Establish a Connection
- python
client = MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
collection = db["mycollection"]
# Insert a document
data = {"name": "John", "age": 30, "city": "New York"}
inserted_id = collection.insert_one(data).inserted_id
print(document)
# Update a document
# Delete a document
collection.delete_one({"_id": inserted_id})
client.close()
This code demonstrates the basic operations you can perform with a
MongoDB driver in Python. Similar operations can be performed with
MongoDB drivers for other programming languages, tailored to the
language's syntax and conventions.
12
MongoDB Performance Tuning
1. Database Profiling
- javascript
2. Monitoring Tools
3. Query Profiling
- javascript
1. Indexing
- javascript
2. Query Structure
- javascript
This query fetches only the "name" and "date" fields for documents
with a "status" of "active" and limits the result set to 10 documents.
Example of pagination:
- javascript
const pageNumber = 1;
db.mycollection.find({}).skip(skipAmount).limit(pageSize);
This query retrieves the first page of results with a page size of 10.
Covered queries occur when all the fields needed for a query are
present in an index, eliminating the need to access the actual
documents. Covered queries are generally faster and more efficient.
- javascript
1. Memory (RAM)
3. CPU Cores
4. Network Throughput
5. MongoDB Configuration
- javascript
rs.initiate({
_id: "myreplicaset",
members: [
});
2. Add Members
- javascript
rs.add("mongo4:27017");
This command adds a new member to the replica set.
- javascript
const uri =
"mongodb://mongo1:27017,mongo2:27017,mongo3:27017/?replica
Set=myreplicaset";
Example:
- shell
2. Initialize Shards
Example:
- shell
Start Mongos routers, which are query routers that route client
requests to the appropriate shard. Mongos instances should be
aware of the config servers and shards.
Example:
- shell
4. Enable Sharding
Enable sharding for a specific database by connecting to a Mongos
instance and running the `sh.enableSharding()` command.
Example:
- javascript
use mydatabase
db.createCollection("mycollection")
sh.enableSharding("
mydatabase")
sh.shardCollection("mydatabase.mycollection", { shardKeyField: 1
})
5. Balancing Data
To work with GridFS, you'll need to install the MongoDB driver for
your chosen programming language, as most drivers include GridFS
functionality.
2. Uploading Files
- javascript
const fs = require('fs');
try {
await client.connect();
fileStream.pipe(uploadStream);
} finally {
await client.close();
uploadFile();
- javascript
const fs = require('fs');
try {
await client.connect();
const downloadStream =
bucket.openDownloadStreamByName('largefile.txt');
const fileStream =
fs.createWriteStream('downloaded_largefile.txt');
downloadStream.pipe(fileStream);
} finally {
await client.close();
downloadFile();
4. Deleting Files
try {
await client.connect();
await bucket.delete(fileId);
} finally {
await client.close();
deleteFile('5f8e3d2151f0b9e14c7d9e35');
Express.js
Modules
1. Routing
Express allows you to define routes for different URLs and HTTP
methods. This enables you to specify how your application should
respond to various requests. For example, you can create routes for
handling user authentication, retrieving data from a database, or
serving static files like HTML, CSS, and JavaScript.
2. Middleware
3. Templating
6. RESTful APIs
7. WebSocket Support
Ensure that you have Node.js installed on your system. You can
download the latest version from the official Node.js website
(https://nodejs.org/).
Step 2: Create a New Directory for Your Project
mkdir my-express-app
cd my-express-app
npm init -y
This command will download and install Express.js along with its
dependencies into the “node_modules” directory of your project.
Step 5: Create an Express Application
Now that you have Express.js installed, you can create a basic
Express application. Create a new JavaScript file (e.g., “app.js” or
“index.js”) in your project directory.
- javascript
// Define a route
res.send('Hello, Express!');
});
app.listen(port, () => {
});
node app.js
Your Express application will start, and you should see the message
"Server is running on port 3000" in the console. You can then access
your application by opening a web browser and navigating to
“http://localhost:3000”.
- javascript
- javascript
Defining a Route
- javascript
res.send('Hello, Express!');
});
Here's what happens in this code:
Finally, we start the server and listen on a specified port (in this case,
port 3000):
- javascript
app.listen(port, () => {
});
Routing in Express.js
- javascript
});
});
});
app.listen(port, () => {
});
In this example:
We define a route for HTTP GET requests to the root path ('/').
When a user accesses the root URL, they receive the response
'This is the homepage.'
We define a route for HTTP POST requests to the '/submit'
path. This is often used for form submissions.
We use a catch-all route (expressed as “app.use()”) to handle
all other paths. If a user requests an undefined path, they
receive a 'Page not found' response.
The server is started on port 3000.
Dynamic Routes
- javascript
});
Here's how you can create and use middleware functions in Express:
- javascript
app.use(logRequest);
// Define a route that uses the middleware
});
In this example:
- javascript
if (isAuthenticated) {
} else {
res.status(401).send('Unauthorized');
});
In this example:
Routing Parameters
- javascript
});
Route Chaining
if (isAuthenticated) {
next();
} else {
res.status(401).send('Unauthorized');
next();
app.get(
'/protected',
authenticate,
logRequest,
);
In this example:
});
app.listen(port, () => {
});
In this example:
Handlebars
- javascript
app.engine('handlebars', exphbs());
});
app.listen(port, () => {
});
In this example:
Rendering Views
});
In this example, the 'index' view is rendered with the provided data.
The templating engine processes the template, injects the data, and
sends the resulting HTML to the client.
Both EJS and Handlebars allow you to access and display data within
your templates. Here's how you can do it in each:
EJS Example:
- html
<!DOCTYPE html>
<html>
<head>
<title>Express EJS Example</title>
</head>
<body>
</body>
</html>
In EJS, you use “<%= ... %>” to embed JavaScript code and output
data within your HTML template. In this case, “data.message” is
displayed as an “<h1>” heading.
Handlebars Example:
- html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</body>
</html>
Both EJS and Handlebars offer additional features for controlling the
flow of your templates, including conditionals, loops, and partials
(reusable template components).
Data Object
- javascript
});
Dynamic Data
- javascript
});
- javascript
});
- javascript
});
app.listen(port, () => {
});
In this example:
- javascript
});
app.listen(port, () => {
});
Query Parameters
- javascript
});
app.listen(port, () => {
});
In this example, a user can access the '/search' route with a query
parameter 'q' to specify a search term. The value of 'q' is then
accessed using “req.query.q”.
Request Bodies
Request bodies are used to send data to the server in the body of an
HTTP request, typically with POST requests. To access request bodies
in Express, you can use “req.body” after parsing the body data.
- javascript
});
app.listen(port, () => {
});
- javascript
app.post(
'/submit',
[
body('email').isEmail(),
],
if (!errors.isEmpty()) {
);
app.listen(port, () => {
});
In this example:
Sanitization
- javascript
app.post(
'/submit',
body('email').trim().normalizeEmail(),
],
if (!errors.isEmpty()) {
}
);
app.listen(port, () => {
});
In this example:
In module 5, we will dive into the best practices and techniques for
structuring Express.js applications. Proper organization and project
structure are essential for building scalable, maintainable, and
readable applications.
Proper organization and project structure are critical for the long-
term maintainability and scalability of your Express.js applications. A
well-structured application is easier to understand, modify, and
extend, making it more manageable as your project grows.
├── node_modules/
├── public/
│ ├── css/
│ ├── js/
│ └── images/
├── routes/
│ ├── index.js
│ ├── users.js
│ └── ...
├── controllers/
│ ├── indexController.js
│ ├── usersController.js
│ └── ...
├── views/
│ ├── index.ejs
│ ├── user.ejs
│ └── ...
├── app.js
├── package.json
└── ...
In this structure:
Separation of Concerns
Routing in Express
- javascript
// routes/index.js
res.render('index');
});
module.exports = router;
In this example, we define a route for the root URL ('/') in the
“index.js” file within the “routes” directory. This route responds by
rendering an 'index' view.
Controllers in Express
- javascript
// controllers/indexController.js
res.render('index');
};
module.exports = indexController;
- javascript
// routes/index.js
const express = require('express');
router.get('/', indexController.renderIndex);
module.exports = router;
6. Error Handling
});
9. Documentation
6.1 Implementing…………
Session Management
Using “express-session”
- javascript
app.use(
session({
secret: 'your_secret_key',
resave: false,
saveUninitialized: true,
})
);
req.session.username = 'john.doe';
});
});
app.listen(port, () => {
});
In this example:
User Registration
- javascript
}
// Hash and salt the password
res.send('Registration successful');
});
app.listen(port, () => {
});
In this example:
- javascript
// Login route
if (!user) {
res.send('Login successful');
});
app.listen(port, () => {
});
In this example:
- javascript
const user = {
username: 'john.doe',
roles: ['user', 'admin'],
};
// Authorization middleware
function authorize(roles) {
if (roles.includes(user.roles)) {
} else {
res.status(403).send('Access denied');
};
});
app.listen(port, () => {
In this example:
Real-World RBAC
});
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(port, () => {
});
In this example:
- javascript
constructor(message, statusCode) {
super(message);
this.statusCode = statusCode;
}
app.get('/', (req, res, next) => {
next(customError);
});
res.status(err.statusCode).send(err.message);
} else {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(port, () => {
});
In this example:
Debugging in Express.js
1. Console Logging
- javascript
console.log('Request received');
// ...
});
2. Debugging Middleware
- javascript
req.debug('Request received');
// ...
});
This will enable logging for all namespaces starting with "myapp."
3. Debugger Statements
- javascript
debugger;
// ...
});
- javascript
});
Within this middleware, you can inspect the error, log it, and
respond to the client with an appropriate error message and status
code.
javascript
console.error(err.stack);
res.status(500).send('Something broke!');
});
- javascript
res.status(err.statusCode).send(err.message);
} else {
next(err);
});
console.error(err.stack);
res.status(500).send('Something broke!');
});
try {
res.send(result);
} catch (err) {
next(err);
});
To create a RESTful API with Express, you need to set up routes and
define how the API responds to different HTTP methods and request
URLs. Here's a basic example of creating a simple API for managing
tasks:
- javascript
app.use(bodyParser.json());
let tasks = [
];
res.json(tasks);
});
const id = parseInt(req.params.id);
if (!task) {
res.json(task);
});
newTask.id = tasks.length + 1;
tasks.push(newTask);
res.status(201).json(newTask);
});
// PUT (update) a task by ID
const id = parseInt(req.params.id);
res.json(tasks[taskIndex]);
});
// DELETE a task by ID
const id = parseInt(req.params.id);
tasks.splice(taskIndex, 1);
res.status(204).send();
});
app.listen(port, () => {
});
In this example:
Read (GET): Retrieve resources using GET requests. You can fetch all
resources (`GET /tasks`) or a specific resource by its identifier (`GET
/tasks/:id`).
URL Versioning: Include the version in the URL, e.g., `/v1/tasks` and
`/v2/tasks`. This is straightforward and visible in the request.
- javascript
// Version 1
// ...
});
// Version 2
// ...
});
API Documentation
javascript
/**
* @apiName GetTasks
* @apiGroup Tasks
* @apiSuccessExample Success-Response:
* HTTP/1.1 200 OK
* [
* {
* "id": 1,
* "completed": false
* },
* {
"id": 2,
* "completed": true
* }
* ]
*/
res.json(tasks);
});
- javascript
mongoose.connect('mongodb://localhost/mydatabase', {
useNewUrlParser: true,
useUnifiedTopology: true,
});
const db = mongoose.connection;
db.once('open', () => {
console.log('Connected to MongoDB');
});
- javascript
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydatabase',
});
connection.connect((err) => {
if (err) {
return;
console.log('Connected to MySQL');
});
Querying Data
javascript
if (err) {
return;
});
MongoDB Query Example (Mongoose):
- javascript
if (err) {
return;
});
Inserting Data
- javascript
if (err) {
return;
});
- javascript
if (err) {
return;
});
Updating Data
- javascript
const userId = 1;
if (err) {
return;
});
- javascript
if (err) {
return;
});
Deleting Data
- javascript
const userId = 1;
if (err) {
return;
}
});
javascript
if (err) {
return;
});
ORM Examples
// Initialize Sequelize
host: 'localhost',
dialect: 'mysql',
});
username: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
});
sequelize.sync();
- javascript
User.findAll().then((users) => {
});
// Update a user
// Delete a user
- javascript
// Define a schema
});
// Define a model
- javascript
newUser.save();
});
// Update a user
});
// Delete a user
});
- javascript
if (err) {
} else {
res.status(201).json(user);
});
});
if (err) {
} else {
res.json(users);
}
});
});
// Update a user by ID
if (err) {
} else {
res.json(user);
});
});
// Delete a user by ID
if (err) {
res.status(204).send();
});
});
module.exports = router;
In module 10, we will dive into the aspect of security and best
practices in Express.js applications. Security is paramount when
developing web applications to protect against various threats and
vulnerabilities
10.1 Implementing………………
- javascript
app.post('/signup', [
body('email').isEmail().normalizeEmail(),
if (!errors.isEmpty()) {
});
- javascript
// Passport configuration
// ...
app.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
failureFlash: true,
}));
3. Session Management
- javascript
secret: 'mysecretkey',
resave: false,
saveUninitialized: true,
}));
- javascript
});
5. Cross-Site Request Forgery (CSRF) Protection
- javascript
});
6. Secure Headers
- javascript
app.use(helmet());
7. Content Security Policy (CSP)
- javascript
next();
});
8. Data Encryption
- javascript
// Handle error
});
9. Rate Limiting
- javascript
});
app.use('/api/', apiLimiter);
10. Error Handling
- javascript
console.error(err.stack);
});
2. Session Fixation
- javascript
if (err) {
// Handle error
} else {
});
- javascript
app.use(
session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: true,
cookie: {
},
})
);
- javascript
});
// Authentication logic
});
6. Protect Password Reset Mechanisms
1. Unit Tests
- javascript
describe('getUserData', () => {
it('should retrieve user data from the database and format it', () => {
});
});
});
2. Integration Tests
- javascript
supertest(app)
.get('/protected')
expect(res.body.message).to.equal('Access granted');
done();
});
});
supertest(app)
.get('/protected')
.expect(401, done);
});
});
2. Create a directory for your test files, e.g., `tests`, and place your
test files there.
4. Run your tests using the `mocha` command in your project's root
directory.
mocha tests
Chai
2. Import Chai in your test files and choose an assertion style (e.g.,
`expect`):
javascript
javascript
expect(isValid).to.be.true;
});
11.3 Test-Driven Development (TDD) - Express
Test-Driven Development (TDD) is a development approach in which
you write tests before implementing the actual code. It follows a
cycle known as the "Red-Green-Refactor" cycle:
2. Green: Implement the code to make the failing test pass. Your goal
is to write the minimum amount of code required to pass the test.
3. Refactor: Once the test passes, refactor your code to improve its
readability, maintainability, and performance. Ensure that the test
continues to pass after refactoring.
1. Red: Start by writing a failing test that describes the behavior you
want to implement.
- javascript
supertest(app)
.get('/nonexistent')
.expect(404, done);
});
- javascript
res.status(404).send('Not Found');
});
3. Refactor: After the test passes, you can refactor the code to make
it more efficient or maintainable. In this case, there's not much to
refactor, but TDD encourages you to continually improve your code.
TDD is a valuable practice for ensuring code quality and reducing the
likelihood of introducing bugs. By writing tests first, you have a clear
specification of what your code should do, which can lead to better-
designed and more maintainable Express.js applications.
12
Deploying and Scaling
In module 12, we will dive into the aspects of deploying and scaling
Express.js applications. Deploying an application to production
servers and ensuring it can handle increased traffic are crucial steps
in the development lifecycle.
In some cases, you may want to use a reverse proxy server (e.g.,
Nginx or Apache) to handle incoming requests and forward them to
your Express.js application. This can provide additional security and
performance benefits.
2. Install the Heroku Command Line Interface (CLI) for managing your
application from the terminal.
- plaintext
git init
git add .
11. Set environment variables on Heroku using the Heroku CLI or the
Heroku Dashboard. For example, if your application uses a database,
you can set the database URL as an environment variable.
12. If you want to use a reverse proxy server like Nginx or Apache,
you can set it up to forward requests to your Heroku app. Heroku
provides guidelines on setting up a reverse proxy if needed.
13. Use Heroku's built-in monitoring tools and services to track the
performance and health of your application.
1. Vertical Scaling
2. Horizontal Scaling
1. Load Balancers
- nginx
http {
upstream express_servers {
server server1.example.com;
server server2.example.com;
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://express_servers;
2. Containerization
- Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
COPY . .
# Expose a port (e.g., 3000) that the application will listen on
EXPOSE 3000
Response Time: Measure the time it takes for the server to respond
to incoming requests. Monitor response times to ensure they remain
within acceptable limits.
Error Rate: Keep an eye on the rate of errors and status codes
returned by your application. Identify and address any recurring
errors.
CPU and Memory Usage: Monitor the CPU and memory utilization of
your application servers to ensure they have sufficient resources.
Traffic and Request Rate: Track the incoming traffic and request rate
to anticipate spikes in traffic and adjust resources accordingly.
1. Caching
- javascript
if (err) {
// Handle error
} else if (cachedData) {
// Serve cached data if available
res.json(JSON.parse(cachedData));
} else {
fetchDataFromDatabase((data) => {
res.json(data);
});
});
});
2. Load Testing
3. Database Optimization
6. Horizontal Scaling
7. Regular Monitoring
app.use(compression());
setTimeout(() => {
res.send('Hello, World!');
}, 1000
);
});
app.listen(port, () => {
AngularJS
Modules
View: The user interface, what users see and interact with.
Testing: AngularJS includes tools for unit testing, which is crucial for
maintaining the quality and reliability of your application.
Create a New Project: You can create a new Angular project using
the CLI:
ng new my-angular-app
cd my-angular-app
ng serve
Access the App: Open a web browser and go to
http://localhost:4200/. You should see your Angular app up and
running.
- html
- typescript
@Component({
selector: 'app-hello-world',
templateUrl: './hello-world.component.html',
styleUrls: ['./hello-world.component.css']
})
name = 'World';
- html
<app-hello-world></app-hello-world>
View: The View is the user interface that the user interacts with. It's
responsible for displaying data and responding to user input. Views
are created using HTML templates.
- html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-controller="MyController">
</body>
<script>
app.controller('MyController', function($scope) {
$scope.changeGreeting = function() {
};
});
</script>
</html>
- javascript
app.directive('myDirective', function() {
return {
element.on('mouseover', function() {
element.css('background-color', 'lightblue');
});
element.on('mouseout', function() {
element.css('background-color', 'white');
});
};
});
- html
- javascript
app.controller('MyController', function($scope) {
});
Two-Way Data Binding: Two-way data binding is a special feature of
AngularJS. It not only updates the View when the Model changes but
also updates the Model when the View is modified. The ng-model
directive is commonly used for two-way data binding. It is often used
with form elements like input fields and checkboxes.
- html
- javascript
app.controller('MyController', function($scope) {
$scope.username = 'User';
});
In this example, the input field and the paragraph element are
synchronized. When you type in the input field, the paragraph
updates in real-time.
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
</div>
</body>
<script>
app.controller('MyController', function($scope) {
});
</script>
</html>
<ul>
</ul>
- javascript
app.controller('MyController', function($scope) {
$scope.items = [
];
});
- html
- html
- javascript
app.controller('MyController', function($scope) {
$scope.isDisplayed = true;
$scope.isHidden = false;
});
- html
<div>
</div>
In this example:
You can also use expressions with conditional statements and loops:
- html
<ul>
</li>
</ul>
- javascript
app.controller('MyController', function($scope) {
$scope.items = [
{ name: 'Item 1', price: 10, inStock: true },
];
});
In this case:
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
</div>
</body>
<script>
app.controller('MyController', function($scope) {
});
</script>
</html>
In this example:
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="ParentController">
<div ng-controller="ChildController">
</div>
</div>
</body>
<script>
app.controller('ParentController', function($scope) {
});
app.controller('ChildController', function($scope) {
});
</script>
</html>
In this example:
If you need to access a parent scope's property directly, you can use
the $parent keyword. For example, to access parentGreeting from
ChildController, you can use $parent.parentGreeting.
- html
<h2>{{$parent.parentGreeting}}</h2>
AngularJS provides several built-in filters, and you can also create
custom filters for specific formatting needs. Here are some examples
of using built-in filters:
- html
Date Filter: The date filter is used to format dates. You can specify
the format and the timezone.
- html
- html
- html
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="FormController">
<label for="name">Name:</label>
<label for="email">Email:</label>
</form>
</div>
</body>
<script>
app.controller('FormController', function($scope) {
$scope.user = {};
});
</script>
</html>
In this example:
We create a form using the <form> element and use the ng-
model directive to bind form fields to properties in the Model.
We use the ng-show directive to display error messages when
form fields are invalid.
The ng-disabled directive disables the submit button when the
form is invalid.
AngularJS also provides CSS classes that can be used for styling
invalid form fields:
ng-dirty: Applied to an element when the user has interacted with it.
- html
- css
.error {
border-color: red;
.error-text {
color: red;
Let's take a closer look at how to use built-in services and create
custom services in AngularJS.
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
<ul>
</ul>
</div>
</body>
<script>
$scope.users = [];
$scope.fetchData = function() {
$http.get('https://jsonplaceholder.typicode.com/users')
.then(function(response) {
$scope.users = response.data;
});
};
});
</script>
</html>
In this example:
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="ListController">
<h1>Item List</h1>
<ul>
{{ item }}
</li>
</ul>
</div>
</body>
<script>
app.service('ItemListService', function() {
this.getItems = function() {
return items;
};
this.addItem = function(item) {
items.push(item);
};
});
$scope.itemList = ItemListService;
$scope.addItem = function(item) {
ItemListService.addItem(item);
};
});
</script>
</html>
In this example:
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-
route.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-view></div>
</body>
<script>
$routeProvider
.when('/', {
templateUrl: 'home.html',
controller: 'HomeController'
})
.when('/about', {
templateUrl: 'about.html',
controller: 'AboutController'
})
});
app.controller('HomeController', function($scope) {
});
app.controller('AboutController', function($scope) {
});
</script>
</html>
In this example:
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-
route.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-view></div>
</body>
<script>
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'home.html',
controller: 'HomeController'
})
.when('/product/:productId', {
templateUrl: 'product.html',
controller: 'ProductController'
})
});
app.controller('HomeController', function($scope) {
});
$scope.productId = $routeParams.productId;
});
</script>
</html>
In this example:
This shows how route parameters and navigation allow you to create
dynamic and data-driven SPAs.
8
Custom Directives
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
</div>
</body>
<script>
app.directive('myTooltip', function() {
return {
element.on('mouseenter', function() {
alert(tooltipText);
});
};
});
app.controller('MyController', function($scope) {
// Controller logic here
});
</script>
</html>
In this example:
- html
<!DOCTYPE html>
<html>
<head>
<script
vsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.
min.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
<my-counter></my-counter>
</div>
</body>
<script>
app.directive('myCounter', function() {
return {
restrict: 'E', // Element directive
template: '<div>' +
'<button ng-click="decrement()">-</button>' +
'<button ng-click="increment()">+</button>' +
'</div>',
controller: function($scope) {
$scope.count = 0;
$scope.increment = function() {
$scope.count++;
};
$scope.decrement = function() {
$scope.count--;
};
};
});
app.controller('MyController', function($scope) {
// Controller logic here
});
</script>
</html>
In this example:
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
<button ng-click="fetchData()">Fetch Data</button>
<ul>
</ul>
</div>
</body>
<script>
$scope.users = [];
$scope.fetchData = function() {
$http.get('https://jsonplaceholder.typicode.com/users')
.then(function(response) {
$scope.users = response.data;
});
};
});
</script>
</html>
In this example:
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="MyController">
<form ng-submit="postData()">
<label for="name">Name:</label>
<button type="submit">Submit</button>
</form>
</div>
</body>
<script>
$scope.postData = function() {
$http.post('https://jsonplaceholder.typicode.com/users',
$scope.newUser)
.then(function(response) {
})
.catch(function(error) {
});
};
});
</script>
</html>
In this example:
- javascript
$http.get('https://jsonplaceholder.typicode.com/nonexistent')
.then(function(response) {
// Success callback
}, function(error) {
// Error callback
});
Error Status Codes: HTTP responses often include status codes that
indicate the outcome of a request. You can check the status code to
handle specific errors. For example, a 404 status code indicates a
resource not found.
- javascript
$http.get('https://jsonplaceholder.typicode.com/nonexistent')
.then(function(response) {
// Success
})
.catch(function(error) {
} else {
});
Global Error Handling: You can implement global error handling for
all HTTP requests by configuring the $httpProvider with an
interceptor. This approach allows you to centralize error handling
and implement consistent error responses.
- javascript
app.config(function ($httpProvider) {
$httpProvider.interceptors.push('errorInterceptor');
});
app.factory('errorInterceptor', function($q) {
return {
responseError: function(rejection) {
} else {
return $q.reject(rejection);
};
});
In this example, the errorInterceptor factory handles response
errors globally, displaying an alert with an appropriate message
based on the error status.
- html
<!DOCTYPE html>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.m
in.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="AuthController">
<div ng-hide="isAuthenticated">
<h2>Login</h2>
<form ng-submit="login()">
<label for="username">Username:</label>
<label for="password">Password:</label>
<button type="submit">Login</button>
</form>
</div>
<div ng-show="isAuthenticated">
<button ng-click="logout()">Logout</button>
</div>
</div>
</body>
<script>
$scope.isAuthenticated = false;
$scope.user = {};
$scope.login = function() {
$scope.isAuthenticated = true;
};
$scope.logout = function() {
$scope.isAuthenticated = false;
$scope.user = {};
};
});
</script>
</html>
In this example:
- html
- javascript
// app.js
app.controller('MyController', function($scope) {
$scope.add = function(a, b) {
return a + b;
};
});
- javascript
// controller.spec.js
describe('MyController', function() {
beforeEach(module('myApp'));
beforeEach(inject(function(_$controller_, _$rootScope_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
}));
expect(result).toBe(5);
});
});
In this example:
Unit tests are valuable for verifying that specific components work as
intended and help maintain code quality during development.
Install Karma Globally: You can install Karma globally using npm.
karma init
Write Your Unit Tests: Create Jasmine test files (ending with .spec.js)
for your AngularJS components.
Run Tests: Use Karma to run your tests.
karma start
- javascript
// app.js
$scope.getData = function() {
$http.get('/data').then(function(response) {
$scope.data = response.data;
});
};
});
- javascript
// controller.spec.js
describe('MyController', function() {
beforeEach(module('myApp'));
beforeEach(inject(function(_$controller_, _$rootScope_,
_$httpBackend_, _$q_) {
$controller = _$controller_;
$rootScope = _$rootScope_;
$httpBackend = _$httpBackend_;
$q = _$q_;
}));
$httpBackend.when('GET', '/data').respond(responseData);
$scope.getData();
expect($scope.data).toEqual(responseData);
});
});
In this example:
Remove Unused Code: Analyze your application for unused code and
dependencies. Removing unnecessary code improves performance
and reduces the application's size.
- javascript
// Controller logic
}]);
- javascript
// Controller logic
}]);
AngularJS provides tools and best practices for i18n and l10n, and
one popular library for managing translations is angular-translate.
Let's go through the process of internationalizing and localizing an
AngularJS application using angular-translate:
- html
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-
translate/2.19.0/angular-translate.min.js"></script>
Configure your AngularJS module to use pascalprecht.translate:
- javascript
Define translation files for each language and region you want to
support. For example, you can have en_US.json for English and
fr_FR.json for French. Each file contains key-value pairs for
translations:
- json
// en_US.json
"GREETING": "Hello!",
json
Copy code
// fr_FR.json
- javascript
app.config(function ($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'translations/',
suffix: '.json'
});
$translateProvider.preferredLanguage('en_US');
});
- html
<h1 translate="GREETING"></h1>
<button translate="BUTTON_LABEL"></button>
You can allow users to change the language dynamically by using the
$translate service. For example, you can add a language switcher
that sets the desired language:
- html
<button ng-click="changeLanguage('fr_FR')">Français</button>
- javascript
$translate.use(key);
};
});
- html
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular-
animate.js"></script>
In your CSS styles, define classes that specify the animations you
want to apply. For example:
- css
.fade-in {
transition: opacity 0.5s;
opacity: 0;
.fade-in.ng-enter-active, .fade-in.ng-leave-active {
opacity: 1;
.fade-in.ng-enter, .fade-in.ng-leave-to {
opacity: 0;
- html
- html
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
- javascript
app.directive('chart', function() {
return {
restrict: 'E',
template: '<canvas></canvas>',
data: scope.data
});
scope.$watch('data', function(newData) {
chart.data = newData;
chart.update();
});
},
scope: {
data: '='
};
});
You can now use the custom chart directive in your HTML templates
to display charts based on the provided data:
- html
Controller Logic:
- javascript
app.controller('ChartController', function($scope) {
$scope.chartData = {
datasets: [{
label: 'Sales',
};
});
Node.js
Modules
- javascript
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
if (err) {
console.error(err);
} else {
console.log(data);
});
2. Fast Execution
5. Scalability
6. Active Community
node -v
npm -v
You should see the versions of Node.js and npm printed to the
console.
Create a new directory for your project and navigate to it using the
terminal or command prompt.
- javascript
console.log("Hello, Node.js!");
Save the file.
node hello.js
Node.js provides a built-in module system, which means that you can
use existing modules, create your own custom modules, and manage
dependencies between them. Here's an overview of Node.js
modules:
Core Modules:
Node.js has a set of built-in core modules like fs (file system), http
(HTTP server), and path (file path utilities). You can use these
modules without needing to install them separately.
- javascript
const fs = require('fs');
You can create your own modules to encapsulate code that performs
specific tasks. To create a custom module, create a JavaScript file and
export the functions, objects, or variables you want to make
available to other parts of your application.
- javascript
// mymodule.js
function greet(name) {
module.exports = {
greet,
};
You can then import and use this module in other parts of your
application.
- javascript
Create a JavaScript file that will serve as your module. For example,
create a file named myModule.js.
- javascript
// myModule.js
function greet(name) {
module.exports = {
greet,
};
In another file (e.g., your main application file), require the custom
module using require. This allows you to use the exported
functionality from your module.
- javascript
npm init
For example:
For example:
This will update the package to the latest version allowed by the
version range defined in your package.json.
npm ls
- javascript
setTimeout(() => {
callback(user);
}, 1000);
});
Node.js has an event loop that constantly checks the message queue
for tasks. When an asynchronous task completes, it places a message
in the queue. The event loop processes these messages and executes
the associated callbacks.
3.3 Promises and Async/Await For Better….
While callbacks are useful, they can lead to callback hell or pyramid
of doom when dealing with complex asynchronous operations.
Promises and async/await were introduced to address this issue.
- javascript
function fetchUserData(userId) {
setTimeout(() => {
resolve(user);
}, 1000);
});
fetchUserData(456)
.then((user) => {
})
.catch((error) => {
console.error(error);
});
- javascript
try {
} catch (error) {
console.error(error);
}
}
getUserInfo(789);
Reading Files
To read a file using the fs module, you can use the “fs.readFile”
method. This method reads the entire content of a file into a buffer
or string, depending on the encoding.
- javascript
const fs = require('fs');
if (err) {
console.error(err);
} else {
console.log(data);
});
Writing Files
To write data to a file, you can use the fs.writeFile method. It allows
you to specify the file to write to and the content to be written.
- javascript
const fs = require('fs');
if (err) {
console.error(err);
} else {
});
The “fs” module provides various other methods for file operations,
including:
Reading Files
To read the contents of a file, you can use the “fs.readFile” method
as shown earlier. It's important to provide a callback function to
handle the file data once it's read. Here's an example of reading a
JSON file:
- javascript
const fs = require('fs');
if (err) {
console.error(err);
} else {
console.log(jsonData);
});
Writing Files
To write data to a file, you can use the “fs.writeFile” method. Here's
an example of writing data to a file:
- javascript
const fs = require('fs');
if (err) {
console.error(err);
} else {
});
In this example, we specify the data to be written and the file
('output.txt') to which the data will be written.
Streams are objects that allow you to read or write data piece by
piece, rather than loading an entire file into memory. Streams are
memory-efficient and enable you to work with data in a more
responsive and performant way.
To read a file using streams, you can create a Readable stream and
pipe it to a Writable stream to save the data.
- javascript
const fs = require('fs');
const readStream = fs.createReadStream('largeFile.txt');
readStream.pipe(writeStream);
readStream.on('end', () => {
});
console.error(err);
});
writeStream.on('finish', () => {
console.log('Writing finished.');
});
You can also use streams to write data to a file piece by piece. Here's
an example of creating a writable stream to write data incrementally:
- javascript
const fs = require('fs');
const dataToWrite = 'This is a long text that will be written to the file
using streams.';
writeStream.end();
});
writeStream.on('finish', () => {
console.log('Writing finished.');
});
console.error(err);
});
In this example, we create a writable stream and use the write
method to write data in smaller chunks. The end method indicates
the end of writing, and we handle events to determine when writing
is finished or if there's an error.
Streams are particularly useful when working with large files, as they
allow you to process data without loading it entirely into memory,
resulting in better performance and efficiency.
5
HTTP and Web Servers
- javascript
});
server.listen(port, () => {
});
Here's what's happening in this code:
Routing Requests
- javascript
res.end('About us page');
} else {
});
server.listen(port, () => {
});
To serve static files like HTML, CSS, JavaScript, and images, you can
use the fs (File System) module to read and send the file content in
response to an HTTP request. Here's a simplified example serving an
HTML file:
- javascript
const fs = require('fs');
if (err) {
} else {
res.end(data);
});
});
const port = 3000;
server.listen(port, () => {
});
In this example, when a request is made to the root URL ('/'), we use
fs.readFile to read the 'index.html' file and send its content as an
HTML response.
To build a RESTful API with Node.js, you need to handle various HTTP
methods (GET, POST, PUT, DELETE) and define routes and resources.
You can use popular libraries like Express.js to simplify the process.
- javascript
const todos = [
];
app.use(express.json());
res.json(todos);
});
const id = parseInt(req.params.id);
const todo = todos.find((t) => t.id === id);
if (todo) {
res.json(todo);
} else {
});
todos.push(newTodo);
res.status(201).json(newTodo);
});
// Update a todo
const id = parseInt(req.params.id);
res.json(todos[index]);
} else {
});
// Delete a todo
const id = parseInt(req.params.id);
res.json(deletedTodo);
} else {
});
const port = 3000;
app.listen(port, () => {
});
Installation:
mkdir express-demo
cd express-demo
npm init -y
npm install express
Create an entry point file (e.g., app.js) and set up your Express
application:
- javascript
res.send('Hello, Express.js!');
});
app.listen(port, () => {
});
You should see the message "Server is listening on port 3000" in the
console. Open your web browser and navigate to
http://localhost:3000 to see the "Hello, Express.js!" message.
This is a simple Express application that defines a single route for the
homepage and sends a basic response.
Routing
- javascript
});
});
});
app.listen(3000, () => {
});
- javascript
app.use(logMiddleware);
// Define a route
res.send('Homepage');
});
app.listen(3000, () => {
});
Template Engines
- javascript
});
app.listen(port, () => {
});
- html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
</html>
This is just the tip of the iceberg when it comes to Express.js. It offers
a wide range of features and middleware for building web
applications, including handling form data, authentication, sessions,
and more. Express is widely used for creating RESTful APIs, web
applications, and even full-fledged websites.
7
Database and No SQL with Node.js
SQL Databases
- javascript
host: 'localhost',
user: 'username',
password: 'password',
database: 'mydb',
});
connection.connect((err) => {
if (err) {
return;
});
if (err) {
return;
}
});
connection.end();
- javascript
client.connect()
.then(() => {
const db = client.db('mydb');
// Insert a document
.then(result => {
// Find documents
.then(docs => {
})
})
Installation
Connecting to MongoDB
- javascript
client.connect()
.then(() => {
console.log('Connected to MongoDB');
})
- javascript
- javascript
Inserting Documents
- javascript
collection.insertOne(newDocument)
.then(result => {
console.log('Inserted document:', result.ops[0]);
})
Finding Documents
- javascript
.then(docs => {
})
Updating Documents
- javascript
.then(result => {
})
- javascript
.then(result => {
})
- javascript
client.close()
.then(() => {
console.log('Connection closed');
})
- javascript
mongoose.connect('mongodb://localhost/auth_demo', {
useNewUrlParser: true, useUnifiedTopology: true });
username: String,
password: String,
}));
// Configure Passport.js
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
app.use(passport.initialize());
app.use(passport.session());
// Routes
});
res.send('Login Page');
});
app.post('/login', passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
}));
});
if (req.isAuthenticated()) {
return next();
res.redirect('/login');
app.listen(3000, () => {
});
In this code:
User Registration
- javascript
res.send('Registration Page');
});
if (err) {
console.error(err);
return res.redirect('/register');
}
passport.authenticate('local')(req, res, () => {
res.redirect('/dashboard');
});
});
});
- javascript
username: String,
password: String,
role: String, // 'admin', 'user', etc.
}));
You can assign roles when registering users or update them later.
Authorizing Routes
- javascript
return next();
res.status(403).send('Permission denied');
// Admin-only route
res.send('Admin Page');
});
// Middleware to check if a user has the 'user' role
return next();
res.status(403).send('Permission denied');
// User-only route
});
Data validation ensures that the data you receive from users is in the
expected format and within acceptable boundaries. Libraries like
validator can help with data validation and sanitation.
// ...
if (!validator.isAlphanumeric(username) ||
!validator.isLength(password, { min: 6 })) {
if (err) {
console.error(err);
res.redirect('/dashboard');
});
});
});
In this code, we use the validator library to validate and sanitize user
input. We ensure that the username contains only alphanumeric
characters and that the password has a minimum length of 6
characters. We also sanitize the username using validator.escape to
prevent cross-site scripting (XSS) attacks.
javascript
// ...
});
});
In this code, we use the csurf library to generate a CSRF token and
verify it when processing form submissions. The CSRF token is
included in the form template and submitted with the form. The
middleware checks that the submitted token matches the expected
value.
- javascript
app.use(helmet());
HTTP Methods: Use HTTP methods (GET, POST, PUT, DELETE, etc.) to
define the actions that can be performed on resources. For example,
use GET to retrieve data, POST to create data, PUT to update data,
and DELETE to remove data.
Endpoints: Endpoints are the URLs that clients use to interact with
resources. For example, /users/123 could represent the user with
the ID 123.
Node.js is a great choice for building RESTful APIs due to its non-
blocking I/O and scalability. Here's a simple example of a RESTful API
using the Express.js framework:
- javascript
const users = [
];
// Middleware to parse JSON request bodies
app.use(express.json());
res.json(users);
});
res.json(user);
});
const user = {
id: users.length + 1,
name: req.body.name,
};
users.push(user);
res.status(201).json(user);
});
user.name = req.body.name;
res.json(user);
});
users.splice(userIndex, 1);
res.send('User deleted');
});
app.listen(port, () => {
});
In this example:
Request Handling
- javascript
// ...
});
Input Validation
- javascript
name: Joi.string().min(3).required(),
});
if (error) {
return res.status(400).send(error.details[0].message);
// ...
});
Proper error handling and responses are crucial for a robust API.
When an error occurs, return the appropriate HTTP status code and a
meaningful error message. For example:
- javascript
if (!user) {
res.json(user);
});
API Documentation
Documenting your API helps other developers understand how to
use it effectively. Tools like Swagger or OpenAPI make it easier to
create and maintain API documentation.
- javascript
const options = {
definition: {
openapi: '3.0.0',
info: {
version: '1.0.0',
},
},
};
API Testing
- javascript
request(app)
.get('/api/users')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(200)
done();
});
});
request(app)
.get('/api/users')
.set('Accept', 'application/json')
.expect(200)
expect(res.body).to.be.an('array');
done();
});
});
});
In this example:
Make sure to configure Mocha for testing and install the necessary
testing dependencies using npm or yarn.
API documentation and testing are essential for ensuring your API's
reliability and providing clear guidelines for other developers who
want to use your API. Additionally, automated testing helps catch
regressions as you make changes to your API, maintaining its
stability.
10
Real-Time Application with WebSocket
npm install ws
- javascript
});
console.log(`Received: ${message}`);
wss.clients.forEach((client) => {
client.send(message);
});
});
// Send a welcome message to the newly connected client
});
server.listen(3000, () => {
});
In this code:
Before building the chat application, make sure you have the ws
library installed, as described in the previous section.
- javascript
const fs = require('fs');
res.end(indexHtml);
} else {
res.end('Not Found');
}
});
console.log(`Received: ${message}`);
wss.clients.forEach((client) => {
client.send(message);
});
});
});
server.listen(3000, () => {
console.log('WebSocket chat server is running on port 3000');
});
- html
<!DOCTYPE html>
<html>
<head>
<title>WebSocket Chat</title>
</head>
<body>
<button onclick="sendMessage()">Send</button>
<ul id="chat"></ul>
<script>
const li = document.createElement('li');
li.textContent = event.data;
chat.appendChild(li);
});
function sendMessage() {
socket.send(message);
document.getElementById('message').value = '';
</script>
</body>
</html>
1. Load Balancing
- javascript
cluster.fork();
} else {
res.end('Hello, World!\n');
});
server.listen(8000);
2. Vertical Scaling
Dockerfile:
- Dockerfile
FROM node:14
WORKDIR /app
COPY package*.json ./
COPY . .
EXPOSE 3000
version: '3'
services:
web:
build: .
ports:
- "3000:3000"
4. Caching
- javascript
if (reply) {
res.send(`Product: ${reply}`);
} else {
// Data not found in cache, fetch it from the database and store
in cache
res.send(`Product: ${productData}`);
});
});
app.listen(3000, () => {
5. Microservices Architecture
- javascript
app.listen(3001, () => {
});
- javascript
orderData.user = userData.data;
res.json(orderData);
});
app.listen(3002, () => {
});
1. Code Profiling
- javascript
function timeConsumingOperation() {
console.time('Operation');
// Your time-consuming code here
console.timeEnd('Operation');
timeConsumingOperation();
2. Asynchronous Operations
- javascript
const fs = require('fs');
if (err) {
console.error(err);
return;
}
console.log(data);
});
3. Optimizing Dependencies
Review the dependencies your application uses and ensure they are
well-maintained and optimized for performance. Remove
unnecessary or outdated dependencies to reduce overhead.
4. Connection Pooling
- javascript
host: 'your-hostname',
user: 'your-username',
password: 'your-password',
database: 'your-database',
});
try {
} catch (error) {
} finally {
In this example:
- javascript
if (n <= 2) return 1;
return memo[n];
Load Balancing
- nginx
upstream my_app {
server localhost:8000;
server localhost:8001;
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://my_app;
}
Test the Nginx configuration to ensure there are no syntax errors:
sudo nginx –t
Clustering
- javascript
if (cluster.isMaster) {
});
} else {
res.writeHead(200);
res.end('Hello, World!\n');
}).listen(8000);
1. Optimizing Dependencies
- json
"dependencies": {
"express": "^4.17.1",
"mysql2": "^2.2.5"
}
To remove development dependencies:
2. Environment Configuration
- javascript
require('dotenv').config();
const databaseConfig = {
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
};
3. Security
- javascript
app.use(helmet());
4. Error Handling
- javascript
console.error(err.stack);
5. Logging
- javascript
level: 'info',
format: winston.format.simple(),
});
6. Testing
- javascript
describe('Array', function() {
});
});
7. Performance Optimization
8. Documentation
- javascript
const options = {
definition: {
openapi: '3.0.0',
info: {
version: '1.0.0',
},
},
apis: ['app.js'],
};
app.use('/api-docs', swaggerUi.serve,
swaggerUi.setup(swaggerSpec));
12.2 Hosting Options, Including Cloud Platforms
Choosing the right hosting option is essential for deploying your
Node.js application. Various hosting options are available, including
traditional web hosting, virtual private servers (VPS), dedicated
servers, and cloud platforms. In this section, we'll focus on cloud
platforms, as they offer scalability, reliability, and easy management.
2. Microsoft Azure
Deployment Options:
Once the App Service is created, you can deploy your Node.js
application using various deployment options. The two common
methods are:
a. Local Git Deployment: You can set up a Git repository in Azure and
use Git to push your application code to Azure. Azure will
automatically build and deploy your application.
b. Azure DevOps (Azure Pipelines): Azure DevOps provides a robust
CI/CD pipeline to build, test, and deploy your application. You can set
up a pipeline to automatically deploy your Node.js application to
Azure App Service whenever changes are pushed to your repository.
Environment Variables:
You can also set up monitoring and alerts using Azure Monitor to
track the performance and health of your application.
Custom Domain:
SSL Certificates:
Google Cloud Platform offers services like Google App Engine for
easy deployment and Google Cloud Functions for serverless
computing. You can deploy Node.js applications to Google App
Engine.
Download and install the Google Cloud SDK on your local machine.
Use the gcloud CLI to deploy your Node.js application to Google App
Engine.
You can configure custom domains and SSL certificates for your
application.
The workflow YAML file defines the CI/CD steps. You can customize it
to suit your application's needs. Below is a basic example:
- yaml
name: Node.js CI/CD
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
uses: actions/checkout@v2
uses: actions/setup-node@v2
with:
node-version: 14
run: |
Deployment Steps:
In the workflow YAML, you can add deployment steps. This might
involve using environment variables, secret keys, or access tokens to
deploy your application to the hosting platform.
Save your workflow file, and GitHub Actions will automatically run it
when changes are pushed to the repository.
Mitigation:
- javascript
host: 'localhost',
user: 'yourusername',
password: 'yourpassword',
database: 'yourdatabase',
});
connection.connect();
});
connection.end();
Mitigation:
- javascript
app.use(helmet());
});
});
app.listen(3000, () => {
});
Mitigation:
- javascript
<button type="submit">Submit</button>
</form>`);
});
});
app.listen(3000, () => {
});
d. Insecure Dependencies
Mitigation:
Regularly update your project's dependencies to the latest
secure versions.
Use tools like npm audit to identify and fix vulnerabilities in
your dependencies.
Consider using a package-lock file to ensure consistent and
secure dependency resolution.
Mitigation:
- javascript
app.use(
session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // Use HTTPS in production
httpOnly: true,
sameSite: 'strict',
},
})
);
passport.use(
})
);
app.use(passport.initialize());
app.use(passport.session());
});
app.get('/dashboard', (req, res) => {
if (req.isAuthenticated()) {
} else {
res.redirect('/login');
});
app.listen(3000, () => {
});
app.use(helmet());
});
app.listen(3000, () => {
});
- javascript
app.post(
'/login',v
body('username').isEmail(),
if (!errors.isEmpty()) {
);
app.listen(3000, () => {
});
c. Secure Authentication
- javascript
app.use(
session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
})
);
passport.use(
new LocalStrategy((username, password, done) => {
})
);
done(null, user.id);
});
done(null, user);
});
app.use(passport.initialize());
app.use(passport.session());
app.post(
'/login',
passport.authenticate('local', {
successRedirect: '/dashboard',
failureRedirect: '/login',
})
);
app.listen(3000, () => {
});
- javascript
app.use(
session({
secret: 'your-secret-key',
resave: false,
saveUninitialized: false,
cookie: {
httpOnly: true,
sameSite: 'strict',
},
})
);
app.listen(3000, () => {
});
- javascript
});
app.use('/login', limiter);
});
In this code, we've set up rate limiting for the /login route, allowing a
maximum of 5 login attempts within a 15-minute window.
b. Session Fixation Attacks
- javascript
req.session.regenerate((err) => {
});
});
By regenerating the session ID, you ensure that the user's session is
not vulnerable to fixation attacks.
Example:
- javascript
Example:
Once the debugger is active, you can use commands like break,
watch, step, and repl to interact with your code.
Example:
- json
{
"version": "0.2.0",
"configurations": [
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/my-app.js",
"skipFiles": ["<node_internals>/**"]
Open your Node.js file in VS Code, set breakpoints, and click the "Run
and Debug" button.
Example:
node-inspect my-debugging-script.js
Open your browser and access the provided URL to start debugging.
a. Unit Testing
Unit testing involves testing individual units or components of your
code in isolation. These units are typically functions or methods. The
goal is to verify that each unit of your code performs as expected.
Chai: An assertion library that pairs well with Mocha for expressive
and readable test assertions.
- javascript
describe('MyModule', function() {
assert.equal(result, 5);
});
assert.equal(result, 5);
});
});
b. Integration Testing
- javascript
request(app)
.get('/api/products')
.expect(200)
.end(function(err, res) {
done();
});
});
it('should add a new product with POST /api/products',
function(done) {
request(app)
.post('/api/products')
.set('Accept', 'application/json')
.expect('Content-Type', /json/)
.expect(201)
.end(function(err, res) {
done();
});
});
});
In both unit and integration testing, you may encounter the need to
isolate parts of your code from external dependencies or services.
This is where mocking and stubbing come into play. Libraries like
sinon can help you create mock objects or stub functions to simulate
interactions with external components.
Example of using sinon for stubbing in unit testing:
- javascript
describe('MyModule', function() {
myModule.setApiCall(fakeApiCall);
});
});
In this test, we're stubbing an external API call using sinon. This
allows us to control the behavior of the external dependency during
testing.
14.3 Tools and Best Practices for Testing
a. Continuous Integration (CI) and Continuous Deployment (CD)
Code coverage tools like Istanbul or nyc help you measure how much
of your code is covered by tests. High code coverage indicates that
more parts of your codebase have been tested, reducing the risk of
undiscovered bugs.
c. Test Frameworks
d. Test Doubles
Test doubles, including mocks, stubs, and spies, can help isolate and
control interactions with external dependencies during testing.
e. Test Data Management
Use fixtures or factories to manage test data. Tools like Faker can
help generate realistic test data for your application.
f. Test Isolation
Ensure that your tests are independent and don't rely on the state of
other tests. This helps maintain test reliability and prevents
cascading failures.
h. Parallel Testing
i. Continuous Monitoring
a. Node.js Core
You can explore the Node.js core on the official GitHub repository:
https://github.com/nodejs/node.
b. NPM (Node Package Manager)
NPM is the default package manager for Node.js, used for installing,
managing, and sharing Node.js packages. The NPM registry hosts
thousands of open-source packages that can be easily integrated into
your projects.
- javascript
res.send('Hello, Node.js!');
});
app.listen(3000, () => {
});
f. Learning Resources
a. Serverless Computing
- javascript
};
b. Deno
c. GraphQL
- javascript
type Query {
hello: String
`;
const resolvers = {
Query: {
},
};
- javascript
const io = socketIo(server);
});
socket.on('disconnect', () => {
});
});
server.listen(3000, () => {
});
e. Microservices
- javascript
});
app.listen(port, () => {
});