Getting Started

Installation & Setup

# Install Node.js from official website
# https://nodejs.org

# Check Node.js version
node --version

# Check npm version
npm --version

# Initialize a new Node.js project
npm init

# Initialize with default values
npm init -y
Note: Node.js comes with npm (Node Package Manager) included. Always verify your installation with the version commands.

Basic HTTP Server

// Import the http module
const http = require('http');

// Create a server
const server = http.createServer((req, res) => {
  // Set response header
  res.writeHead(200, {'Content-Type': 'text/plain'});
  // Send response
  res.end('Hello, Node.js!');
});

// Listen on port 3000
server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

Core Modules

File System (fs)

// Import fs module
const fs = require('fs');

// Read file (async)
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// Read file (sync)
const data = fs.readFileSync('file.txt', 'utf8');

// Write file (async)
fs.writeFile('file.txt', 'Hello World', (err) => {
  if (err) throw err;
  console.log('File written!');
});

// Append to file
fs.appendFile('file.txt', 'New data', (err) => {
  if (err) throw err;
  console.log('Data appended!');
});

Path Module

// Import path module
const path = require('path');

// Get directory name
const dirName = path.dirname('/path/to/file.txt');

// Get file extension
const ext = path.extname('index.html'); // .html

// Join path segments
const fullPath = path.join('/foo', 'bar', 'baz/asdf');

// Resolve absolute path
const absPath = path.resolve('file.txt');

// Get base name
const base = path.basename('/path/to/file.txt'); // file.txt

// Parse path
const parsed = path.parse('/path/to/file.txt');
// Returns: { root: '/', dir: '/path/to', base: 'file.txt', ext: '.txt', name: 'file' }

Events Module

// Import events module
const EventEmitter = require('events');

// Create custom event emitter
class MyEmitter extends EventEmitter {}

// Create instance
const myEmitter = new MyEmitter();

// Register event listener
myEmitter.on('event', () => {
  console.log('An event occurred!');
});

// Emit event
myEmitter.emit('event');

// Event with parameters
myEmitter.on('data', (data) => {
  console.log(`Received data: ${data}`);
});

myEmitter.emit('data', 'Hello World');

OS Module

// Import os module
const os = require('os');

// Get OS platform
const platform = os.platform(); // 'darwin', 'win32', 'linux'

// Get CPU architecture
const arch = os.arch(); // 'x64', 'arm'

// Get total system memory
const totalMem = os.totalmem();

// Get free system memory
const freeMem = os.freemem();

// Get system uptime
const uptime = os.uptime();

// Get user info
const userInfo = os.userInfo();

// Get network interfaces
const network = os.networkInterfaces();

// Get home directory
const homedir = os.homedir();

// Get temp directory
const tmpdir = os.tmpdir();

NPM & Packages

NPM Basics

# Install a package locally
npm install package-name

# Install a specific version
npm install package-name@version

# Install as dev dependency
npm install --save-dev package-name

# Install globally
npm install -g package-name

# Update a package
npm update package-name

# Uninstall a package
npm uninstall package-name

# List installed packages
npm list

# List outdated packages
npm outdated

# Run scripts defined in package.json
npm run script-name

Package.json

{
  "name": "my-app",
  "version": "1.0.0",
  "description": "My Node.js application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "dev": "nodemon index.js",
    "test": "jest"
  },
  "keywords": ["nodejs", "javascript"],
  "author": "Your Name",
  "license": "MIT",
  "dependencies": {
    "express": "^4.18.2",
    "mongoose": "^7.0.3"
  },
  "devDependencies": {
    "nodemon": "^2.0.22",
    "jest": "^29.5.0"
  },
  "engines": {
    "node": ">=14.0.0"
  }
}

Express.js Framework

Basic Express Server

// Install Express
// npm install express

// Import Express
const express = require('express');
const app = express();
const port = 3000;

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

// Route with parameters
app.get('/users/:id', (req, res) => {
  res.send(`User ID: ${req.params.id}`);
});

// Start server
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

Middleware

// Built-in middleware
app.use(express.json()); // Parse JSON bodies
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies

// Custom middleware
app.use((req, res, next) => {
  console.log(`${req.method} ${req.path}`);
  next(); // Pass control to next middleware
});

// Error handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

// Third-party middleware (install first)
// npm install cors morgan helmet
const cors = require('cors');
const morgan = require('morgan');
const helmet = require('helmet');

app.use(cors()); // Enable CORS
app.use(morgan('combined')); // HTTP request logger
app.use(helmet()); // Security headers

Routing

// Different HTTP methods
app.get('/resource', (req, res) => {
  // Handle GET request
  res.send('GET request');
});

app.post('/resource', (req, res) => {
  // Handle POST request
  res.send('POST request');
});

app.put('/resource/:id', (req, res) => {
  // Handle PUT request
  res.send(`PUT request for ID ${req.params.id}`);
});

app.delete('/resource/:id', (req, res) => {
  // Handle DELETE request
  res.send(`DELETE request for ID ${req.params.id}`);
});

// Route chaining
app.route('/book')
  .get((req, res) => { res.send('Get a book'); })
  .post((req, res) => { res.send('Add a book'); })
  .put((req, res) => { res.send('Update the book'); });

// Router module (create in separate file)
const router = express.Router();

router.get('/', (req, res) => {
  res.send('Router home');
});

// Mount the router
app.use('/route', router);

Template Engines

