🚀 How to Host Website Using Node.js
Note: This post was originally published in 2014. While the core concepts remain valid, some examples may use older Node.js syntax. Modern Node.js development often uses frameworks like Express.js and deployment platforms like Vercel, Netlify, or cloud providers.
Node.js has revolutionized web development by allowing developers to use JavaScript on both the client and server side. In this guide, I'll show you how to create a simple web server using Node.js and host your website.
Prerequisites
- Node.js installed on your system
- Basic knowledge of JavaScript
- A text editor (VS Code, Sublime Text, etc.)
Step 1: Create Your Project Structure
First, create a new directory for your project and initialize it:
mkdir my-website cd my-website npm init -y
Step 2: Create the Basic Server
Create a file named server.js
with the following content:
const http = require('http'); const fs = require('fs'); const path = require('path'); const PORT = process.env.PORT || 3000; const server = http.createServer((req, res) => { let filePath = '.' + req.url; if (filePath === './') { filePath = './index.html'; } const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; } fs.readFile(filePath, (error, content) => { if (error) { if (error.code === 'ENOENT') { res.writeHead(404); res.end('File not found'); } else { res.writeHead(500); res.end('Server error: ' + error.code); } } else { res.writeHead(200, { 'Content-Type': contentType }); res.end(content, 'utf-8'); } }); }); server.listen(PORT, () => { console.log(`Server running at http://localhost:${PORT}/`); });
Step 3: Create Your HTML File
Create an index.html
file in your project directory:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Node.js Website</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; line-height: 1.6; } .header { background-color: #f4f4f4; padding: 20px; border-radius: 5px; margin-bottom: 20px; } .content { background-color: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); } </style> </head> <body> <div class="header"> <h1>Welcome to My Node.js Website</h1> <p>This website is hosted using Node.js!</p> </div> <div class="content"> <h2>About This Site</h2> <p>This is a simple website created and hosted using Node.js. The server handles:</p> <ul> <li>Static file serving</li> <li>Content-Type detection</li> <li>Error handling</li> <li>Basic routing</li> </ul> <h2>Features</h2> <ul> <li>Lightweight and fast</li> <li>Easy to customize</li> <li>Cross-platform compatibility</li> <li>No external dependencies</li> </ul> </div> </body> </html>
Step 4: Run Your Server
Start your server by running:
node server.js
Your website will be available at http://localhost:3000
Step 5: Adding More Features
Let's enhance the server with some additional features:
Enhanced Server with Logging
const http = require('http'); const fs = require('fs'); const path = require('path'); const PORT = process.env.PORT || 3000; // Simple logging middleware function logRequest(req, res, next) { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${req.method} ${req.url}`); next(); } const server = http.createServer((req, res) => { // Log the request logRequest(req, res, () => {}); let filePath = '.' + req.url; if (filePath === './') { filePath = './index.html'; } const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; case '.ico': contentType = 'image/x-icon'; break; } fs.readFile(filePath, (error, content) => { if (error) { if (error.code === 'ENOENT') { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('<h1>404 - Page Not Found</h1><p>The requested page could not be found.</p>'); } else { res.writeHead(500, { 'Content-Type': 'text/html' }); res.end('<h1>500 - Internal Server Error</h1><p>Something went wrong on the server.</p>'); } } else { res.writeHead(200, { 'Content-Type': contentType }); res.end(content, 'utf-8'); } }); }); server.listen(PORT, () => { console.log(`🚀 Server running at http://localhost:${PORT}/`); console.log(`📁 Serving files from: ${__dirname}`); });
Step 6: Adding API Endpoints
You can also add simple API endpoints to your server:
const http = require('http'); const fs = require('fs'); const path = require('path'); const PORT = process.env.PORT || 3000; const server = http.createServer((req, res) => { const url = req.url; const method = req.method; // API endpoints if (url === '/api/status' && method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ status: 'OK', timestamp: new Date().toISOString(), uptime: process.uptime() })); return; } if (url === '/api/hello' && method === 'GET') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Hello from Node.js!', timestamp: new Date().toISOString() })); return; } // Handle POST requests if (url === '/api/echo' && method === 'POST') { let body = ''; req.on('data', chunk => { body += chunk.toString(); }); req.on('end', () => { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ message: 'Echo response', data: body, timestamp: new Date().toISOString() })); }); return; } // Serve static files (existing code...) let filePath = '.' + url; if (filePath === './') { filePath = './index.html'; } const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; } fs.readFile(filePath, (error, content) => { if (error) { if (error.code === 'ENOENT') { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('<h1>404 - Page Not Found</h1>'); } else { res.writeHead(500, { 'Content-Type': 'text/html' }); res.end('<h1>500 - Internal Server Error</h1>'); } } else { res.writeHead(200, { 'Content-Type': contentType }); res.end(content, 'utf-8'); } }); }); server.listen(PORT, () => { console.log(`🚀 Server running at http://localhost:${PORT}/`); console.log(`📡 API endpoints available:`); console.log(` GET /api/status - Server status`); console.log(` GET /api/hello - Hello message`); console.log(` POST /api/echo - Echo POST data`); });
Step 7: Production Deployment
For production deployment, consider these options:
Using PM2 (Process Manager)
# Install PM2 globally npm install -g pm2 # Start your application pm2 start server.js --name "my-website" # Monitor your application pm2 monit # View logs pm2 logs # Restart application pm2 restart my-website # Stop application pm2 stop my-website
Using Environment Variables
// Create a .env file PORT=3000 NODE_ENV=production // Install dotenv npm install dotenv // Update server.js require('dotenv').config(); const PORT = process.env.PORT || 3000; const NODE_ENV = process.env.NODE_ENV || 'development'; console.log(`Environment: ${NODE_ENV}`); console.log(`Port: ${PORT}`);
Step 8: Package.json Configuration
Update your package.json
with scripts:
{ "name": "my-website", "version": "1.0.0", "description": "A simple Node.js website", "main": "server.js", "scripts": { "start": "node server.js", "dev": "nodemon server.js", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": ["nodejs", "website", "server"], "author": "Your Name", "license": "MIT", "dependencies": { "dotenv": "^16.0.0" }, "devDependencies": { "nodemon": "^2.0.15" } }
Best Practices
- Use environment variables for configuration
- Implement proper error handling for production
- Add logging for debugging and monitoring
- Use a process manager like PM2 for production
- Implement security headers and input validation
- Use HTTPS in production
Common Issues and Solutions
- Port already in use: Change the PORT environment variable
- File not found errors: Check file paths and permissions
- Memory leaks: Use proper cleanup in event listeners
- Performance issues: Implement caching and compression
Key Takeaways
- Node.js provides a simple way to create web servers
- Static file serving is straightforward with the built-in modules
- You can easily add API endpoints to your server
- Use process managers like PM2 for production deployment
- Environment variables help with configuration management