Categories
JavaScript Node.js Server-Side

Introduction to Node.js: JavaScript on the Server

Introduction

JavaScript on the server isn't new. We've had Rhino, SpiderMonkey, and other JavaScript engines for years. But Node.js is different, and it's generating serious excitement.

Released last year by Ryan Dahl, Node.js takes Chrome's V8 JavaScript engine and wraps it with APIs for file I/O, networking, and other server-side tasks. The result is a platform for building scalable network applications using JavaScript.

Why JavaScript on the server? Because JavaScript developers can now write both client and server code. Because Node's event-driven model handles concurrency elegantly. Because it's fast.

Let's explore Node.js and see what the buzz is about.

What is Node.js?

Node.js is:

  • JavaScript runtime built on Chrome's V8 engine
  • Event-driven and non-blocking I/O model
  • Single-threaded but highly concurrent
  • Fast – V8 compiles JavaScript to machine code

Node.js is NOT:

  • A web framework (but can build one)
  • Multi-threaded
  • The solution to every problem
  • Production-ready yet (still early, version 0.2.x)

Think of Node as a platform for JavaScript applications, similar to how Ruby is a platform for Rails.

Why Node.js?

One language everywhere: JavaScript on client and server. Share code, share data structures, switch contexts seamlessly.

Event-driven concurrency: Handle thousands of concurrent connections without threads. No locks, no deadlocks, no threading complexity.

Fast: V8 is incredibly fast. Node performs well even compared to compiled languages.

npm (coming soon): Package manager for Node modules. Easy dependency management.

Active community: Rapid development, many modules, enthusiastic adoption.

Traditional vs Node.js

Traditional (Apache/PHP):

Request comes in → Spawn thread → Block on database → Wait → Respond

Each request gets a thread. Threads are expensive. Blocking I/O wastes CPU.

Node.js:

Request comes in → Register callback → Do something else
Database responds → Run callback → Send response

Single thread handles thousands of requests. Non-blocking I/O keeps CPU busy.

Example – File read:

Blocking (traditional):

var data = readFile('file.txt'); // Wait here
console.log(data);
console.log('Done');

Non-blocking (Node):

readFile('file.txt', function(data) {
    console.log(data);
});
console.log('Done'); // Runs immediately

Node continues executing while waiting for I/O. Callbacks handle results when ready.

Installing Node.js

From source (Linux/Mac):

wget http://nodejs.org/dist/node-v0.2.5.tar.gz
tar xzf node-v0.2.5.tar.gz
cd node-v0.2.5
./configure
make
sudo make install

Test installation:

node --version

You should see the version number.

Hello World

Create hello.js:

console.log('Hello World!');

Run it:

node hello.js

Output: Hello World!

That's it. JavaScript running on the server.

A Simple HTTP Server

Node's real power is networking. Create server.js:

var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
});

server.listen(8000);
console.log('Server running at http://localhost:8000/');

Run it:

node server.js

Visit http://localhost:8000/ and you'll see "Hello World".

That's a complete web server in 8 lines of code.

Compare to Apache+PHP configuration. Node makes servers trivial.

Understanding the Event Loop

Node runs a single-threaded event loop:

// Start server
server.listen(8000);

// Event loop starts
while (true) {
    // Wait for event
    var event = getNextEvent();

    // Execute callback
    event.callback();
}

Everything is asynchronous:

setTimeout(function() {
    console.log('After 1 second');
}, 1000);

console.log('Immediately');

// Output:
// Immediately
// After 1 second

The event loop continues while waiting. No blocking, no wasted CPU.

Reading Files

Asynchronous (preferred):

var fs = require('fs');

fs.readFile('file.txt', 'utf8', function(err, data) {
    if (err) throw err;
    console.log(data);
});

console.log('Reading file...');

Synchronous (avoid in production):

var fs = require('fs');
var data = fs.readFileSync('file.txt', 'utf8');
console.log(data);

Synchronous blocks the event loop. Use only at startup.

Serving Static Files

Real web server needs to serve files:

var http = require('http');
var fs = require('fs');

http.createServer(function(req, res) {
    fs.readFile('index.html', function(err, data) {
        if (err) {
            res.writeHead(404);
            res.end('Not Found');
            return;
        }
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(data);
    });
}).listen(8000);

This reads and serves index.html for every request.

