This is a repository for learning Node.js. It contains a collection of resources to learn Node.js from scratch. It includes topics like Node.js, NPM, Modules, Events, File System, HTTP, Express, RESTful API, MongoDB, Mongoose, Authentication, Authorization, Validation, Unit Testing, Integration Testing, Test Driven Development, Deployment, Security, Performance, Scalability, Design Patterns, Error Handling, Logging, Debugging, Monitoring, CI/CD, Docker, Microservices, GraphQL, Websockets, TypeScript, ES6, and Best Practices.
- Introduction
- Prerequisites
- Environment Setup
- ECMAScript
- Chrome's V8 Engine
- JavaScript Runtime
- Node.js
- Features of Node.js
- Node.js Architecture
- Node.js Applications
- Node.js Use Cases
- Node.js Advantages
- Node.js Disadvantages
- Hello World
- NPM
- Modules
- Creating Modules
- Exporting Modules
- Importing Modules
- Built-in Modules
- Custom Modules
- Local Modules
- Module Scope
- Module Wrapper
- Module Caching
- ES Modules
- Importing JSON and Watch Mode
- Path Module
- OS Module
- URL Module
- Query String Module
- Crypto Module
- Zlib Module
- Stream Module
- Child Process Module
- Cluster Module
- Callback Pattern
- Events
- Character Sets and Encoding
- Streams
- Buffers
- Asynchronous JavaScript
- File System
- Pipes
- HTTP
- Thread
- libuv
- Worker Threads
- Queue
- Promises
- Creating a Node Server
- Web Framework
- Express
- RESTful API
- MongoDB
- Mongoose
- Unit Testing
- Integration Testing
- Test Driven Development
- Deployment
- Security
- Security Guidelines
- Performance Optimization
- Performance
- Scalability
- Design Patterns
- Error Handling
- Logging
- Debugging
- Monitoring
- CI/CD
- Docker
- Microservices
- GraphQL
- Websockets
- TypeScript
- ES6
- Best Practices
- Clean Code
- Interview Questions
- Resources
-
Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside a web browser.
-
Node.js lets developers use JavaScript to write command line tools and for server-side scripting.
-
Node.js represents a "JavaScript everywhere" paradigm, unifying web application development around a single programming language, rather than different languages for server- and client-side scripts.
console.log('Hello from Node.js!');
-
Before you start learning Node.js, you should have a basic understanding of JavaScript.
const greet = (name) => `Hello, ${name}!`; console.log(greet('World'));
- You can run Node.js on Windows, macOS, and Linux.
-
You can download Node.js from the official website nodejs.org.
-
You can also install Node.js using a package manager like
chocolatey
&fnm
.# download and install Node.js choco install nodejs-lts --version="20.14.0" # verifies the right Node.js version is in the environment node -v # should print `20` # verifies the right NPM version is in the environment npm -v # should print `10.7.0`
# installs fnm (Fast Node Manager) winget install Schniz.fnm # download and install Node.js fnm use --install-if-missing 20 # verifies the right Node.js version is in the environment node -v # should print `v20.14.0` # verifies the right NPM version is in the environment npm -v # should print `10.7.0`
-
You can download Node.js from the official website nodejs.org.
-
You can also install Node.js using a package manager like
brew
.brew install node
-
You can download Node.js from the official website nodejs.org.
-
You can also install Node.js using a package manager like
apt
.sudo apt install nodejs
-
You can also install Node.js using a package manager like
nvm
.# installs nvm (Node Version Manager) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # download and install Node.js (you may need to restart the terminal) nvm install 20 # verifies the right Node.js version is in the environment node -v # should print `v20.14.0` # verifies the right NPM version is in the environment npm -v # should print `10.7.0`
-
ECMAScript is the standard upon which JavaScript is based, and it's often abbreviated to ES.
const sum = (a, b) => a + b; console.log(sum(1, 2)); // 3
- ECMAScript 5 (ES5) is the fifth edition of the ECMAScript standard.
- ES5 was published in December 2009 and was widely adopted by all modern web browsers.
- ECMAScript 6 (ES6) is the sixth edition of the ECMAScript standard.
- ES6 was published in June 2015 and is also known as ECMAScript 2015.
- V8 is Google's open-source high-performance JavaScript and WebAssembly engine, written in C++.
- It is used in Chrome and in Node.js, among others.
- A JavaScript runtime is a program that executes JavaScript code.
- Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.
- Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine.
- Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient.
- Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
- Asynchronous and Event-Driven
- Very Fast
- Single-Threaded but Highly Scalable
- No Buffering
- Node.js is built on the Google Chrome V8 JavaScript engine.
- It uses a non-blocking, event-driven I/O model.
- It is lightweight and efficient.
- Web Applications
- Real-Time Chat Applications
- RESTful API Applications
- Microservices
- CRON Jobs
- I/O Bound Applications
- Data Streaming Applications
- Data Intensive Real-Time Applications (DIRT)
- JSON APIs based Applications
- Single Page Applications
- Easy to Learn
- Fast Execution
- Large Ecosystem
- Active Community
- Great Performance
- Callback Hell
- Unhandled Exceptions
- Single Threaded
- Not Suitable for CPU Intensive Tasks
console.log('Hello, World!');
-
REPL stands for Read-Eval-Print-Loop. It is a simple, interactive computer programming environment.
$ node > console.log('Hello, World!'); Hello, World! undefined >
-
You can access command line arguments using
process.argv
.process.argv.forEach((val, index) => { console.log(`${index}: ${val}`); });
-
You can access environment variables using
process.env
.console.log(process.env.HOME);
-
Node.js global objects are global in nature and available in all modules.
console.log(__dirname); console.log(__filename);
- npm is the package manager for JavaScript and the world’s largest software registry.
- npm consists of a command line client that interacts with a remote registry.
- npm comes with Node.js. You only need to install Node.js to get npm.
- You can install packages using
npm install <package-name>
. - You can install packages globally using
npm install -g <package-name>
. - You can install packages as development dependencies using
npm install --save-dev <package-name>
. - You can uninstall packages using
npm uninstall <package-name>
. - You can update packages using
npm update <package-name>
. - You can search packages using
npm search <package-name>
. - You can list packages using
npm list
.
-
The
package.json
file is the heart of a Node.js project. -
It contains metadata about the project, such as the name, version, description, and dependencies.
{ "name": "my-app", "version": "1.0.0", "description": "My first Node.js app", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.17.1" }, "devDependencies": { "jest": "^26.6.3" } }
-
Semantic Versioning is a versioning scheme based on three numbers: major, minor, and patch.
-
A version number is in the format of
MAJOR.MINOR.PATCH
.{ "dependencies": { "express": "^4.17.1" } }
-
^4.17.1
means any version from4.17.1
to<5.0.0
.
-
You can run scripts using
npm run <script-name>
.{ "scripts": { "start": "node index.js", "test": "jest" } }
-
You can run
npm start
to start the application.
-
You can create your own modules using
module.exports
.// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
The npm registry is a large public database of JavaScript software and the meta-information surrounding it.
npm search express npm info express
-
You can use the npm CLI to manage packages.
npm install express npm install express@4.17.1 npm install express --save npm install express --save-dev npm uninstall express npm update express npm search express npm list
-
A module encapsulates related code into a single unit of code.
-
A module can be included in other modules using
require
function. -
Node.js has a set of built-in modules which you can use without any further installation.
const fs = require('fs'); const http = require('http'); const url = require('url');
-
You can create your own modules using
module.exports
.// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
You can export modules using
module.exports
.// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
You can import modules using
require
.// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
Node.js has a set of built-in modules which you can use without any further installation.
const fs = require('fs'); const http = require('http'); const url = require('url');
-
You can create your own modules using
module.exports
.// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
Local modules are modules that are stored locally in your project.
// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2));
-
Each module has its own scope.
// math.js const PI = 3.14; module.exports.area = (r) => PI * r * r; // index.js const math = require('./math'); console.log(math.area(5));
-
Node.js wraps each module with a function wrapper.
(function (exports, require, module, __filename, __dirname) { // Your code here });
-
Node.js caches the modules on the first
require
call. -
Subsequent
require
calls will return the cached module.// math.js console.log('math.js is loaded!'); module.exports.add = (a, b) => a + b; // index.js console.log('Before require'); const math = require('./math'); console.log('After require'); const math = require('./math');
-
ES Modules are the official standard format to package JavaScript code for reuse.
-
ES Modules are stored in files.
// math.js export const add = (a, b) => a + b; // index.js import { add } from './math'; console.log(add(1, 2));
-
You can import JSON files using ES Modules.
// data.json { "name": "John Doe", "email": "john.doe@gmail.com" } // index.js import data from './data.json'; console.log(data.name);
-
You can use watch mode to automatically reload the application.
node --experimental-modules --es-module-specifier-resolution=node index.js
node --experimental-modules --es-module-specifier-resolution=node --watch index.js
node --experimental-modules --es-module-specifier-resolution=node --watch-dir . index.js
node --experimental-modules --es-module-specifier-resolution=node --watch-dir . --watch-extensions js, mjs index.js
-
The
path
module provides utilities for working with file and directory paths.const path = require('path'); console.log(path.dirname('/path/to/file.txt')); console.log(path.extname('/path/to/file.txt')); console.log(path.basename('/path/to/file.txt'));
-
The
os
module provides operating system-related utility methods.const os = require('os'); console.log(os.arch()); console.log(os.cpus()); console.log(os.freemem());
-
The
url
module provides utilities for URL resolution and parsing.const url = require('url'); console.log(url.parse('https://example.com')); console.log(url.resolve('https://example.com', '/about'));
-
The
querystring
module provides utilities for parsing and formatting URL query strings.const querystring = require('querystring'); console.log(querystring.parse('name=John Doe')); console.log(querystring.stringify({ name: 'John Doe' }));
-
The
crypto
module provides cryptographic functionality.const crypto = require('crypto'); const hash = crypto.createHash('sha256'); hash.update('Hello, World!'); console.log(hash.digest('hex'));
-
The
zlib
module provides compression and decompression functionality.const zlib = require('zlib'); const input = 'Hello, World!'; zlib.deflate(input, (err, buffer) => { if (!err) { console.log(buffer.toString('base64')); } });
-
The
stream
module provides an API for streaming data.const fs = require('fs'); const readStream = fs.createReadStream('file.txt'); const writeStream = fs.createWriteStream('copy.txt'); readStream.pipe(writeStream);
-
The
child_process
module provides the ability to spawn child processes.const { exec } = require('child_process'); exec('ls -la', (err, stdout, stderr) => { if (!err) { console.log(stdout); } });
-
The
cluster
module allows you to create child processes that share server ports.const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); } } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello, World!'); }).listen(8000); console.log(`Worker ${process.pid} started`); }
-
A callback function is a function passed into another function as an argument.
-
Callback functions can be synchronous or asynchronous.
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
- Events in Node.js are actions or occurrences that happen in the system.
- Node.js has a built-in module,
events
, where you can create-, fire-, and listen for- your own events.
-
Node.js core API is built around an idiomatic asynchronous event-driven architecture in which certain kinds of objects (called "emitters") emit named events that cause Function objects ("listeners") to be called.
const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');
- Node.js is a single-threaded application, but it can support concurrency via the concept of an event loop.
-
Event Emitter patterns are used to handle events in Node.js.
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');
- A character set is a set of characters that can be used in a language.
- An encoding is a mapping from a character set to a sequence of bytes.
-
Streams are objects that let you read data from a source or write data to a destination in continuous fashion.
const fs = require('fs'); const read = fs.createReadStream('file.txt'); const write = fs.createWriteStream('copy.txt'); read.pipe(write);
-
A buffer is a temporary memory location for data when it is being moved from one place to another.
-
Buffers are used to store raw binary data.
const buffer = Buffer.from('Hello, World!'); console.log(buffer.toString());
-
Asynchronous JavaScript is a programming pattern that provides non-blocking I/O operations.
-
Asynchronous JavaScript uses callbacks to handle asynchronous operations.
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
- Node.js includes
fs
module to work with the file system. - The
fs
module provides file I/O operations using simple wrappers around standard POSIX functions.
-
You can read files using
fs.readFile
.const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
You can write files using
fs.writeFile
.const fs = require('fs'); fs.writeFile('file.txt', 'Hello, World!', (err) => { if (err) throw err; console.log('The file has been saved!'); });
-
You can delete files using
fs.unlink
.const fs = require('fs'); fs.unlink('file.txt', (err) => { if (err) throw err; console.log('The file has been deleted!'); });
-
You can rename files using
fs.rename
.const fs = require('fs'); fs.rename('file.txt', 'newfile.txt', (err) => { if (err) throw err; console.log('The file has been renamed!'); });
-
Pipes are used to connect the output of one stream to another stream.
const fs = require('fs'); const read = fs.createReadStream('file.txt'); const write = fs.createWriteStream('copy.txt'); read.pipe(write);
- Node.js has a built-in module,
http
, which allows Node.js to transfer data over the Hyper Text Transfer Protocol (HTTP). - Node.js has a built-in module,
https
, which allows Node.js to transfer data over secure Hyper Text Transfer Protocol (HTTPS).
-
You can create an HTTP server using
http.createServer
.const http = require('http'); const server = http.createServer((req, res) => { res.end('Hello, World!'); }); server.listen(3000);
-
You can handle requests using
req
andres
objects.const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello, World!'); }); server.listen(3000);
-
You can route requests using
url
module.const http = require('http'); const url = require('url'); const server = http.createServer((req, res) => { const path = url.parse(req.url).pathname; if (path === '/') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Home Page'); } else if (path === '/about') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('About Page'); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); } }); server.listen(3000);
-
You can parse query strings using
url
module.const http = require('http'); const url = require('url'); const server = http.createServer((req, res) => { const query = url.parse(req.url, true).query; res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end(`Hello, ${query.name}!`); }); server.listen(3000);
-
You can redirect requests using
res.writeHead
.const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(301, { 'Location': 'http://example.com' }); res.end(); }); server.listen(3000);
- Node.js is a single-threaded application, but it can support concurrency via the concept of an event loop.
-
libuv is a multi-platform support library with a focus on asynchronous I/O.
-
Node.js uses the
libuv
library to handle asynchronous operations.const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
Worker threads are used to perform CPU-intensive JavaScript operations.
const { Worker, isMainThread, parentPort } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename); worker.on('message', (message) => { console.log(message); }); worker.postMessage('Hello, World!'); } else { parentPort.on('message', (message) => { parentPort.postMessage(message); }); }
-
A queue is a data structure that stores elements in a First-In-First-Out (FIFO) order.
class Queue { constructor() { this.items = []; } enqueue(element) { this.items.push(element); } dequeue() { return this.items.shift(); } front() { return this.items[0]; } isEmpty() { return this.items.length === 0; } print() { console.log(this.items.toString()); } } const queue = new Queue(); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); queue.print(); queue.dequeue(); queue.print();
-
Microtask Queue is a queue that stores microtasks in a First-In-First-Out (FIFO) order.
console.log('Start'); setTimeout(() => { console.log('Timeout'); }, 0); Promise.resolve().then(() => { console.log('Promise'); }); console.log('End');
-
Timer Queue is a queue that stores timers in a First-In-First-Out (FIFO) order.
console.log('Start'); setTimeout(() => { console.log('Timeout'); }, 0); console.log('End');
-
I/O Queue is a queue that stores I/O operations in a First-In-First-Out (FIFO) order.
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
Check Queue is a queue that stores check operations in a First-In-First-Out (FIFO) order.
setImmediate(() => { console.log('Immediate'); }); console.log('End');
-
Close Queue is a queue that stores close operations in a First-In-First-Out (FIFO) order.
const server = require('http').createServer(); server.listen(3000); server.close(() => { console.log('Server closed'); });
-
I/O Polling is a mechanism that polls the I/O Queue for I/O operations.
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
Network I/O is a mechanism that handles network I/O operations.
const server = require('http').createServer(); server.listen(3000);
-
Timers are used to schedule tasks to be executed in the future.
setTimeout(() => { console.log('Timeout'); }, 1000);
-
A promise is an object representing the eventual completion or failure of an asynchronous operation.
const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello, World!'); }, 1000); }); promise.then((value) => { console.log(value); });
-
You can chain promises using
then
.const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello,'); }, 1000); }); promise.then((value) => { return value + ' World!'; }).then((value) => { console.log(value); });
-
You can create a simple Node server.
const http = require('http'); const server = http.createServer((req, res) => { res.end('Hello, World!'); }); server.listen(3000);
-
You can send JSON responses.
const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Hello, World!' })); }); server.listen(3000);
-
You can send HTML responses.
const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('<h1>Hello, World!</h1>'); }); server.listen(3000);
-
You can use HTML templates.
const http = require('http'); const server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(` <h1>Hello, World!</h1> <p>${new Date()}</p> `); }); server.listen(3000);
-
You can create routes using
url
module.const http = require('http'); const url = require('url'); const server = http.createServer((req, res) => { const path = url.parse(req.url).pathname; if (path === '/') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Home Page'); } else if (path === '/about') { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('About Page'); } else { res.writeHead(404, { 'Content-Type': 'text/plain' }); res.end('Not Found'); } }); server.listen(3000);
- A web framework is a software framework designed to aid in the development of web applications including web services, web resources, and web APIs.
-
There are many web frameworks available for Node.js.
- Express
- Koa
- Hapi
- Nest
- Fastify
- Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
- Express provides a thin layer of fundamental web application features, without obscuring Node.js features.
- You can install Express using
npm install express
.
-
You can create a simple Express application.
const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
Middleware functions are functions that have access to the request object (
req
), the response object (res
), and the next middleware function in the application’s request-response cycle.const express = require('express'); const app = express(); app.use((req, res, next) => { console.log('Time:', Date.now()); next(); }); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
You can create routes using
app.get
,app.post
,app.put
, andapp.delete
.const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Home Page'); }); app.get('/about', (req, res) => { res.send('About Page'); }); app.listen(3000);
-
Express supports a variety of template engines.
const express = require('express'); const app = express(); app.set('view engine', 'pug'); app.get('/', (req, res) => { res.render('index', { title: 'Express' }); }); app.listen(3000);
-
You can serve static files using
express.static
.const express = require('express'); const app = express(); app.use(express.static('public')); app.listen(3000);
-
You can handle errors using
app.use
.const express = require('express'); const app = express(); app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!'); }); app.listen(3000);
- REST (Representational State Transfer) is an architectural style for designing networked applications.
- A RESTful API is an application program interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data.
-
RESTful APIs use standard HTTP methods.
GET
to retrieve a resource.POST
to create a resource.PUT
to update a resource.DELETE
to delete a resource.
-
RESTful APIs use endpoints to access resources.
GET /api/users
to get all users.POST /api/users
to create a user.GET /api/users/:id
to get a user.PUT /api/users/:id
to update a user.DELETE /api/users/:id
to delete a user.
-
RESTful APIs use standard HTTP status codes.
200 OK
for successful requests.201 Created
for successful creation.400 Bad Request
for invalid requests.404 Not Found
for missing resources.500 Internal Server Error
for server errors.
-
RESTful APIs use JSON (JavaScript Object Notation) to exchange data.
{ "id": 1, "name": "John Doe", "email": "johndoe@gmail.com" }
-
RESTful APIs use CRUD (Create, Read, Update, Delete) operations.
GET /api/users
to get all users.POST /api/users
to create a user.GET /api/users/:id
to get a user.PUT /api/users/:id
to update a user.DELETE /api/users/:id
to delete a user.
-
RESTful APIs use authentication to secure resources.
Basic Auth
using username and password.Token Auth
using JWT (JSON Web Tokens).OAuth
using OAuth 2.0 protocol.
-
RESTful APIs use authorization to control access to resources.
Role Based
access control.Attribute Based
access control.Policy Based
access control.
-
RESTful APIs use validation to ensure data integrity.
Input Validation
to validate user input.Schema Validation
to validate data structure.Business Rules
to validate business logic.
-
RESTful APIs use pagination to limit data.
Limit
to limit the number of records.Offset
to skip a number of records.Page
to get a specific page of records.
-
RESTful APIs use filtering to search data.
Filter
to search by specific criteria.Sort
to sort data by specific criteria.Search
to search by keyword.
-
RESTful APIs use versioning to manage changes.
URI Versioning
using the URI path.Header Versioning
using the request header.Media Type Versioning
using the request header.
-
HATEOAS (Hypermedia as the Engine of Application State) is a constraint of the REST application architecture.
Links
to navigate between resources.Actions
to perform operations on resources.Forms
to submit data to resources.
- MongoDB is a cross-platform document-oriented database program.
- Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas.
- Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js.
- It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.
- Unit testing is a software testing method by which individual units of source code are tested to determine whether they are fit for use.
- Jest is a delightful JavaScript Testing Framework with a focus on simplicity.
// math.js
const add = (a, b) => a + b;
module.exports = add;
// math.test.js
const add = require('./math');
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
-
Integration testing is the phase in software testing in which individual software modules are combined and tested as a group.
-
Supertest is a high-level abstraction for testing HTTP.
// app.js const express = require('express'); const app = express(); app.get('/', (req, res) => { res.send('Hello, World!'); }); module.exports = app; // app.test.js const request = require('supertest'); const app = require('./app'); test('GET /', async () => { const response = await request(app).get('/'); expect(response.text).toBe('Hello, World!'); });
-
Test-driven development (TDD) is a software development process that relies on the repetition of a very short development cycle.
-
TDD is a programming technique that involves writing tests before writing the actual code.
// math.js const add = (a, b) => a + b; module.exports = add; // math.test.js const add = require('./math'); test('adds 1 + 2 to equal 3', () => { expect(add(1, 2)).toBe(3); });
- Deployment is the process of making a software system available for use.
-
Security is the degree of resistance to, or protection from, harm.
-
Helmet helps secure Express apps by setting various HTTP headers.
const express = require('express'); const helmet = require('helmet'); const app = express(); app.use(helmet());
- JWT implementation
- OAuth2 integration
- Role-based access control
- Session management
- Input validation
- Output encoding
- SQL injection prevention
- XSS protection
- HTTPS setup
- Rate limiting
- CORS configuration
- Security headers
-
Performance is a measure of how quickly a system performs a certain process or transaction.
-
PM2 is a production process manager for Node.js applications with a built-in load balancer.
pm2 start app.js
- Memory leaks detection
- Heap analysis
- Garbage collection optimization
- Memory monitoring
- Blocking operations analysis
- Hot code paths identification
- Async operations optimization
- Worker threads usage
- Connection pooling
- Request queuing
- Response caching
- Load balancing
-
Scalability is the capability of a system to handle a growing amount of work, or its potential to accommodate growth.
-
Horizontal scaling means that you scale by adding more machines into your pool of resources.
pm2 start app.js -i max
pm2 scale app +3
pm2 scale app 2
-
Design patterns are typical solutions to common problems in software design.
-
Design patterns can speed up the development process by providing tested, proven development paradigms.
// Singleton Pattern class Singleton { constructor() { if (!Singleton.instance) { Singleton.instance = this; } return Singleton.instance; } } const instance1 = new Singleton(); const instance2 = new Singleton(); console.log(instance1 === instance2);
-
Error handling is the process of responding to and recovering from error conditions in a program.
-
Express has a default error handler, but you can also define custom error handlers.
const express = require('express'); const app = express(); app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!'); });
-
Logging is the process of recording events that happen in an application.
-
Winston is a versatile logging library for Node.js.
const winston = require('winston'); const logger = winston.createLogger({ level: 'info', format: winston.format.json(), defaultMeta: { service: 'user-service' }, transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); logger.info('Hello, World!');
-
Debugging is the process of finding and resolving defects or problems within a computer program.
-
Node.js has a built-in debugging interface.
node inspect app.js
node --inspect app.js
node --inspect-brk app.js
node --inspect=
node --inspect-brk=
node --inspect --debug-brk app.js
node --inspect --debug-brk=
node --inspect --debug-brk --inspect-brk app.js
node --inspect --debug-brk --inspect-brk=
node --inspect --debug-brk --inspect-brk= app.js
-
Monitoring is the process of observing and checking the progress or quality of a program over time.
-
PM2 provides a monitoring feature.
pm2 monit
-
Continuous Integration (CI) is the practice of merging all developer working copies to a shared mainline several times a day.
-
Continuous Deployment (CD) is a strategy for software releases wherein any code commit that passes the automated testing phase is automatically released into the production environment.
name: CI on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js uses: actions/setup-node@v2 with: node-version: '14' - name: Install Dependencies run: npm install - name: Run Tests run: npm test
name: CD on: push: branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js uses: actions/setup-node@v2 with: node-version: '14' - name: Install Dependencies run: npm install - name: Build run: npm run build - name: Deploy run: | npm install -g pm2 pm2 start app.js
-
Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers.
-
A Docker container image is a lightweight, standalone, executable package of software that includes everything needed to run a piece of software.
# Dockerfile FROM node:14 WORKDIR /app COPY package.json . RUN npm install COPY . . EXPOSE 3000 CMD ["node", "app.js"]
docker build -t my-app . docker run -p 3000:3000 my-app
- Microservices is a variant of the service-oriented architecture (SOA) architectural style that structures an application as a collection of loosely coupled services.
- Each service is self-contained and should implement a single business capability.
-
GraphQL is a query language for APIs and a runtime for executing those queries by using a type system you define for your data.
-
GraphQL is a specification for how to communicate with APIs.
const { ApolloServer, gql } = require('apollo-server'); const typeDefs = gql` type Query { hello: String } `; const resolvers = { Query: { hello: () => 'Hello, World!', }, }; const server = new ApolloServer({ typeDefs, resolvers }); server.listen().then(({ url }) => { console.log(`Server ready at ${url}`); });
-
WebSockets is a communication protocol that provides full-duplex communication channels over a single TCP connection.
-
Socket.IO enables real-time, bidirectional and event-based communication.
const http = require('http'); const server = http.createServer(); const io = require('socket.io')(server); io.on('connection', (socket) => { console.log('a user connected'); socket.on('disconnect', () => { console.log('user disconnected'); }); }); server.listen(3000);
-
TypeScript is an open-source programming language developed and maintained by Microsoft.
-
TypeScript is a strict syntactical superset of JavaScript and adds optional static typing to the language.
// math.ts const add = (a: number, b: number): number => a + b; export default add; // index.ts import add from './math'; console.log(add(1, 2));
-
ECMAScript 6, also known as ECMAScript 2015, is the latest version of the ECMAScript standard.
-
ES6 includes significant enhancements to the language, such as arrow functions, classes, template literals, and let + const.
// ES6 Arrow Functions const add = (a, b) => a + b; // ES6 Classes class Math { add(a, b) { return a + b; } } // ES6 Template Literals const name = 'John Doe'; console.log(`Hello, ${name}!`); // ES6 Destructuring const [a, b] = [1, 2]; console.log(a, b); // ES6 Spread Operator const a = [1, 2]; const b = [3, 4]; const c = [...a, ...b]; console.log(c);
-
Best practices are a set of guidelines, ethics or ideas that represent the most efficient or prudent course of action.
-
Node.js best practices include error-first callbacks, event emitters, streams, and middleware.
// Error-First Callbacks fs.readFile('file.txt', (err, data) => { if (err) throw err; console.log(data); }); // Event Emitters const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event'); // Streams const fs = require('fs'); const readStream = fs.createReadStream('file.txt'); readStream.on('data', (data) => { console.log(data); }); // Middleware const express = require('express'); const app = express(); app.use((req, res, next) => { console.log('Time:', Date.now()); next(); });
-
Clean code is code that is easy to understand, easy to maintain, and easy to extend.
// Bad Code const a = 1; // Variable a const b = 2; // Variable b const c = a + b; // Sum of a and b // Good Code const sum = (a, b) => a + b; const a = 1; const b = 2; const c = sum(a, b);
-
What is Node.js?
-
Node.js is an open-source, cross-platform, JavaScript runtime environment that executes JavaScript code outside a web browser. It is built on Chrome's V8 JavaScript engine and uses an event-driven, non-blocking I/O model.
Code Example:
console.log('Hello from Node.js!'); // Check Node.js version and environment console.log(`Node.js Version: ${process.version}`); console.log(`Platform: ${process.platform}`);
-
-
How does Node.js handle asynchronous operations?
-
Node.js handles asynchronous operations using an event-driven architecture and the event loop. It uses callbacks, Promises, and async/await to manage asynchronous code execution.
Code Example:
// Callback example const fs = require('fs'); fs.readFile('input.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); }); // Promise example const readFilePromise = () => { return new Promise((resolve, reject) => { fs.readFile('input.txt', 'utf8', (err, data) => { if (err) reject(err); resolve(data); }); }); }; // Async/await example async function readFileAsync() { try { const data = await readFilePromise(); console.log(data); } catch (err) { console.error(err); } }
-
-
What are the differences between var, let, and const in Node.js?
var
is function-scoped and can be redeclared.let
andconst
are block-scoped;let
can be reassigned, whileconst
cannot be reassigned.
Code Example:
// Function scope with var function varExample() { var x = 1; if (true) { var x = 2; // same variable console.log(x); // 2 } console.log(x); // 2 } // Block scope with let function letExample() { let x = 1; if (true) { let x = 2; // different variable console.log(x); // 2 } console.log(x); // 1 } // Const example const PI = 3.14; // PI = 3.15; // TypeError: Assignment to constant variable
-
What is the event loop in Node.js?
-
The event loop is a mechanism that allows Node.js to perform non-blocking I/O operations by offloading operations to the system kernel whenever possible.
Code Example:
console.log('Start'); setTimeout(() => { console.log('Timeout'); }, 0); Promise.resolve().then(() => { console.log('Promise'); }); console.log('End'); // Output: Start, End, Promise, Timeout
-
-
Explain the concept of callbacks in Node.js.
-
A callback is a function passed into another function as an argument, which is then invoked inside the outer function to complete some kind of routine or action.
Code Example:
const fs = require('fs'); fs.readFile('input.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
-
What are streams in Node.js?
-
Streams are objects that let you read data from a source or write data to a destination in a continuous fashion. They are used to handle reading/writing files, network communications, or any kind of end-to-end information exchange.
Code Example:
const fs = require('fs'); const readStream = fs.createReadStream('file.txt'); const writeStream = fs.createWriteStream('copy.txt'); readStream.pipe(writeStream);
-
-
How do you handle file operations in Node.js?
-
File operations in Node.js are handled using the
fs
module, which provides methods for reading, writing, deleting, and renaming files.Code Example:
const fs = require('fs'); // Reading a file fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); }); // Writing to a file fs.writeFile('file.txt', 'Hello, World!', (err) => { if (err) throw err; console.log('The file has been saved!'); }); // Deleting a file fs.unlink('file.txt', (err) => { if (err) throw err; console.log('The file has been deleted!'); }); // Renaming a file fs.rename('file.txt', 'newfile.txt', (err) => { if (err) throw err; console.log('The file has been renamed!'); });
-
-
What are global objects in Node.js?
-
Global objects are objects that are available in all modules. Examples include
__dirname
,__filename
,process
,Buffer
, andglobal
.Code Example:
console.log(__dirname); console.log(__filename); console.log(process.env); console.log(Buffer.from('Hello, World!').toString());
-
-
How do you export and import modules in Node.js?
-
Modules are exported using
module.exports
orexports
and imported usingrequire()
for CommonJS modules. For ES6 modules,export
andimport
are used.Code Example:
// math.js module.exports.add = (a, b) => a + b; // index.js const math = require('./math'); console.log(math.add(1, 2)); // ES6 Modules // math.js export const add = (a, b) => a + b; // index.js import { add } from './math'; console.log(add(1, 2));
-
-
What is the difference between process.nextTick(), setImmediate(), and setTimeout()?
-
process.nextTick()
schedules a callback to be invoked in the next iteration of the event loop.setImmediate()
schedules a callback to be executed in the next iteration of the event loop after I/O events.setTimeout()
schedules a callback to be executed after a specified delay.Code Example:
console.log('Start'); process.nextTick(() => { console.log('Next Tick'); }); setImmediate(() => { console.log('Immediate'); }); setTimeout(() => { console.log('Timeout'); }, 0); console.log('End');
-
-
What is middleware in Node.js? How is it used in Express.js?
-
Middleware functions are functions that have access to the request object, the response object, and the next middleware function in the application’s request-response cycle. In Express.js, middleware is used to handle requests, responses, and errors.
Code Example:
const express = require('express'); const app = express(); app.use((req, res, next) => { console.log('Time:', Date.now()); next(); }); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
-
Explain the concept of Promises and async/await in Node.js.
-
Promises represent the eventual completion (or failure) of an asynchronous operation and its resulting value.
async/await
is syntactic sugar built on Promises, allowing asynchronous code to be written in a synchronous style.Code Example:
// Promise example const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello, World!'); }, 1000); }); promise.then((value) => { console.log(value); }); // Async/await example async function asyncFunction() { const value = await promise; console.log(value); } asyncFunction();
-
-
How do you handle errors in Node.js applications?
-
Errors in Node.js applications are handled using try-catch blocks, error-first callbacks, and error-handling middleware in Express.js.
Code Example:
// Try-catch block try { throw new Error('Something went wrong!'); } catch (err) { console.error(err.message); } // Error-first callback const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) { console.error(err.message); return; } console.log(data); }); // Error-handling middleware in Express.js const express = require('express'); const app = express(); app.use((err, req, res, next) => { console.error(err.stack); res.status(500).send('Something broke!'); }); app.listen(3000);
-
-
What is the difference between synchronous and asynchronous code in Node.js?
-
Synchronous code is executed sequentially, blocking the execution of subsequent code until the current operation completes. Asynchronous code allows other operations to continue before the current operation completes, using callbacks, Promises, or async/await.
Code Example:
// Synchronous code const fs = require('fs'); const data = fs.readFileSync('file.txt', 'utf8'); console.log(data); // Asynchronous code fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
-
Explain the working of the cluster module in Node.js.
-
The cluster module allows you to create child processes (workers) that share the same server port, enabling the creation of a multi-process server to handle concurrent requests.
Code Example:
const cluster = require('cluster'); const http = require('http'); const numCPUs = require('os').cpus().length; if (cluster.isMaster) { console.log(`Master ${process.pid} is running`); for (let i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('exit', (worker, code, signal) => { console.log(`Worker ${worker.process.pid} died`); }); } else { http.createServer((req, res) => { res.writeHead(200); res.end('Hello, World!'); }).listen(8000); console.log(`Worker ${process.pid} started`); }
-
-
How do you secure a Node.js application?
-
Security measures include using HTTPS, validating and sanitizing user input, using environment variables for sensitive information, implementing authentication and authorization, and using security-related middleware like Helmet.
Code Example:
const express = require('express'); const helmet = require('helmet'); const app = express(); app.use(helmet()); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
-
What is the difference between require() and import in Node.js?
-
require()
is used for CommonJS modules, whileimport
is used for ES6 modules.require()
is synchronous, whileimport
is asynchronous and supports static analysis.Code Example:
// CommonJS const math = require('./math'); console.log(math.add(1, 2)); // ES6 Modules import { add } from './math'; console.log(add(1, 2));
-
-
What is the purpose of package.json and package-lock.json?
-
package.json
contains metadata about the project and its dependencies.package-lock.json
records the exact versions of dependencies installed, ensuring consistent installs across environments.Code Example:
// package.json { "name": "my-app", "version": "1.0.0", "description": "My first Node.js app", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.17.1" }, "devDependencies": { "jest": "^26.6.3" } } // package-lock.json { "name": "my-app", "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { "express": { "version": "4.17.1", "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", "integrity": "sha512-...", "requires": { "accepts": "~1.3.7", "array-flatten": "1.1.1", // ...other dependencies... } }, // ...other dependencies... } }
-
-
How do you manage environment variables in Node.js?
-
Environment variables are managed using the
process.env
object or by using packages likedotenv
to load variables from a.env
file.Code Example:
// Using process.env console.log(process.env.NODE_ENV); // Using dotenv require('dotenv').config(); console.log(process.env.DB_HOST);
-
-
Explain the concept of CORS and how to handle it in Node.js.
-
CORS (Cross-Origin Resource Sharing) is a mechanism that allows restricted resources on a web page to be requested from another domain. It is handled in Node.js using the
cors
middleware.Code Example:
const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
-
How does Node.js achieve non-blocking I/O operations?
-
Node.js achieves non-blocking I/O operations using an event-driven architecture and the event loop, which offloads I/O operations to the system kernel.
Code Example:
const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); });
-
-
Explain the architecture of Node.js.
-
Node.js architecture is based on the event-driven, non-blocking I/O model. It uses the V8 JavaScript engine, libuv for asynchronous I/O, and a single-threaded event loop to handle multiple concurrent operations.
Code Example:
const http = require('http'); const server = http.createServer((req, res) => { res.end('Hello, World!'); }); server.listen(3000);
-
-
What are worker threads in Node.js, and when would you use them?
-
Worker threads are used to perform CPU-intensive JavaScript operations in parallel. They are used when you need to offload heavy computations from the main thread to improve performance.
Code Example:
const { Worker, isMainThread, parentPort } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename); worker.on('message', (message) => { console.log(message); }); worker.postMessage('Hello, World!'); } else { parentPort.on('message', (message) => { parentPort.postMessage(message); }); }
-
-
How do you handle memory leaks in Node.js applications?
-
Memory leaks are handled by profiling the application using tools like Node.js built-in inspector, Chrome DevTools, or third-party tools like
heapdump
andmemwatch-next
.Code Example:
// Profiling with Node.js built-in inspector const inspector = require('inspector'); inspector.open(9229, 'localhost', true); // Profiling with Chrome DevTools console.log('Open chrome://inspect in Chrome to start profiling');
-
-
Explain the difference between process and thread in Node.js.
-
A process is an instance of a program in execution, with its own memory space. A thread is a smaller unit of a process that can be scheduled for execution. Node.js uses a single-threaded event loop for handling asynchronous operations.
Code Example:
// Process example console.log(`Process ID: ${process.pid}`); // Thread example using worker threads const { Worker, isMainThread, parentPort } = require('worker_threads'); if (isMainThread) { const worker = new Worker(__filename); worker.on('message', (message) => { console.log(message); }); worker.postMessage('Hello, World!'); } else { parentPort.on('message', (message) => { parentPort.postMessage(message); }); }
-
-
What are microservices, and how can they be implemented in Node.js?
-
Microservices are a design pattern where an application is composed of small, independent services that communicate over a network. They can be implemented in Node.js using frameworks like Express, Koa, or NestJS.
Code Example:
// User service const express = require('express'); const app = express(); app.get('/users', (req, res) => { res.json([{ id: 1, name: 'John Doe' }]); }); app.listen(3001, () => { console.log('User service running on port 3001'); }); // Order service const express = require('express'); const app = express(); app.get('/orders', (req, res) => { res.json([{ id: 1, user_id: 1, product: 'Laptop' }]); }); app.listen(3002, () => { console.log('Order service running on port 3002'); });
-
-
Describe the role of event emitters in Node.js.
-
Event emitters are objects that can emit named events and register listeners for those events. They are used to handle asynchronous events in Node.js.
Code Example:
const EventEmitter = require('events'); const myEmitter = new EventEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');
-
-
What are the performance optimization techniques for Node.js applications?
-
Techniques include using asynchronous code, optimizing database queries, using caching, load balancing, clustering, and profiling the application to identify bottlenecks.
Code Example:
// Asynchronous code const fs = require('fs'); fs.readFile('file.txt', 'utf8', (err, data) => { if (err) throw err; console.log(data); }); // Caching const cache = {}; function getData(key) { if (cache[key]) { return cache[key]; } const data = fetchDataFromDatabase(key); cache[key] = data; return data; }
-
-
How do you implement rate limiting in Node.js?
-
Rate limiting can be implemented using middleware like
express-rate-limit
to limit the number of requests a client can make to an API within a specified time frame.Code Example:
const express = require('express'); const rateLimit = require('express-rate-limit'); const app = express(); const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100 // limit each IP to 100 requests per windowMs }); app.use(limiter); app.get('/', (req, res) => { res.send('Hello, World!'); }); app.listen(3000);
-
-
Explain the difference between monolithic and distributed architectures in the context of Node.js.
-
A monolithic architecture is a single, unified codebase for the entire application. A distributed architecture, such as microservices, breaks the application into smaller, independent services that communicate over a network.
Code Example:
// Monolithic architecture const express = require('express'); const app = express(); app.get('/users', (req, res) => { res.json([{ id: 1, name: 'John Doe' }]); }); app.get('/orders', (req, res) => { res.json([{ id: 1, user_id: 1, product: 'Laptop' }]); }); app.listen(3000, () => { console.log('Server running on port 3000'); }); // Distributed architecture (microservices) // User service const express = require('express'); const app = express(); app.get('/users', (req, res) => { res.json([{ id: 1, name: 'John Doe' }]); }); app.listen(3001, () => { console.log('User service running on port 3001'); }); // Order service const express = require('express'); const app = express(); app.get('/orders', (req, res) => { res.json([{ id: 1, user_id: 1, product: 'Laptop' }]); }); app.listen(3002, () => { console.log('Order service running on port 3002'); });
-
- Node.js Documentation
- Express Documentation
- MongoDB Documentation
- Mongoose Documentation
- Jest Documentation
If you like this learning repository and find it useful, consider buying me a coffee or sponsoring me through the GitHub Sponsor. Your support will help me to continue and bring more exciting projects. Thank you!
Show your support by 🌟 the repository.