#100DaysOfMERN - Day 24

Subscribe to my newsletter and never miss my upcoming articles

✏ More about Express

I'm still exploring a server setup with Express JS. So far, I've used it to make GET/POST/PUT/DELETE requests to the backend in my Boring Book App (starting from Day 17), and also set up another project to serve a static HTML file with express.static() - with very little code. Continuing from Day 23 (I've removed the logger function, as that was only to demonstrate how to use middleware with app.use()):


import express from 'express';
import path from 'path';

const app = express();

app.use(express.static(path.join(path.resolve('./'), 'public')))

app.listen(3001, ()=>console.log('express is serving'))

✏ Creating an API

Let's say I want to create a simple API to serve and manipulate some data. I've already done that with my Book App, where I set up a few routes, going either to an /api/books or an /api/books/:id endpoint. With Express, this was easily done:

import books from './data/bookdata.js';

app.get('/api/books', (req, res) => res.json(bookdata))

I had four functions to handle GET, POST, PUT and DELETE requests, and I wrote them all directly into my server.js file. While that worked well for such a small app, the server file would get a little clogged up when there are many routes that need to be defined. Express offers a possibililty to handle this much cleaner:

✏ Express Router

express.Router is a built-in middleware that's quite easy to use. It works pretty much the same as with defining routes directly on the app instance of Express.

What's nice about this is that I can put all the parts of the code that deal with routing into a separate file, from which I only export the router middleware:


import express from 'express';
import books from './data/bookdata.js';

const router = express.Router();

router.get('/api/books', (req, res) => res.json(bookdata))

router.post('/api/books', (req, res) => {
    const newBook = {...req.body};
    newBook.id = (Math.max(...books.map(b => +b.id)) + 1).toString();


/* ... more routes or custom middleware */

export default router

Then, over in express.js, I just import it, and all the routes are ready to use (note that I've also added app.use(express.json), which is a body parser middleware that comes with Express):

import express from 'express';
import path from 'path';
import { router } from './routes.js'

const app = express();


app.listen(3001, ()=>console.log('express is serving'))

So far, I've only set up the backend that serves a static HTML file, and an API to send back raw JSON data. If I wanted to make a real application like my Book App, where I could make POST, PUT and DELETE requests to edit my book data, I'd now also have to set up a frontend with at least a <form> and some <input> elements in order to test if the requests are working as expected. However this isn't necessary, and this is where another tool comes in very handy:

✏ Postman

Postman is a tool that lets you make all possible HTTP requests to your backend, without actually having a frontend.


Here, you can see that I've made a POST request to http://localhost:3001/api/books. I've first set the Content-Type in the Headers to application/json, and entered some raw JSON data with a new book title into the Body field, then clicked on "Send".

In the bottom section, you can see that the server responded with status code 200 OK, and that the response includes the new, updated book list.

I haven't even begun to explore all of Postman's features, but this is already quite helpful if you're only working on the backend and want to test if all your routes are doing what they're supposed to do.

✏ Recap

I've learned

  • how to use express.Router
  • how to use Postman as a tool to test the backend without a frontend

✏ Next:

✏ Thanks for reading!

I do my best to thoroughly research the things I learn, but if you find any errors or have additions, please leave a comment below, or @ me on Twitter. If you liked this post, I invite you to subsribe to my newsletter. Until next time 👋

✏ Previous Posts

  • Day 1: Introduction, Node.js, Node.js in the terminal
  • Day 2: npm, node_modules, package.json and package-lock.json, local vs global installation of packages
  • Day 3: Create a React app without create-react-app, Webpack, Babel
  • Day 4: npx and cowsay
  • Day 5: npm vs. npx, npm audit, semantic versioning and update rules
  • Day 6: Call stack, event loop, JavaScript engine, JavaScript runtime
  • Day 7: Call stack and event loop in Node.js, setImmediate()
  • Day 8: setImmediate(), process.nextTick(), event loop phases in Node.js
  • Day 9: Network requests with XMLHttpRequest and callbacks
  • Day 10: Promises
  • Day 11: Network requests with XMLHttpRequest and Promises
  • Day 12: React Quiz App part 1
  • Day 13: React Hangman
  • Day 14: FullStackOpen course 1: details of GET and POST requests, request headers
  • Day 15: React Hangman: Trigger fetch with click event callback vs useEffect
  • Day 16: REST API and CRUD
  • Day 17: Boring Book App part 1: React Frontend, Express Backend, GET requests, CORS
  • Day 18: Boring Book App part 2: POST request, File System API
  • Day 19: Boring Book App part 3: Request Parameters, DELETE request
  • Day 20: Boring Book App part 4: PUT request
  • Day 21: Express.js vs Vanilla.js part 1: Server setup, routes
  • Day 22: Express.js vs Vanilla.js part 2: Serve static files with Vanilla Server
  • Day 23: Express.js vs Vanilla.js part 3: Serve static files with Express Server, Middleware

No Comments Yet