Routing Requests

Handle different URLs:

var http = require('http');
var url = require('url');

http.createServer(function(req, res) {
    var pathname = url.parse(req.url).pathname;

    if (pathname === '/') {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Home Page');
    } else if (pathname === '/about') {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('About Page');
    } else {
        res.writeHead(404);
        res.end('Not Found');
    }
}).listen(8000);

Now different URLs serve different content.

Handling POST Data

Receive form submissions:

var http = require('http');
var querystring = require('querystring');

http.createServer(function(req, res) {
    if (req.method === 'POST') {
        var body = '';

        req.on('data', function(chunk) {
            body += chunk;
        });

        req.on('end', function() {
            var data = querystring.parse(body);
            res.end('Received: ' + data.name);
        });
    } else {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('<form method="post">' +
                '<input name="name">' +
                '<button>Submit</button>' +
                '</form>');
    }
}).listen(8000);

Data arrives in chunks. Collect chunks in the 'data' event, process in 'end' event.

Modules

Node uses CommonJS modules:

math.js:

exports.add = function(a, b) {
    return a + b;
};

exports.multiply = function(a, b) {
    return a * b;
};

app.js:

var math = require('./math');

console.log(math.add(2, 3));        // 5
console.log(math.multiply(2, 3));   // 6

Organize code into reusable modules.

Alternative export style:

module.exports = function() {
    return {
        add: function(a, b) { return a + b; },
        multiply: function(a, b) { return a * b; }
    };
};

Built-in Modules

Node includes many modules:

http – HTTP server/client fs – File system operations path – File path utilities url – URL parsing querystring – Query string parsing events – Event emitter stream – Streaming data crypto – Cryptography util – Utility functions

Example – path module:

var path = require('path');

console.log(path.basename('/foo/bar/file.txt'));  // file.txt
console.log(path.dirname('/foo/bar/file.txt'));   // /foo/bar
console.log(path.extname('/foo/bar/file.txt'));   // .txt

Event Emitters

Many Node objects are EventEmitters:

var events = require('events');
var emitter = new events.EventEmitter();

// Register listener
emitter.on('data', function(data) {
    console.log('Received: ' + data);
});

// Emit event
emitter.emit('data', 'Hello World');

This pattern is fundamental to Node.

HTTP server is an EventEmitter:

var server = http.createServer();

server.on('request', function(req, res) {
    res.end('Hello World');
});

server.listen(8000);

Streams

Streams handle data efficiently:

var fs = require('fs');

// Read stream
var readStream = fs.createReadStream('input.txt');

// Write stream
var writeStream = fs.createWriteStream('output.txt');

// Pipe data
readStream.pipe(writeStream);

Streams process data in chunks without loading everything into memory.

HTTP response is a stream:

http.createServer(function(req, res) {
    var stream = fs.createReadStream('large-file.txt');
    stream.pipe(res);
}).listen(8000);

Serve large files without memory issues.

Error Handling

Always handle errors:

fs.readFile('file.txt', function(err, data) {
    if (err) {
        console.error('Error:', err);
        return;
    }
    console.log(data);
});

Uncaught exceptions crash Node:

process.on('uncaughtException', function(err) {
    console.error('Uncaught exception:', err);
    process.exit(1);
});

Handle errors gracefully to avoid crashes.

Building a Simple App

Let's build a URL shortener:

var http = require('http');
var url = require('url');

var urls = {}; // In-memory storage
var counter = 1;

http.createServer(function(req, res) {
    var pathname = url.parse(req.url).pathname;
    var query = url.parse(req.url, true).query;

    // Home page - show form
    if (pathname === '/') {
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('<h1>URL Shortener</h1>' +
                '<form action="/shorten" method="get">' +
                '<input name="url" placeholder="Enter URL">' +
                '<button>Shorten</button>' +
                '</form>');
    }
    // Shorten URL
    else if (pathname === '/shorten') {
        var longUrl = query.url;
        var id = counter++;
        urls[id] = longUrl;

        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('Short URL: <a href="/' + id + '">/' + id + '</a>');
    }
    // Redirect to long URL
    else {
        var id = pathname.substring(1);
        var longUrl = urls[id];

        if (longUrl) {
            res.writeHead(302, {'Location': longUrl});
            res.end();
        } else {
            res.writeHead(404);
            res.end('Not Found');
        }
    }
}).listen(8000);

