Node.js allows you to run JavaScript on the server. It's the foundation of modern full-stack JavaScript development, powering everything from simple APIs to Netflix's streaming platform.
What is Node.js?
Node.js is a JavaScript runtime built on Chrome's V8 engine. It enables JavaScript to run outside the browser, making it possible to build servers, command-line tools, and more.
Why Node.js?
- JavaScript everywhere: Use one language for frontend and backend
- Non-blocking I/O: Handle thousands of concurrent connections efficiently
- npm ecosystem: Access millions of open-source packages
- Fast development: Quick to prototype and iterate
- Great for real-time: WebSockets, chat apps, live updates
Getting Started
Installation
Download Node.js from nodejs.org or use a version manager:
# Check installation
node --version # Should show v18.x or higher
npm --version # Node Package Manager
# Run JavaScript files
node app.js
# Start interactive REPL
node Your First Node.js Script
// hello.js
console.log('Hello from Node.js!');
// Access command line arguments
console.log('Arguments:', process.argv);
// Environment variables
console.log('Node version:', process.version);
console.log('Current directory:', process.cwd()); npm Basics
# Initialize a new project
npm init -y
# Install dependencies
npm install express # Production dependency
npm install nodemon -D # Development dependency
# Run scripts defined in package.json
npm run dev
npm start Core Concepts
Modules
// math.js - Export functions
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// app.js - Import and use
import { add, multiply } from './math.js';
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20 Built-in Modules
| Module | Purpose |
|---|---|
fs | File system operations |
path | File path utilities |
http | HTTP server and client |
crypto | Cryptographic functions |
os | Operating system info |
Creating a Basic HTTP Server
import http from 'http';
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello, World!');
});
server.listen(3000, () => {
console.log('Server running at http://localhost:3000');
}); Building APIs with Express
Express is the most popular Node.js web framework. It simplifies building APIs and web applications.
Basic Express Setup
import express from 'express';
const app = express();
// Middleware to parse JSON
app.use(express.json());
// Routes
app.get('/', (req, res) => {
res.json({ message: 'Welcome to the API' });
});
app.get('/users', (req, res) => {
res.json([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]);
});
app.post('/users', (req, res) => {
const { name, email } = req.body;
// Save to database...
res.status(201).json({ id: 3, name, email });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
}); Route Parameters & Query Strings
// Route parameters - /users/123
app.get('/users/:id', (req, res) => {
const userId = req.params.id;
res.json({ id: userId, name: 'User ' + userId });
});
// Query strings - /search?q=node&limit=10
app.get('/search', (req, res) => {
const { q, limit = 10 } = req.query;
res.json({ query: q, limit: parseInt(limit) });
}); Middleware
// Logging middleware
const logger = (req, res, next) => {
console.log(`${req.method} ${req.path}`);
next(); // Continue to next middleware
};
app.use(logger);
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something went wrong!' });
}); Working with Files
import fs from 'fs/promises';
import path from 'path';
// Read file
const content = await fs.readFile('data.txt', 'utf-8');
console.log(content);
// Write file
await fs.writeFile('output.txt', 'Hello, World!');
// Append to file
await fs.appendFile('log.txt', 'New log entry\n');
// Check if file exists
try {
await fs.access('config.json');
console.log('File exists');
} catch {
console.log('File does not exist');
}
// Read directory
const files = await fs.readdir('./src');
console.log(files);
// Create directory
await fs.mkdir('uploads', { recursive: true }); Database Integration
MongoDB with Mongoose
import mongoose from 'mongoose';
// Connect to MongoDB
await mongoose.connect('mongodb://localhost:27017/myapp');
// Define a schema
const userSchema = new mongoose.Schema({
name: { type: String, required: true },
email: { type: String, unique: true },
createdAt: { type: Date, default: Date.now }
});
const User = mongoose.model('User', userSchema);
// CRUD operations
const user = await User.create({ name: 'Alice', email: 'alice@example.com' });
const users = await User.find();
const found = await User.findById(user._id);
await User.findByIdAndUpdate(user._id, { name: 'Alicia' });
await User.findByIdAndDelete(user._id); PostgreSQL with Prisma
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Create user
const user = await prisma.user.create({
data: { name: 'Alice', email: 'alice@example.com' }
});
// Find users
const users = await prisma.user.findMany({
where: { name: { contains: 'Ali' } }
});
// Update user
await prisma.user.update({
where: { id: 1 },
data: { name: 'Alicia' }
}); Async Patterns
Promises and Async/Await
// Async function
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Fetch failed:', error);
throw error;
}
}
// Parallel execution
async function fetchMultiple() {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);
return { users, posts };
}
// Error handling with Promise.allSettled
const results = await Promise.allSettled([
fetch('/api/fast'),
fetch('/api/slow'),
fetch('/api/might-fail')
]);
// results contain status: 'fulfilled' or 'rejected' Best Practices
Environment Variables
// Use dotenv for local development
import 'dotenv/config';
const port = process.env.PORT || 3000;
const dbUrl = process.env.DATABASE_URL;
// Never commit secrets to git!
// .env file (add to .gitignore)
// PORT=3000
// DATABASE_URL=mongodb://localhost:27017/myapp
// JWT_SECRET=your-secret-key Project Structure
my-api/
├── src/
│ ├── routes/ # Route handlers
│ ├── controllers/ # Business logic
│ ├── models/ # Database models
│ ├── middleware/ # Custom middleware
│ ├── utils/ # Helper functions
│ └── index.js # Entry point
├── tests/ # Test files
├── .env # Environment variables
├── .gitignore
└── package.json Security Tips
- Validate input: Never trust user input, use validation libraries
- Use HTTPS: Encrypt data in transit
- Hash passwords: Use bcrypt, never store plain text
- Rate limiting: Prevent abuse and DDoS attacks
- Helmet: Set security headers automatically