// Set EJS as template engine
// npm install ejs
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// Render a view
app.get('/', (req, res) => {
  res.render('index', {
    title: 'Home Page',
    message: 'Hello EJS!'
  });
});

// Using Pug (formerly Jade)
// npm install pug
app.set('view engine', 'pug');

// Using Handlebars
// npm install express-handlebars
const exphbs = require('express-handlebars');
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');

// Serve static files
app.use(express.static('public'));

// Multiple static directories
app.use(express.static('public'));
app.use(express.static('uploads'));

Database Integration

MongoDB with Mongoose

// Install Mongoose
// npm install mongoose

// Connect to MongoDB
const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/mydatabase', {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

// Define a schema
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  },
  age: {
    type: Number,
    min: 18
  },
  createdAt: {
    type: Date,
    default: Date.now
  }
});

// Create a model
const User = mongoose.model('User', userSchema);

// Create a new user
const newUser = new User({
  name: 'John Doe',
  email: 'john@example.com',
  age: 25
});

newUser.save((err, user) => {
  if (err) return console.error(err);
  console.log('User saved:', user);
});

// Find users
User.find({ age: { $gte: 21 } }, (err, users) => {
  if (err) return console.error(err);
  console.log('Users:', users);
});

MySQL with Sequelize

// Install Sequelize and MySQL2
// npm install sequelize mysql2

// Connect to database
const Sequelize = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql',
  logging: false // Disable SQL logging in console
});

// Define a model
const User = sequelize.define('User', {
  name: {
    type: Sequelize.STRING,
    allowNull: false
  },
  email: {
    type: Sequelize.STRING,
    allowNull: false,
    unique: true,
    validate: {
      isEmail: true
    }
  },
  age: {
    type: Sequelize.INTEGER,
    validate: {
      min: 18
    }
  }
}, {
  timestamps: true // Adds createdAt and updatedAt fields
});

// Sync model with database
sequelize.sync({ force: false }) // Set force: true to drop tables and recreate
.then(() => {
  console.log('Database & tables created!');
});

// Create a new user
User.create({
  name: 'Jane Doe',
  email: 'jane@example.com',
  age: 28
}).then(user => {
  console.log('User created:', user.toJSON());
}).catch(err => {
  console.error('Error creating user:', err);
});

// Find all users
User.findAll().then(users => {
  console.log('All users:', users);
});

Error Handling

Try-Catch & Async/Await

// Using try-catch with async/await
app.get('/user/:id', async (req, res, next) => {
  try {
    const user = await User.findById(req.params.id);
    if (!user) {
      return res.status(404).json({ error: 'User not found' });
    }
    res.json(user);
  } catch (err) {
    next(err); // Pass to error handling middleware
  }
});

// Using promises
app.get('/users', (req, res, next) => {
  User.findAll()
    .then(users => {
      res.json(users);
    })
    .catch(err => {
      next(err);
    });
});

// Using a wrapper function to avoid try-catch repetition
const asyncHandler = fn => (req, res, next) => {
  Promise.resolve(fn(req, res, next)).catch(next);
};

// Usage
app.get('/user/:id', asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  if (!user) {
    return res.status(404).json({ error: 'User not found' });
  }
  res.json(user);
}));

Custom Error Classes

// Custom error class
class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
    this.isOperational = true;

    Error.captureStackTrace(this, this.constructor);
  }
}

// Usage in route handlers
app.get('/protected', (req, res, next) => {
  const token = req.headers.authorization;
  if (!token) {
    return next(new AppError('Access token required', 401));
  }
  // Continue processing...
  res.json({ message: 'Access granted' });
});

// Global error handling middleware
app.use((err, req, res, next) => {
  err.statusCode = err.statusCode || 500;
  err.status = err.status || 'error';

  if (process.env.NODE_ENV === 'development') {
    res.status(err.statusCode).json({
      status: err.status,
      error: err,
      message: err.message,
      stack: err.stack
    });
  } else {
    // Production: send minimal information
    res.status(err.statusCode).json({
      status: err.status,
      message: err.isOperational ? err.message : 'Something went wrong!'
    });
  }
});

Deployment & Production

Environment Variables

// Install dotenv for local development
// npm install dotenv

// Create a .env file in root directory
// DB_HOST=localhost
// DB_USER=root
// DB_PASS=password
// JWT_SECRET=your-secret-key
// NODE_ENV=development

// Load environment variables
if (process.env.NODE_ENV !== 'production') {
  require('dotenv').config();
}

// Access environment variables
const port = process.env.PORT || 3000;
const dbHost = process.env.DB_HOST;
const jwtSecret = process.env.JWT_SECRET;

// Use in application
mongoose.connect(`mongodb://${process.env.DB_HOST}/mydatabase`, {
  useNewUrlParser: true,
  useUnifiedTopology: true
});

app.listen(process.env.PORT || 3000, () => {
  console.log(`Server running on port ${process.env.PORT || 3000}`);
});

Process Managers

# Install PM2 globally
npm install -g pm2

# Start application with PM2
pm2 start app.js

# Start with name
pm2 start app.js --name "my-app"

# Monitor application
pm2 monit

# List all processes
pm2 list

# Stop process
pm2 stop my-app

# Restart process
pm2 restart my-app

# Delete process
pm2 delete my-app

# Startup script generation
pm2 startup

# Save current processes
pm2 save

# Cluster mode (utilize all CPUs)
pm2 start app.js -i max

# Using environment variables
pm2 start app.js --env production