In this blog post, I will show you how to set up a simple Node.js web server which you can use for your local development environment to serve up some static files. This simple web server can be used if you are making your own static site generator to generate HTML files from other files like markdown files. For example, your write your own blogs using markdown and convert them into HTML files, you can serve up these files on a local development environment or even an actual VPS using a simple Node.js web server.
You can find different npm packages like http-server which offer zero configuration HTTP servers but if you want to learn to set up one yourself then this article will help you.
The first step is installing Node.js. Head over to the Node.js download page and follow the download instructions for your Operating System.
Make sure you include the path to the Node.js application in your System Environment Variables, especially in Windows OS, so that you can run the node command from anywhere in a terminal. To do that in Windows if you hadn't checked the option to add path to variables during installation, you can follow this guide.
You can create a folder for this project and inside that folder, create a file named server.js
.
You can create a folder named public
at the root of your project and inside it, you can add the index.html
file. I have a quick html template below you can use when following this tutorial:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Sample html file</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="w-full h-screen flex flex-col justify-center items-center">
<p class="text-2xl font-medium">Hello there!</p>
</div>
</body>
</html>
Your sample project structure will look something like this:
├── public
| ├── pages
| ├── posts
| └── index.html
└── server.js
Inside the server.js
file, you can add the following content to serve up a single file:
// Load the necessary modules that come with Node
var http = require("http");
const fs = require("fs").promises;
// Assigning host and port number
const host = "localhost";
const port = 5000;
// Variable for the home/main website page
let indexFile;
// Handling the expected requests and their corresponding files
const requestListener = function (req, res) {
if (req.url == "/") {
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(indexFile);
}
};
// Assigning the request listener to createServer
const server = http.createServer(requestListener);
// Start the server and listen on the specified host & port
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
// Here we assign the index.html to indexFile. The file contents are read once at the time of running this server script instead of everytime the request is made
fs.readFile(__dirname + "/public/index.html")
.then((contents) => {
indexFile = contents;
})
.catch((err) => {
console.error(`Could not read the file: ${err}`);
process.exit(1);
});
The file above will be modified slightly to read multiple html files in a folder (we will assume we have html files in the ./public/pages
& ./public/posts
folders):
var http = require("http");
const fs = require("fs").promises;
// Adding the path module from Node
const path = require("path");
const host = "localhost";
const port = 5000;
let indexFile;
// New variables for posts & pages
let posts = [];
let pages = [];
const requestListener = function (req, res) {
if (req.url == "/") {
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(indexFile);
}
// Loop through all existing html content found in the ./public/pages folder and serve them if url matches file name
pages.forEach((page) => {
if (req.url == `/${page.name}`) {
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(page.page);
}
});
// Loop through all existing html content found in the ./public/posts folder and serve them if url matches file name
posts.forEach((post) => {
if (req.url == `/posts/${post.name}`) {
res.setHeader("Content-Type", "text/html");
res.writeHead(200);
res.end(post.page);
}
});
};
const server = http.createServer(requestListener);
server.listen(port, host, () => {
console.log(`Server is running on http://${host}:${port}`);
});
fs.readFile(__dirname + "/public/index.html")
.then((contents) => {
indexFile = contents;
})
.catch((err) => {
console.error(`Could not read the file: ${err}`);
process.exit(1);
});
// Read the contents of the files once when the server script is run instead of reading them for every request
// Assign contents of files found to the pages variable
fs.readdir("public/pages")
.then((files) => {
for (let file of files) {
if (path.parse(file).ext == ".html") {
fs.readFile(__dirname + `/public/pages/${path.parse(file).name}.html`)
.then((contents) => {
pages.push({ name: path.parse(file).name, page: contents });
})
.catch((err) => {
console.error(`Could not read the file: ${err}`);
process.exit(1);
});
}
}
})
.catch((err) => {
console.error(`Could not read from the posts directory: ${err}`);
process.exit(1);
});
// Assign contents of files found to the posts variable
fs.readdir("public/posts")
.then((files) => {
for (let file of files) {
if (path.parse(file).ext == ".html") {
fs.readFile(__dirname + `/public/posts/${path.parse(file).name}.html`)
.then((contents) => {
posts.push({ name: path.parse(file).name, page: contents });
})
.catch((err) => {
console.error(`Could not read the file: ${err}`);
process.exit(1);
});
}
}
})
.catch((err) => {
console.error(`Could not read from the posts directory: ${err}`);
process.exit(1);
});
The last thing left is to run the server. You can do that by running node server.js
or node server
in a terminal after you have changed directory to where the server.js
file exists .i.e: at the root of the project. The web server should be running on the port specified at the port
variable. You can stop the server on the terminal by simply pressing the following keyboard combination ctrl + c
.
You have seen that coming up with your own web server with Node.js is simple. Probably the next step will be to learn how to pair Node.js with Express.js, a Node.js web app framework that can be used to build RESTful APIs. This would help to make your website/web app dynamic. I hope to write an article on this in the near future, so stay tuned. I also hope this article has helped you to make a simple web server which you can use locally.