Fastify is a framework designed for back-end web development. It offers a more lightweight alternative to heavier Node.js API frameworks, such as Hapi and Express. From July 2020, Fastify has released its third version of the framework. This third version comes with improved validation abilities to verify incoming and outgoing requests, as request parameters. Moreover, the third version of the framework consolidates its throughput claims of being the fastest Node.js framework compared with Koa, Resitfy, Hapi, and Express. More information can be found on the benchmarks page.
Let’s get started with this tutorial. You’ll learn the following aspects of Fastify:
- How to set up your first Fastify API
- How to define Fastify API routes
- How to add schema validation to requests
- How to load and use Fastify plugins
- How to define Fastify hooks
Requirements and Installation
To follow this tutorial, you’ll need:
- the latest Node.js version
- a tool for sending requests, such as cURL or Postman
Next, make sure to create an empty Node.js project. If you don’t have one yet, you can use the following command to set up your project:
npm init -y
Lastly, we want to add this Fastify dependency to our project:
npm i fastify --save
All good? Let’s create our basic API setup in the next step.
Step 1: Basic API Setup
First, let’s create our basic API setup. To get started, we need to create a new file called
index.js within our project root:
Next, let’s add the basic server setup. Copy the code below:
// Require the framework and instantiate it const app = require('fastify')( logger: true ) // Declare a route app.get('/', function (req, reply) reply.send( hello: 'world' ) ) // Run the server! app.listen(3000, (err, address) => if (err) app.log.error(err) process.exit(1) app.log.info(`server listening on $address`) )
There are a couple of things happening here. We first load the Fastify application object and enable logging. Next, we declare a root route that replies with a JSON response. The last part of the code snippet shows that we’re listening on port 3000 for the application to receive requests.
Let’s validate if your basic server setup works. First, we need to start the server by running the
Thereafter, navigate to
http://localhost:3000 in your browser. You should see the following response:
Success? Let’s go to Step 2 to define different CRUD routes.
Step 2: Define CRUD Routes
An API is useless with only GET routes. Let’s define more routes for handling blogs. Therefore, let’s create the following routes:
- GET all blogs at /api/blogs
- GET one blog at /api/blogs/:id
- POST add blog at /api/blogs
- PUT update blog at /api/blogs/:id
- DELETE delete blog at /api/blogs/:id
The first thing to do is creating a blog controller.
Step 2.1: Create Blogs Controller
To keep our code clean, let’s define a
controller folder in the project root. Here, we create a file called
This file contains some demo data to avoid complicating this tutorial with a database integration. Therefore, we use an array containing blog objects which each contain an ID and title field.
Moreover, we define the different handlers for all the above routes in this file. A handler always accepts a
req (request) and
reply parameter. The request parameter is useful to access request parameters or request body data.
Add the following code to your
// Demo data let blogs = [ id: 1, title: 'This is an experiment' , id: 2, title: 'Fastify is pretty cool' , id: 3, title: 'Just another blog, yea!' ] // Handlers const getAllBlogs = async (req, reply) => return blogs const getBlog = async (req, reply) => const id = Number(req.params.id) // blog ID const blog = blogs.find(blog => blog.id === id) return blog const addBlog = async (req, reply) => const id = blogs.length + 1 // generate new ID const newBlog = id, title: req.body.title blogs.push(newBlog) return newBlog const updateBlog = async (req, reply) => const id = Number(req.params.id) blogs = blogs.map(blog => if (blog.id === id) return id, title: req.body.title ) return id, title: req.body.title const deleteBlog = async (req, reply) => const id = Number(req.params.id) blogs = blogs.filter(blog => blog.id !== id) return msg: `Blog with ID $id is deleted` module.exports = getAllBlogs, getBlog, addBlog, updateBlog, deleteBlog
Note how we can access the request parameter for routes such as
req.params.id. For POST and PUT routes, we can access the body of the request via
In step 2.2, we’ll connect the route handlers to the route objects.
Step 2.2: Define Blog Routes and Couple Blogs Controller
Again, to keep our code clean, let’s define a
routes folder in the project root. Here, we create a file called
blogs.js. This file holds the routes object for our blog routes:
mkdir routes cd routes touch blogs.js
Luckily, Fastify allows us to define an array containing route objects. Here, we can couple the handlers we’ve defined previously to the different routes. Don’t forget to require the blogs controller. Let’s take a look:
const blogController = require('../controller/blogs'); const routes = [ method: 'GET', url: '/api/blogs', handler: blogController.getAllBlogs , method: 'GET', url: '/api/blogs/:id', handler: blogController.getBlog , method: 'POST', url: '/api/blogs', handler: blogController.addBlog , method: 'PUT', url: '/api/blogs/:id', handler: blogController.updateBlog , method: 'DELETE', url: '/api/blogs/:id', handler: blogController.deleteBlog ] module.exports = routes
Now we’ve defined all routes. However, Fastify doesn’t know about these routes. The next step shows how you can register routes with your Fastify application object.
How to Create Your First REST API with Fastify