Comprehensive Backend Development Guide with Node.js, Express, and Databases

Introduction to Node.js Runtime

Node.js serves as a JavaScript runtime environment that exposes fundamental APIs for building backend systems. Mastering this technology enables developers to expand their skillset beyond the frontend.

Key capabilities include:

  • Constructing web applications using frameworks like Express.
  • Developing cross-platform desktop utilities via Electron.
  • Building RESTful API services efficiently.
  • Managing databases and creating command-line tools.

Version Selection

Two primary release types are available:

  1. LTS (Long Term Support): Recommended for production environments requiring stability.
  2. Current: Contains bleeding-edge features but may introduce bugs; unsuitable for critical enterprise systems.

To execute scripts, use the following command structure:

node path/to/script.js

Core Built-in Modules

File System Operations (fs)

The fs module provides essential methods for interacting with the file system.

Common usage includes importing the module and handling asynchronous callbacks or Promises:

const fs = require('fs').promises;

async function processFile() {
  try {
    const filePath = '/path/to/data.txt';
    // Reading content with Promise-based API
    const content = await fs.readFile(filePath, 'utf8');
    console.log(`File Content: ${content}`);
    
    // Writing new data
    await fs.writeFile(filePath, 'Updated Content', 'utf8');
    console.log('Write operation completed.');
  } catch (error) {
    console.error('Operation failed:', error.message);
  }
}

processFile();

Note on paths: Avoid relative paths starting with ./ or ../ in production scripts to prevent execution context errors. Prefer absolute paths derived from __dirname.

Path Handling (path)

To ensure cross-platform compatibility when constructing file paths, utilize the path module.

const path = require('path');

// Joining segments safely
const fullPath = path.join('/root', 'folder', 'file.txt');

// Extracting name without extension
const fileName = path.basename(fullPath, '.txt');
console.log(fileName); 

// Getting extension
const ext = path.extname(fullPath);
console.log(ext);

Always prefer path.join() over string concatenation (+) for reliability across operating systems.

HTTP Server Creation

The native http module allows server creation without external dependencies.

const http = require('http');

const server = http.createServer((request, response) => {
  response.setHeader('Content-Type', 'text/html; charset=utf-8');
  const url = request.url;
  const method = request.method;
  
  response.end(`Method: ${method} | URL: ${url}`);
});

server.listen(3000, () => {
  console.log('Server listening on port 3000');
});

Module Architecture

System Overview

Modules are categorized into three types:

  1. Built-in: Provided by the Node.js core (e.g., fs, http).
  2. Custom: User-defined .js files within the project.
  3. Third-party: External libraries installed via NPM.

Exporting and Importing

JavaScript modules in Node.js follow the CommonJS specification.

Defining Exports:

// utils.js
const greet = (name) => `Hello, ${name}`;

module.exports = { greet };

Loading Modules:

const utils = require('./utils');
console.log(utils.greet('User'));

Variables defined inside a module are scoped locally to prevent global pollution. Only properties attached to module.exports are accessible externally.

Package Management with NPM

NPM (Node Package Manager) handles dependency installation and configuration.

Project Initialization

Run the following to scaffold a new project:

npm init -y

This generates a package.json file containing metadata and script definitions.

Dependency Classification

  • dependencies: Packages required for runtime operations.
  • devDependencies: Tools needed only during development (e.g., linters, test runners).

Installation commands:

# Production dependency
npm install lodash

# Development tool
npm install --save-dev eslint

To avoid committing large vendor folders, add node_modules to .gitignore. Re-install all packages using npm install upon cloning a repository.

The Express Framework

Express is a minimalist web framework facilitating rapid application development.

Setup and Routing

const express = require('express');
const app = express();
const port = 4000;

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Root route
app.get('/', (req, res) => {
  res.send('Welcome to the API server');
});

// Parameterized route
app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.json({ id: userId });
});

app.listen(port, () => console.log(`App running on port ${port}`));

Middleware Stack

Middleware functions sit between request entry and response exit.

// Custom logging middleware
const logger = (req, res, next) => {
  console.log(`${new Date().toISOString()} - ${req.path}`);
  next();
};

app.use(logger);

// Error handling middleware
app.use((err, req, res, next) => {
  res.status(500).send('Internal Server Error');
});

Routes must be registered before error-handling middleware to ensure exceptions bubble correctly.

Static Asset Hosting

Use express.static to serve public files.

app.use('/public', express.static('assets'));

API Interface Design

Standard REST principles are commonly applied.

Request Methods

  • GET: Retrieve resources.
  • POST: Create new records.
  • DELETE: Remove existing entries.

Example router implementation:

// api/userRouter.js
const express = require('express');
const router = express.Router();

router.get('/list', (req, res) => {
  res.json({ status: 200, data: [] });
});

router.post('/create', (req, res) => {
  const bodyData = req.body;
  res.json({ status: 201, message: 'Created' });
});

module.exports = router;

Cross-Origin Resource Sharing (CORS)

When frontend and backend run on different domains, CORS policies block requests. Enable support via the cors package.

const cors = require('cors');
app.use(cors());

Configure specific origins if strict security is required.

Database Integration

MySQL connectivity is managed through connection pools.

const mysql = require('mysql');

const pool = mysql.createPool({
  host: 'localhost',
  user: 'db_user',
  password: 'secure_password',
  database: 'production_db'
});

pool.query('SELECT * FROM users WHERE id = ?', [1], (err, results) => {
  if (err) return console.error(err);
  console.log(results);
});

// Cleanup function
pool.end();

Parameterized queries protect against SQL injection. Always validate inputs before executing statements.

Authentication Strategies

Modern architectures typically choose between two models:

  1. Session-Based: Uses server-side storage linked to client cookies. Effective for traditional server-rendered pages.
  2. Token-Based (JWT): Stateless tokens sent in headers. Preferred for decoupled frontands/mobile apps.

Decision factors:

  • SEO: Server-side rendering aids search crawling.
  • Scalability: Token statelessness simplifies horizontal scaling.
  • Security: Consider cross-domain implications. Tokens handle mixed-origin better than Sessions without complex cookie configurations.

Development mode choice impacts the authentication mechanism selected for the project.

Posted on Sat, 09 May 2026 00:15:36 +0000 by themire