Node.js Web Server from Scratch

Build a Node.js Web Server from Scratch with TypeScript

If you’re looking to build a Node.js web server with TypeScript, you’ve come to the right place! In this step-by-step guide, we’ll walk through setting up a simple HTTP server using Node.js and TypeScript, configuring the project, and handling HTTP requests effectively. Let’s get started!


Setting Up Your Node.js and TypeScript Project

Before we write any code, we need to set up our project. Open VSCode and create an empty folder. Then, initialize a Node.js project by running:

npm init -y

This command generates a package.json file, which will store project metadata and dependencies.

Installing Dependencies

Next, install the necessary dependencies:

npm install typescript @types/node tsconfig-paths tsc-watch --save-dev

These packages will allow us to work with TypeScript and Node.js efficiently.

Configuring TypeScript

Now, create a tsconfig.json file in the project root. This file sets up TypeScript configurations. For our server, we’ll extend Node.js 20 settings and specify our project structure:

{
  "extends": "@tsconfig/node20/tsconfig.json",
  "compilerOptions": {
    "rootDir": "src",
    "outDir": "dist"
  }
}

This setup ensures that TypeScript compiles source files from src to dist.

🚀Boost your career with Full Stack Software Developer Certificate


Creating the Node.js HTTP Server

Now, let’s build a Node.js web server with TypeScript!

Writing the Server File

Create a server.ts file inside the src folder and add the following code:

import { createServer } from "http";
import { handler } from "./handler";

const port = 3000;
const server = createServer(handler);

server.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

This code:

  • Imports the createServer function from Node.js’s built-in http module.
  • Imports a handler function (we’ll define it next) to process incoming requests.
  • Creates an HTTP server and listens on port 3000.

Defining the Request Handler

Now, create a handler.ts file in the src folder. This file defines how our server handles incoming requests.

import { IncomingMessage, ServerResponse } from "http";

export const handler = async (req: IncomingMessage, res: ServerResponse) => {
  console.log(`Received request: ${req.method} ${req.url}`);

  const parsedURL = new URL(req.url ?? "", `http://${req.headers.host}`);
  const keyword = parsedURL.searchParams.get("keyword");

  if (req.method !== "GET" || parsedURL.pathname === "/favicon.ico") {
    res.writeHead(404, "Not Found");
    res.end();
    return;
  }

  res.writeHead(200, { "Content-Type": "text/plain" });
  res.write(keyword ? `Hello, ${keyword}` : "Hello, HTTP");
  res.end();
};

This function:

  • Logs the request method and URL.
  • Extracts query parameters from the URL.
  • Responds with “Hello, HTTP” or “Hello, [keyword]” if a query parameter exists.
  • Returns a 404 error for non-GET requests or favicon requests.

Running and Testing the Server

Adding a Dev Script

Modify package.json to include a dev script for automatic reloading:

"scripts": {
  "dev": "tsc-watch --onSuccess \"node dist/server.js\""
}

This command compiles TypeScript files and runs server.js whenever changes are made.

Starting the Server

Run the server with:

npm run dev

You should see the message: Server listening on port 3000.

Sending a Request

To test our server, create an api-test.http file and add the following request:

GET http://localhost:3000/hello?keyword=World

Using the REST Client extension in VSCode, send the request. The response should be:

Hello, World

Enhancing Request Handling

Now, let’s extract more information from incoming requests by modifying handler.ts:

console.log("Method:", req.method);
console.log("URL:", req.url);
console.log("Host:", req.headers.host);
console.log("Parsed URL:", parsedURL);

This will log details like HTTP method, URL, host, and query parameters, helping us understand incoming requests better.

Handling Additional Requests

Enhance the response logic:

if (!keyword) {
  res.write("Hello, HTTP");
} else {
  res.write(`Hello, ${keyword}`);
}

If the URL contains ?keyword=Alex, the response will be:

Hello, Alex

Conclusion

In this guide, we learned how to build a Node.js web server with TypeScript by:

  • Setting up a TypeScript-based Node.js project.
  • Creating an HTTP server with Node.js.
  • Handling incoming requests and parsing URLs.
  • Responding dynamically based on query parameters.

This server provides a solid foundation, but it’s still basic. To simplify request handling, check out the next tutorial on using Express.js with TypeScript!

Share this article

Similar Posts