DEV Community

Peter
Peter

Posted on

Routup: A Fast, Lightweight and Asynchronous Routing Framework

Image description

Introduction

If you're looking for a blazing fast, lightweight, and asynchronous routing framework for Node.js (and other runtimes like Deno), look no further than Routup πŸš€. It's designed to be runtime-agnostic, meaning you can use it in various environments with ease. Plus, it's even 228% faster than Express! In this blog post, we'll explore Routup's key features, usage, and more.

Installation

To get started, simply install Routup via npm:

npm install routup --save
Enter fullscreen mode Exit fullscreen mode

Key Features

  • πŸš€ Runtime Agnostic: Routup can be used across different JavaScript runtime environments, including Node.js, Deno, and more.
  • πŸ“ Handler Types: It supports different handler types, including base and error handlers.
  • ✨ Async Support: Promises and asynchronous functions are fully supported for both core and error handlers.
  • πŸ”Œ Plugin System: Routup comes with a powerful plugin system that extends its functionality.
  • 🧰 Request and Response Helpers: It provides a set of utility functions to interact with requests and manipulate responses.
  • 🀝️ Handler Declaration Styles: Routup offers different handler declaration styles, from shorthand to verbose, to suit your preferences.
  • πŸ“ Nestable Routers: You can nest routers within routers for a structured routing hierarchy.
  • πŸ‘• TypeScript Support: If you love TypeScript, Routup has you covered.
  • 🀏 Minimalistic: It's designed to be minimalistic, ensuring it fits seamlessly into your solution with minimal overhead.
  • & much more

Code

To contribute to the project or examine the code, this can be done on GitHub.

Documentation

For in-depth information and examples, check out the official Routup documentation (routup.net).

Usage

Let's dive into how to use Routup by exploring its handler types and various runtime examples.

Handlers

Routup supports two handler types: core and error handlers. You can define them in two different ways: shorthand and verbose.

Shorthand

In the shorthand variant, only the handler function is passed as an argument to the coreHandler and errorHandler functions.

import { createServer } from 'node:http';
import {
    coreHandler,
    createNodeDispatcher,
    errorHandler,
    Router,
    useRequestParam
} from 'routup';

const router = new Router();

router.get('/', coreHandler(() => 'Hello, World!'));
router.get(
   '/greet/:name', 
    coreHandler((req) => `Hello, ${useRequestParam(req, 'name')}!`)
);
router.use(errorHandler(
    (err) => `An error with statusCode ${err.statusCode} occured.`)
);

const server = createServer(createNodeDispatcher(router));
server.listen(3000)
Enter fullscreen mode Exit fullscreen mode

Verbose

The verbose variant allows you to set additional information like the path, method, etc., in the handler definition.

import { createServer } from 'node:http';
import {
    coreHandler,
    createNodeDispatcher,
    errorHandler,
    Router,
    useRequestParam
} from 'routup';

const router = new Router();

router.get(coreHandler({
    path: '/',
    fn: () => 'Hello, World!',
}));

router.get(coreHandler({
    path: '/greet/:name',
    fn: (req) => `Hello, ${useRequestParam(req, 'name')}!`
}))

router.use(errorHandler({
    fn: (err) => `An error with statusCode ${err.statusCode} occured.`
}))

const server = createServer(createNodeDispatcher(router));
server.listen(3000)
Enter fullscreen mode Exit fullscreen mode

Runtimes

Routup is compatible with various JavaScript runtime environments. Here are examples for running Routup with Bun and Deno.

Bun

import { coreHandler, createWebDispatcher, Router } from 'routup';

const router = new Router();

router.get('/', coreHandler(() => 'Hello, World!'));

const dispatch = createWebDispatcher(router);

Bun.serve({
    async fetch(request) {
        return dispatch(request);
    },
    port: 3000,
});
Enter fullscreen mode Exit fullscreen mode

Deno

import { coreHandler, createWebDispatcher, Router } from 'routup';

const router = new Router();

router.get('/', coreHandler(() => 'Hello, World!'));

const dispatch = createWebDispatcher(router);

const server = Deno.listen({
    port: 3000,
});
for await (const conn of server) {
    const httpConn = Deno.serveHttp(conn);

    for await (const requestEvent of httpConn) {
        const response = await dispatch(requestEvent.request);
        requestEvent.respondWith(response);
    }
}
Enter fullscreen mode Exit fullscreen mode

Plugins

While Routup is minimalistic, it offers a powerful plugin system to extend its functionality. Check out some essential plugins:

  • assets: Serve static files from a directory.
  • basic: Bundle of the body, cookie and query plugin.
  • body: Read and parse the request body.
  • cookie: Read and parse request cookies and serialize cookies for the response.
  • decorators: Create request handlers with class, method, and parameter decorators.
  • prometheus: Collect and serve metrics for Prometheus.
  • query: Read and parse the query string of the request URL.
  • rate-limit: Rate limit incoming requests.
  • rate-limit-redis: Redis adapter for the rate-limit plugin. swagger: Serve generated docs from URL or based on a JSON file.

Top comments (0)