Let's learn Fastify.js - A Fast and low overhead web framework, for Node.js

Let's learn Fastify.js - A Fast and low overhead web framework, for Node.js

Get started with basics of fastify, learning body,query,parameters etc.

What is fastify

According to the website itself, Fastify is a web framework highly focused on providing the best developer experience with the least overhead and a powerful plugin architecture, inspired by Hapi and Express.

It is another node js powered server side framework, which is good enough to be considered.

Why fastify

Fastify promotes itself by some really good points that will help us understand, why we can use this.

  1. Fast and low overhead web framework.

  2. Like express js but faster than express js.

  3. A better way to use plugins.

  4. Straight forward for APIs development, although can be used for SSR.

  5. A Better Request and response validation.

Other Options

There are many other options available for creating a web server using node.js

  1. Express js

  2. Fastify js

  3. Nest js

  4. Koa

But when it comes to developing API, fastify could be a very good option as it provides a clean architecture and default validation for request and responses.

See the pro and cons of some top nodejs web frameworks here.

Express vs Fastify

A common question may arise that why would you use fastify when there is express already. Fastify wins this argument by it's benchmarks. Fastify benchmarks

Fastify has a logger included, so I don't have to think about how to log.

Fastify supports async/await out of the box for all the components that must be awaited.

Another reason is that fastify provides some core plugins for which express js has to rely on the community.

Getting Started

We simply create a node js project, and install fastify in it.

mkdir fastify_started
cd fastify_started
npm init --yes
npm i fastify

Simple Server

A simple fastify server to say hello world is almost similiar to an express server doing the same.

We create an index.js file to write server code.

touch index.js
const fastify = require('fastify');
const app = fastify();

app.get('/', (req, res) => {
    res.send("Hello World !");
});

const PORT = 5000;
app.listen(PORT, () => {
    console.log("Server Started !")
});

The code is as simple as it looks. We created an app using Fastify.

When a get request is made at / route, we simply send hello world.

We use a port variable and make the app listen to the particular port.

Routing

Let's see how we can handle different Request methods using Fastify. I think the code itself is pretty self-explanatory.

const fastify = require('fastify');
const app = fastify();

app.get('/', (req, res) => {
    res.send("Hello World !");
});

app.post('/', (req, res) => {
    res.send("Hello POST !");
});

app.delete('/', (req, res) => {
    res.send("Hello DELETE !");
});

app.put('/', (req, res) => {
    res.send("Hello PUT !");
});

app.all('/user', (req, res) => {
    res.send("Hello All !");
});

const PORT = 5000;
app.listen(PORT, () => {
    console.log("Server Started !")
});

Router / Controller

It's a good idea to handle all the routes in different files or via a controller. it's a good way to maintain clean code and good architecture. Create a router.js file in controllers directory in the root folder. In our index.js file, we will register a router.

// register the router from controller to handle routes
app.register(require('./controllers/router'));

In the router.js file we will add a simple router function to handle the routes.

function Router(app, options, done) {
    // @Routes
    app.get('/', (req, res) => {
        res.code(200).send({"data" : "Response from router !"});
    }); 

    // @Not-Found Route
    app.all('*', (req, reply) => reply.code(404).send("ERR ! Not Found !"));

    done();
};

module.exports = Router;

Notice that things are little different here from express.js. Instead of use, we are using register and the router function ends with done(), just like a middleware in express js.

Route Prefix

Adding a route prefix is as simple as shown in the below code.

It adds a /api/v1 to all the routes of the router.

app.register(require('./controllers/router'), { prefix: 'api/v1' });

Query Parameters

All the query parameters are available in req.query. Let's take a look at a simple example.

// query
app.get('/user', (req, res) => {
    res.code(200).send({"data" : req.query.name});
});

If we send a name query with data, we will get the following response.

localhost:5000/user?name=Prince
{
  "data": "Prince"
}

Url Parameters

Url Parameters are available in req.params Let's take a look at a simple example.

app.get('/user/:username', (req, res) => {
    res.code(200).send({"data" : req.params.username});
});
localhost:5000/user/prince
{
  "data": "prince"
}

The parameter here is mandatory, which means without a parameter value, the route will throw an error. If we add a ? then the parameter becomes optional.

app.get('/user/:username?', (req, res) => {
    res.code(200).send({"data" : req.params.username});
});

Body

Handling body data is pretty easy in fastify as it securely parses the json by default.

That's why I said Straight forward for APIs development.

app.post('/', (req, res) => {
    res.code(200).send({"name" : req.body.name, "data" : req.body});
});

Make a request with name in json data and you will get the value in response.

  • Request
localhost:5000/
  • Body
{
    "name" : "prince",
    "username" : "prince"
}
  • Response
{
    "name": "prince",
    "data": {
        "name": "prince",
        "username": "prince"
    }
}