Node.js & Express

Introduction to Node.js

20 min Lesson 1 of 40

Introduction to Node.js

Node.js has revolutionized the way we build server-side applications by bringing JavaScript to the backend. In this lesson, we'll explore what Node.js is, how it works, and why it has become one of the most popular platforms for building modern web applications.

What is Node.js?

Node.js is an open-source, cross-platform JavaScript runtime environment that executes JavaScript code outside of a web browser. Created by Ryan Dahl in 2009, Node.js allows developers to use JavaScript for server-side scripting, enabling the development of scalable network applications.

Important: Node.js is not a programming language, framework, or library. It is a runtime environment that executes JavaScript code on the server using the V8 JavaScript engine.

Key characteristics of Node.js:

  • JavaScript Everywhere: Use the same language (JavaScript) for both frontend and backend development
  • Non-blocking I/O: Handles multiple operations simultaneously without waiting for one to complete
  • Event-Driven Architecture: Uses events and callbacks to handle asynchronous operations
  • Single-Threaded: Uses a single thread with an event loop to handle concurrent operations
  • Fast Execution: Built on Chrome's V8 JavaScript engine for high performance

The V8 JavaScript Engine

At the core of Node.js is the V8 JavaScript engine, developed by Google for the Chrome browser. V8 compiles JavaScript directly to native machine code before executing it, resulting in extremely fast performance.

// V8 compiles this JavaScript code to machine code function calculateSum(a, b) { return a + b; } // V8 optimizes frequently-called functions for (let i = 0; i < 1000000; i++) { calculateSum(i, i + 1); }

What makes V8 special:

  • Just-In-Time (JIT) Compilation: Compiles JavaScript to machine code at runtime
  • Inline Caching: Optimizes property access by remembering object structures
  • Hidden Classes: Creates internal representations of objects for faster property access
  • Garbage Collection: Automatically manages memory allocation and deallocation

Event-Driven Architecture

Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Instead of waiting for operations to complete (like reading a file or querying a database), Node.js continues executing other code and responds to events when operations finish.

// Traditional blocking approach (NOT Node.js) const data = readFileSync('large-file.txt'); // Waits here console.log(data); console.log('This runs after file is read'); // Node.js non-blocking approach readFile('large-file.txt', (err, data) => { if (err) throw err; console.log(data); }); console.log('This runs immediately, before file is read');
Performance Tip: Non-blocking I/O allows Node.js to handle thousands of concurrent connections with minimal overhead, making it ideal for I/O-intensive applications.

The Event Loop

The event loop is the heart of Node.js's asynchronous nature. It continuously checks for and processes events, allowing Node.js to perform non-blocking I/O operations despite JavaScript being single-threaded.

console.log('1. Start'); setTimeout(() => { console.log('3. Timeout callback'); }, 0); Promise.resolve().then(() => { console.log('2. Promise callback'); }); console.log('1. End'); // Output order: // 1. Start // 1. End // 2. Promise callback // 3. Timeout callback

The event loop processes tasks in this order:

  1. Timers: Executes callbacks scheduled by setTimeout() and setInterval()
  2. Pending Callbacks: Executes I/O callbacks deferred to the next loop iteration
  3. Idle, Prepare: Internal operations only
  4. Poll: Retrieves new I/O events; executes I/O related callbacks
  5. Check: Executes setImmediate() callbacks
  6. Close Callbacks: Executes close event callbacks (e.g., socket.on('close'))

Non-Blocking I/O Model

Node.js uses libuv, a multi-platform support library, to provide asynchronous I/O operations. This allows Node.js to handle file system operations, network requests, and other I/O tasks without blocking the main thread.

const fs = require('fs'); // Non-blocking file read fs.readFile('data.txt', 'utf8', (err, data) => { if (err) { console.error('Error reading file:', err); return; } console.log('File content:', data); }); // This code runs immediately, not waiting for file read console.log('Reading file in background...'); // Example output: // Reading file in background... // File content: [file contents here]
Common Mistake: Don't confuse asynchronous code with parallel execution. Node.js is single-threaded, but it can handle multiple operations concurrently through its event loop.

Node.js Use Cases

