Published on

Setting Up a Simple Express Server

Authors
  • avatar
    Name
    Nali Thephavong Haehn
    Twitter

This tutorial will walk you through creating a standalone Express application that serves dummy order data. We'll incorporate basic concepts of RESTful web services and an MVC-like design pattern to create an app that you can use as a template for simple or complex APIs. No frontend, no database, just the basics.

Link to repository: GitHub

NOTE
This post was meant as a reference for quickly deploying an Express app, so I'm leaving out much of the why and focusing on the how. Be sure to bookmark this for future reference.

Pre-requisites

  • Install Node.js. I am using version 18.17.1, as of writing, but anything >= 16 should be sufficient.
HOT TIP
To check which version of node is installed, use the command node --version in a terminal window.

Setup Project Folder Structure

For very simple projects, you can get away with writing code in the entry point file (typically, something like app.ts or index.ts) located directly under the main folder, but if you are doing anything more complex you should be segregating your logic into easily readable components. In this case, we'll use something akin to MVC.

  • Create a folder for your project files, I created express_example.
  • Create the following folders under your main folder: routes, controllers, models.
NOTE
You can also have a views folder if you plan to create an integrated UI with ejs templates, but I prefer to use Express as a backend for a standalone React frontend, so we won't need that here. Also, yes, mono-repos are gaining popularity, but that's not what we're doing here.

At the end of this tutorial, you should have a folder structure that looks like this:

express_example
├── controllers
│   └── orders-controller.ts
├── models
│   └── orders-model.ts
├── package.json
├── routes
│   └── orders-route.ts
├── server.ts
└── tsconfig.json

Instantiate Node Project

  • In a terminal window, navigate to the express_example folder and run the command: npm init -y.

    This will generate a package.json file in express_example. The -y switch is to suppress the prompts, but if you'd prefer to go through the setup wizard, then you can remove it.

  • Run the following command to install dependencies: npm install express dotenv cors body-parser

  • Run the following to install dev-only dependencies: npm install -D @types/cors @types/express @types/node nodemon typescript

NOTE
You can also use yarn to install packages, but for simplicity, I will use npm which is included in the Node.js package.

Create a tsconfig.json File

This file is used to transpile your typescript files into javascript.

Under your express_example folder, create a file named tsconfig.json. Paste the following code in the file:

{
  "compilerOptions": {
    "target": "es2016",
    "module": "commonjs",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Write Express Entry Point Script

Under the express_example folder, create a file named server.ts. This will be where you instantiate your Express app.

NOTE
I prefer to use server vs. app/index in this case as it's more indicative of what we're doing (setting up a backend server). If you do decide to use app or index, make sure all references to server are changed accordingly.

Paste the following code in your file:

import express, { Express, Request, Response, NextFunction } from 'express';
import dotenv from 'dotenv';
import cors from 'cors';
import { json } from 'body-parser';

dotenv.config();

const app: Express = express();
const port = process.env.PORT || 8000;

app.use(cors());

app.use(json());

app.get('/', (req: Request, res: Response) => {
  res.json({message:'Simple Express Server'});
});

app.use((err: Error, req: Request, res:Response, next: NextFunction) => {
  res.status(500).json({message: err.message});
});

app.listen(port, () => {
  console.log(`[server]: Server started at http://localhost:${port}`);
});

Create a Model File

Since we are returning information about orders, we'll create a model for an order with very basic fields.

Under the models folder, create an orders-model.ts file with the following information:

export class Order {
    orderdate: string;
    id: string;
    customer: string;
    total: string;
    status: string;
    shipdate: string;
    trackingnumber:string;
    constructor (
        orderdate: string,
        id: string,
        customer: string,
        total: string,
        status: string,
        shipdate: string,
        trackingnumber:string
    ) {
      this.orderdate = orderdate;
      this.id = id;
      this.customer = customer;
      this.total = total;
      this.status = status;
      this.shipdate = shipdate;
      this.trackingnumber = trackingnumber;
    }
}

Create a Controller File

This is where all of the logic for our route lives.

Under the controllers folder, create an orders-controller.ts file, with the following code:

import { Request, Response, NextFunction } from 'express';
import { Order } from '../models/orders-model';

// DO NOT USE THIS IN PRODUCTION
// THIS IS JUST TO INITIALIZE TEST DATA
let ORDERS: Order[] = [
    {
        orderdate: '2023-08-01',
        id: '20000001',
        customer: 'A Popular Donut Place',
        total: '457.89',
        status: 'New',
        shipdate: '',
        trackingnumber: ''
    },
    {
        orderdate: '2023-08-02',
        id: '20000002',
        customer: 'Another Popular Donut Place',
        total: '975.42',
        status: 'In Process',
        shipdate: '',
        trackingnumber: ''
    }
];

// #region MAIN FUNCTIONS
export const getOrders = (req: Request, res: Response, next: NextFunction) => {
    return res.status(200).json({
        "orders": ORDERS
    });
}
// #endregion

Create Your First Route

Associate the getOrders function from the controllers file with our main GET route.

Under the routes folder, create an orders-route.ts file:

import { Router } from 'express';
import { getOrders } from '../controllers/orders-controller';

const router = Router();
router.get('/', getOrders);
router.post('/');
router.patch('/:id');
router.delete('/:id');

export default router;

Update Your Entry Point Script

Tie all of the code together in the entry point file.

Open server.ts and add the lines of code designated by the arrow:

//...

import { json } from 'body-parser';

import ordersRoutes from './routes/orders-route';  //<---

//...

app.use(json());

app.use('/orders', ordersRoutes); // <---

app.get('/', (req: Request, res: Response) => {
  res.json({message:'Simple Express Server'});
});

//...

Prepare to Run Your App

Open the package.json file and update the scripts section. Also, make sure the main tag aligns with the name of your entry point file:

{
  "name": "express_example",
  "version": "1.0.0",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npx tsc",
    "start": "node dist/server.js",
    "dev": "npm run build && nodemon -q dist/server.js"
  },
  ...
}

Run Your App

Open a terminal window and navigate to express_example, then run npm run dev. This will compile your files into javascript and serve them up on localhost port 3000 (unless a different port was specified in server.ts).

Navigating to http://localhost:3000/orders will return the list of orders from your controller.

What's Next

  • Create the rest of the routes using what you've learned. The complete code can be found in the github repo (GitHub) if you prefer to just see the answers.
  • Use an application like Postman to test your routes.
  • Create a front-end to call your new Express server (more on this soon!).