console.log('URL Shortener running at http://localhost:8000/');

A functional URL shortener in ~40 lines.

Node vs Other Platforms

Node.js vs PHP:

  • Node is non-blocking, PHP is blocking
  • Node uses JavaScript, PHP uses PHP
  • Node requires process management, PHP works with Apache

Node.js vs Ruby/Python:

  • Similar scripting languages
  • Node is single-threaded event-driven, Ruby/Python typically use threads
  • Node emphasizes asynchronous I/O

Node.js vs Java/C#:

  • Node is simpler for certain tasks
  • Java/C# better for CPU-intensive work
  • Node excels at I/O-bound applications

When to Use Node.js

Good fit:

  • Real-time applications (chat, gaming)
  • API servers
  • Data streaming
  • I/O-heavy applications
  • Microservices
  • Single-page application backends

Poor fit:

  • CPU-intensive calculations
  • Traditional web apps with server-side rendering
  • Environments requiring stability (Node is young)

Node shines for I/O-bound, event-driven applications.

The Node Ecosystem

Coming soon: npm (Node Package Manager)

npm will make installing modules easy:

npm install express
npm install socket.io

Community is building modules rapidly:

  • Express – Web framework
  • Socket.IO – WebSocket library
  • Connect – Middleware framework
  • Jade – Template engine
  • Mongoose – MongoDB ODM

The ecosystem is growing fast.

Learning Resources

Node.js website: http://nodejs.org/

Node.js Manual: http://nodejs.org/api.html

HowToNode: http://howtonode.org/ – Tutorials and articles

Node.js Google Group: Active community for questions

GitHub: http://github.com/joyent/node – Source code

Common Pitfalls

Callback hell: Nested callbacks get messy:

fs.readFile('file1', function(err, data1) {
    fs.readFile('file2', function(err, data2) {
        fs.readFile('file3', function(err, data3) {
            // Getting deep...
        });
    });
});

Use named functions or libraries to manage this.

Blocking the event loop: Don't do CPU-intensive work in the main thread. Use child processes or worker queues.

Not handling errors: Always handle callback errors. Uncaught exceptions crash Node.

Production Considerations

Node.js is young (version 0.2.x). For production:

Process management: Use tools to restart Node if it crashes

Reverse proxy: Put nginx in front of Node

Error handling: Log everything, handle all errors

Testing: Test thoroughly, Node changes fast

Clustering: Run multiple Node processes

Many companies are using Node in production (Yahoo, LinkedIn), but be aware of the risks.

The Future of Node

Node is evolving rapidly. Upcoming features:

  • npm package manager
  • Better Windows support
  • Improved stability
  • Growing ecosystem

The community is vibrant. New modules appear daily. Conference talks generate excitement. Node is gaining momentum.

Wrapping Up

Node.js represents a new approach to server-side development. Event-driven, non-blocking I/O handles concurrency elegantly. JavaScript everywhere reduces context switching. The platform is fast and efficient.

It's early days. Node isn't production-ready for everything. The API changes. Documentation is sparse. But the potential is clear.

If you're building real-time applications, API servers, or I/O-heavy services, Node deserves serious consideration. The event-driven model fits these use cases perfectly.

Start experimenting. Build a simple server. Try handling WebSockets. Explore the ecosystem. Node's approach to concurrency is different from threads, and understanding it takes practice.

JavaScript on the server isn't just possible – with Node.js, it's powerful. The future of server-side JavaScript looks bright.

Give Node.js a try. You might find it changes how you think about building network applications.

By Shishir Sharma

Shishir Sharma is a Software Engineering Leader, husband, and father based in Ottawa, Canada. A hacker and biker at heart, and has built a career as a visionary mentor and relentless problem solver.

With a leadership pedigree that includes LinkedIn, Shopify, and Zoom, Shishir excels at scaling high-impact teams and systems. He possesses a native-level mastery of JavaScript, Ruby, Python, PHP, and C/C++, moving seamlessly between modern web stacks and low-level architecture.

A dedicated member of the tech community, he serves as a moderator at LUG-Jaipur. When he’s not leading engineering teams or exploring new technologies, you’ll find him on the open road on his bike, catching an action movie, or immersed in high-stakes FPS games.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.