Node.js excels in certain types of applications:

1. Real-Time Applications

Perfect for applications requiring real-time, bidirectional communication:

  • Chat applications (Slack, Discord)
  • Collaborative tools (Google Docs, Figma)
  • Live notifications and updates
  • Online gaming platforms

2. RESTful APIs

const express = require('express'); const app = express(); // Simple REST API endpoint app.get('/api/users/:id', (req, res) => { const userId = req.params.id; // Fetch user from database (non-blocking) getUserById(userId, (err, user) => { if (err) return res.status(500).json({ error: err }); res.json(user); }); }); app.listen(3000, () => { console.log('API server running on port 3000'); });

3. Microservices Architecture

Node.js's lightweight nature makes it ideal for microservices:

  • Small, independent services
  • Fast startup times
  • Easy horizontal scaling
  • Container-friendly (Docker, Kubernetes)

4. Streaming Applications

const fs = require('fs'); const http = require('http'); // Stream a large video file http.createServer((req, res) => { const stream = fs.createReadStream('large-video.mp4'); stream.pipe(res); // Streams data chunk by chunk }).listen(3000);

5. Command-Line Tools

Many popular CLI tools are built with Node.js:

  • npm (Node Package Manager)
  • webpack (Module bundler)
  • ESLint (Code linter)
  • Gulp (Task runner)

When NOT to Use Node.js

Not Ideal For:
  • CPU-Intensive Tasks: Heavy computations (video encoding, complex algorithms) block the event loop
  • Simple CRUD Applications: Traditional frameworks might be more straightforward
  • Applications Requiring Multi-Threading: Node.js is single-threaded by design

However, for CPU-intensive tasks, Node.js offers solutions:

// Worker Threads for CPU-intensive tasks const { Worker } = require('worker_threads'); function runHeavyComputation(data) { return new Promise((resolve, reject) => { const worker = new Worker('./heavy-computation.js', { workerData: data }); worker.on('message', resolve); worker.on('error', reject); }); } // Now heavy computation runs in separate thread runHeavyComputation({ numbers: [1, 2, 3, 4, 5] }) .then(result => console.log('Result:', result));

Node.js Ecosystem

Node.js has the largest ecosystem of open-source libraries through npm (Node Package Manager):

  • Over 2 million packages available on npm registry
  • Express.js: Most popular web framework
  • Socket.io: Real-time bidirectional communication
  • Mongoose: MongoDB object modeling
  • Passport: Authentication middleware
  • Jest: Testing framework
Best Practice: Always check package popularity, maintenance status, and security before installing third-party dependencies.

Node.js vs Traditional Server Technologies

Feature Node.js Traditional (PHP, Java)
Language JavaScript PHP, Java, Python, etc.
I/O Model Non-blocking, event-driven Blocking, thread-based
Concurrency Single-threaded with event loop Multi-threaded
Best For I/O-intensive, real-time apps CPU-intensive, traditional apps

Real-World Node.js Success Stories

Major Companies Using Node.js:
  • Netflix: Reduced startup time by 70% after migrating to Node.js
  • PayPal: Built 2x faster with fewer developers compared to Java
  • LinkedIn: Moved from Ruby on Rails to Node.js, reducing servers from 30 to 3
  • Uber: Handles millions of requests per second with Node.js
  • NASA: Uses Node.js for data access and keeping astronauts safe

Practice Exercise:

Think about a web application you'd like to build. Based on what you've learned, answer these questions:

  1. Is Node.js a good fit for your application? Why or why not?
  2. What features of Node.js would benefit your application the most?
  3. Are there any aspects of your application that might be challenging with Node.js?
  4. What alternatives to Node.js might you consider, and why?

Summary

In this lesson, you've learned:

  • Node.js is a JavaScript runtime built on Chrome's V8 engine
  • It uses an event-driven, non-blocking I/O model for efficiency
  • The event loop enables asynchronous operations in a single thread
  • Node.js excels at I/O-intensive and real-time applications
  • It's not ideal for CPU-intensive tasks without worker threads
  • Major companies successfully use Node.js in production at scale

In the next lesson, we'll set up your Node.js development environment and start writing your first Node.js application!