Routinejs, An Express inspired blazingly fast Nodejs router
Tags: javascript, typescript, node
Published: 2022-10-16 03:36:23

Hello there,
I am here to introduce you to Routine, An Express inspired and compatible Nodejs router.

> [Documentation](https://routine.juniordev.net) is still a work in progress but the core framework api is stable and ready to use.
Please consider leaving a star at Routine's Github [repo](https://github.com/Zulfiqar-Qureshi/routine-js)

**Some high level features of Routine**

✅ It is 5 times faster than Express (benchmark code is also available within the repo)
✅ Typescript support is built-in
✅ Radix trie based router
✅ Supports regex as url-path
✅ Middleware and nested route support
✅ Supports almost all existing Expressjs plugins/middlewares
✅ Built-in body parser and cookie-parser
✅ Built in json responder using fast-safe-stringify which is faster than native JSON.stringify and also detects _circular_ objects

>**Benchmark** comparing `Routine` with `Express` and `Hapi`, `Koa` was also tested but it failed to process so many requests and kept giving `ERPIPE error`, You can run these benchmarks yourself as well, simply refer to the `benchmarks` folder within the repo

![Benchmarks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u6z4g3lp364pg6v7nv5q.png)


> **Code examples below are also available on CodeSandbox [here](https://codesandbox.io/s/hello-routine-ltq4fq?file=/src/index.ts)**

**Let's start with a simple _Hello World_ example in Typescript**
```typescript
//Importing Routine class along with some types
import Routine, { Request, Response } from "@juniordev/routinejs";

//Creating a new instance of Routine
const app = new Routine();

//Registering a GET route on path '/'
app.get(`/`, (req: Request, res: Response) => {
  res.json({
    msg: "Hello Routine"
  });
});

//Starting the server on PORT 8080, default port is also 8080
app.listen(8080);
```

This starts the server at `http://localhost:8080` and when we visit this url, we receive `{"msg": "Hello Routine"}` since we have a `GET` route registered at `/` path.

> **Note:** The built-in `.json` method uses `fast-safe-stringify` which is faster than native `JSON.stringify` and also detects and prevents `[Circular]` Object within Response, So it is highly recommended to use this method for sending json payload to client.

**Let's have a look at _POST_ route**
```typescript
//Importing Routine class along with some types
import Routine, { Request, Response } from "@juniordev/routinejs";

//Creating a new instance of Routine
const app = new Routine();

//Registering a GET route on path '/'
app.get(`/`, (req: Request, res: Response) => {
  res.json({
    msg: "Hello Routine"
  });
});

//Registering a POST route also on path `/`
app.post(`/`, (req: Request, res: Response) => {
  //Automatic request body parsing without any plugin  
  //Sending the request body back to the client
  res.json(req.body);
});

//Starting the server on PORT 8080, default port is also 8080
app.listen(8080);
```
This time, we receive whatever we send as body to the server, if we send `{"msg": "Hello Routine"}` as `JSON` payload to the server,  we receive `{"msg": "Hello Routine"}` back.

Routine has all major `http verbs` built-in, such as
`GET`, `POST`, `PUT`, `PATCH` and `DELETE`

**Named & Query Params**
```typescript
//Importing Routine class along with some types
import Routine, { Request, Response } from "@juniordev/routinejs";

//Creating a new instance of Routine
const app = new Routine();

//Registering a GET route on path '/:name'
app.get(`/:name`, (req: Request, res: Response) => {
  res.json({
    name: req.params.name,
    query: req.query
  });
});

//Starting the server on PORT 8080, default port is also 8080
app.listen(8080);
```
Visiting `http://localhost:8080/routine?hello=world` would return us 
```json
{
  "name": "routine",
  "query": {
    "hello": "world"
  }
}
```

> **Note:** You can put any valid `regex` as path and routine will try to match it

**Using middlewares**
```typescript
//Registering a middleware
app.use((req: Request, res: Response, next: NextFunction) => {
  console.log("middleware called");
  next();
});
```

> Middleware functionality is same as Express, that is why Routine is almost fully compatible with Express plugins, and is tested with popular ones such as `Morgan`, `Express Validator` etc

**Lastly, let's see how `nested routes` are implemented**
```typescript
//src/router.ts
import { Router, Request, Response } from "@juniordev/routinejs";

const router = new Router();

router.get(`/router`, (req: Request, res: Response) => {
  res.json({
    msg: "from router"
  });
});

export default router;
```

```typescript
//src/index.ts
import Routine, { NextFunction, Request, Response } from "@juniordev/routinejs";
import router from "./router";

//Creating a new instance of Routine
const app = new Routine();

//Using a nested router
app.use(`/nested`, router);

app.listen(8080)
```

When we visit `http://localhost:8080/nested/router`, server returns `{"msg":"from router"}`

> All the above `http methods`, `named or query params`, `middlewares` can also be applied to `nested routes` as well, even so much so that `nested routes` can have more `nested routes`, and it does NOT degrade route matching performance due to startup/compile time route compilation

This was a basic introduction to `Routine`, many features such as `cancel` function, `global async error handling` etc is not yet talked about, but will be covered in future posts, you can read the [docs](https://routine.juniordev.net/docs/advanced/error-handler) for `async` error handling caveats for now though, its a good read i promise :)