Why Node.js for Web Servers?
Node.js revolutionized backend development with its non-blocking I/O and event-driven architecture. Building HTTP servers with Node.js gives you direct control over request handling, making it perfect for custom APIs, microservices, and learning server fundamentals.
In this guide, you'll create a functional web server using Node.js's built-in http module and ES6 modules.
Understanding the HTTP Module
The http module is Node.js's core tool for creating web servers. It handles:
- Request-response cycles – Processing incoming HTTP requests and sending responses
-
Server creation – The
createServer()method instantiates your server - Stream management – Efficiently handling file transfers without loading entire files into memory
Building Your HTTP Server
Step 1: Import Required Modules
import { createReadStream } from 'node:fs';
import http from 'node:http';
We use ES6 import syntax with the node: protocol prefix for clarity. The createReadStream function enables efficient file streaming.
Step 2: Create the Server with Routing Logic
const server = http.createServer(async (req, res) => {
console.log(req.url);
if (req.url === '/') {
const readStream = createReadStream('./public/index.html');
readStream.pipe(res);
} else {
const readStream = createReadStream(`./public/${req.url}`);
readStream.on('error', (err) => {
res.end('Not Found!');
console.log(err.message);
});
readStream.pipe(res);
}
});
What's happening here:
-
createServer()accepts a callback that receivesreq(request) andres(response) objects - Root route (
/) servesindex.html - Other routes dynamically serve files from the
publicfolder -
pipe()streams file content directly to the response (memory-efficient!) - Error handling catches missing files and returns "Not Found!"
Step 3: Start the Server
server.listen(8080, "0.0.0.0", () => {
console.log(`Server is listening on http://localhost:8080`);
});
The server binds to port 8080 on all network interfaces (0.0.0.0), making it accessible locally and on your network.
Complete Code
import { createReadStream } from 'node:fs';
import http from 'node:http';
const server = http.createServer(async (req, res) => {
console.log(req.url);
if (req.url === '/') {
const readStream = createReadStream('./public/index.html');
readStream.pipe(res);
} else {
const readStream = createReadStream(`./public/${req.url}`);
readStream.on('error', (err) => {
res.end('Not Found!');
console.log(err.message);
});
readStream.pipe(res);
}
});
server.listen(8080, "0.0.0.0", () => {
console.log(`Server is listening on http://localhost:8080`);
});
Why This Matters
Understanding HTTP servers at this level gives you:
- Foundation knowledge for frameworks like Express.js
- Performance insights – streaming vs. buffering files
- Debugging skills – seeing exactly how requests flow through your application
Key Takeaways
✅ The http module provides low-level server control
✅ File streaming with pipe() is memory-efficient
✅ Error handling prevents server crashes from missing files
✅ ES6 modules improve code readability and maintainability
Next Steps
Try enhancing this server:
- Add support for different HTTP methods (POST, PUT, DELETE)
- Implement proper MIME type detection for CSS/JS files
- Add middleware patterns for authentication
What feature would you add first? Share your implementation in the comments below!
📚 Further Reading: Official Node.js HTTP Documentation
Top comments (1)
Great submission