Our First Express Code and Route
Now that we understand some key concepts, let us build and run our first Express server together. We will walk through each part of the code and explain what it does, as well as how to run and test our server.
Write Our First Express Server
Add the following code to src/index.ts:
import express from "express";
const app = express(); // This creates our Express application
const PORT = 3000; // This is the port our server will listen on
// This defines a GET route for the root URL ('/')
app.get("/", (req, res) => {
// req (the request) contains information about the incoming request (URL, query params, etc.)
// res (the response) is used to send data back to the client
res.json({ message: "Hello world!" }); // This sends a JSON response to the client
});
// This starts the server and listens for incoming requests
app.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}`);
});
What does each part do?
express(): Creates our Express application. This is the main object we use to define routes and handle requests.app.get('/', ...): Sets up a route that listens for GET requests to the root URL (/).(req, res): Every route handler receives two arguments:req(the request): Contains information about the incoming request (such as URL, query parameters, headers, etc.).res(the response): Used to send data back to the client, usually with methods likeres.json().
res.json({ message: 'Hello world!' }): Sends a JSON response back to the client. This is the standard way to return data from an API endpoint.app.listen(PORT, ...): Starts our server and tells it to listen for requests on the specified port. The callback function runs when the server starts.console.log(...): Prints a message to the terminal where we started the server. This is not visible in the browser’s console — unlike frontend development, allconsole.logoutput from our backend code appears in our terminal or command prompt.
Testing your API endpoint
- The
res.jsonmethod sends JSON data from our server to the client that made the request. After we start the server, if we visithttp://localhost:3000/in a browser, we will see a JSON response:{ "message": "Hello world!" }. If we use Postman or curl, the same JSON will be returned in the response.
Why use res.json?
res.jsonis the standard way to send data from an API. It ensures the response is always in JSON format, which is what frontend applications expect when working with APIs.
Running Our Server
There are a couple of ways to run our TypeScript server:
Option 1: Using tsx (Recommended for Development)
tsxis a tool we installed above that runs our TypeScript code directly and automatically restarts the server when we make changes. This is very convenient during development and works perfectly with ES modules.-
To run the server with
tsx, use:npx tsx watch src/index.ts - Now, whenever we save changes to our code, the server will restart automatically. Visit http://localhost:3000/ to see the json returned. Change the value in
res.jsonto see the return value updated without restarting the server.
Option 2: Using tsc and node (For Production)
- We can also compile our TypeScript code to JavaScript and then run it with Node.js.
- First, compile the code:
npx tsc -
Then, run the compiled code:
node dist/index.jsThis output is compiled into the
distfolder and will need to be compiled again before you see any changes. So use this for production, not for development.
Setting Up Scripts in package.json
To make running our server easier, let us add scripts to our package.json file:
"scripts": {
"dev": "tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js"
}
npm run dev: Starts the server in development mode with auto-reloading.npm run build: Compiles our TypeScript code to JavaScript.npm start: Runs the compiled JavaScript code (for production).