Recently I've been writing simple VueJS tutorials. This got me thinking -- wouldn't it be better if I also had a backend that complements Vue? Several articles later, I was convinced that ExpressJS is just what I need.
This tutorial:
- will generate a bare-bones ExpressJS server app
- will discuss how to write a simple ExpressJS API (GET)
- will demonstrate how to convert a static route to a dynamic one
- will not discuss the complete RESTful verbs (POST, PUT, PATCH, etc)
Project Setup
mkdir express-routing-practice && cd express-routing-practice
npm init -y
npm i --save express debug http
This will generate package.json
and package-json.lock
for us. We'll need the debug
and http
modules because it's required by bin/www
(more details later).
Express Setup
For this tutorial, I don't recommend using the Express generator because it creates a lot of boilerplate code that we won't use. What we'll do is use it as a guide to bootstrap our app. This also helps identify which sections of the Express generator is directly related to routing.
Create a bin
folder and an empty file www
.
mkdir bin && cd $_
touch www
Copy this from the official repo to bin/www
to do the heavy lifting. We don't need to delve in detail what each line does. However we do need to note that var app = require('../app')
tells us which file is our entry point. Let's create that file now via touch app.js
in the root folder, then add the following:
// app.js
var express = require('express');
var app = express();
module.exports = app;
Update package.json
to remove the default entry point index.js
and add a new script to start our server:
// before
{
"name": "express-routing-practice",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
...
}
// after
{
"name": "express-routing-practice",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "DEBUG=express-routing-practice:* node ./bin/www",
"test": "echo \"Error: no test specified\" && exit 1"
},
...
}
Then in your terminal, start your server via npm start
. Visit localhost:3000
in your browser. If you're seeing Cannot GET /
, that means our server is operational! 🎉
Create a GET endpoint
We'll create 2 routes with 1 GET endpoint for each. Create a new folder and the 2 files via:
mkdir routes
touch routes/home.js
touch routes/users.js
home route
Open home.js
and paste the following:
var express = require('express');
var router = express.Router();
// Explanation: A nameless path GET request without any parameters.
// We'll learn how to name a path in users route.
router.get('/', function(req, res, next) {
return res.json({ message: 'Home!', data: null })
});
module.exports = router;
Then add this to app.js
anywhere before module.exports = app;
to use it:
// Explanation: requests to `localhost:3000/` should be redirected to `routes/home.js`
var homeRouter = require('./routes/home')
app.use('/', homeRouter);
Restart your server then visit localhost:3000
to see the json on screen!
users route
Setup users.js
and add some data:
var express = require('express');
var router = express.Router();
var data = [
{
name: 'Bibi',
},
{
name: 'Colt',
},
{
name: 'Jessie',
}
]
router.get('/', function(req, res, next) {
return res.json({ message: 'Users Index', data: data });
});
module.exports = router;
then update app.js
to include:
var usersRouter = require('./routes/users');
app.use('/users', usersRouter);
Restart server, visit 'localhost:3000/users' and see the data come to life.
Tip: You can also use cURL
to test your endpoints. We're making an API after all 😄.
Adding path name to a GET endpoint
By convention, a GET endpoint will return a complete list (or an index) of a resource. But should you need to set another GET endpoint, Express is ready for that.
Let's build on top of users.js
to create more GET endpoints:
router.get('/Bibi', function(req, res, next) {
var name = req.originalUrl.split('/')[2];
var user = data.filter(u => u.name == name);
return res.json({ message: 'User Show', data: user });
});
router.get('/Colt', function(req, res, next) {
var name = req.originalUrl.split('/')[2];
var user = data.filter(u => u.name == name);
return res.json({ message: 'User Show', data: user });
});
router.get('/Jessie', function(req, res, next) {
var name = req.originalUrl.split('/')[2];
var user = data.filter(u => u.name == name);
return res.json({ message: 'User Show', data: user });
});
Explanation: a GET request to localhost:3000/users/Bibi
will be redirected to the subpath Bibi
, and so on.
Whoa there! Our reference data didn't change but our source code just scaled in size! Imagine if we had 99 objects in the data
array -- will we make 99 subpaths? Well technically we can but wouldn't it be better if there was a way to encapsulate all these subpaths?
Dynamic routes
What we've created up until now are called static routes. To convert these into a dynamic route, we simply need to declare an identifier using a colon (:
). Express then automagically determines which subpath the request should be redirected to.
Updating the three subpaths:
router.get('/:name', function(req, res, next) {
var name = req.params.name;
var user = data.filter(u => u.name == name );
return res.json({ message: 'Users Show', data: user });
});
Hooray! Now you'll be able to access localhost:3000/users/Bibi
, localhost:3000/users/Colt
, and localhost:3000/users/Jessie
using one dynamic route 🎉!
Top comments (0)