Tutorial

Using Web-standard API Frameworks with Ampt

Ampt's universal runtime lets developers easily use web-standard frameworks like Elysia, Hono, and Itty Router.

TL;DR

Thanks to Ampt's standards-compliant runtime, app developers can take advantage of the speed, small size, and portability of web-standard frameworks like Elysia, Hono, and Itty Router. You can get started using one of our templates, or just install the Ampt CLI, install your favorite framework, and start building.

Introduction

Web-standard frameworks are becoming more and more popular thanks to the emergence of standards-compliant runtimes like Ampt, Cloudflare Workers, Bun, and Deno. These lightweight, fast, and highly portable frameworks rely on the standard Fetch API and "fetch" event. In this blog post, we'll dive into what web-standard frameworks are and how they work, explore their benefits and show you how to get started using them with Ampt.

What Are Web-Standard Frameworks?

Web-standard frameworks rely on the standard Fetch APIs, including the "fetch" event, Request and Response classes, and Streams classes. They are primarily used for building APIs, which take incoming requests, route them to appropriate handlers based on the URL and HTTP method, process the request, and return a response.

So why would you want to use a web-standard framework? The main reasons are:

  1. Size and speed: Web-standard frameworks are designed to run at the "edge," making them incredibly lightweight and fast. They are optimized for high performance, which ultimately is going to make your application faster and more responsive.
  2. Portability: These frameworks can be used across runtimes that support web standards, such as Ampt, Bun, Deno, Vercel Edge, and Cloudflare Workers. This portability allows developers to deploy their APIs in various environments without major modifications.
  3. Growing Popularity: Web-standard frameworks are gaining popularity and are continually evolving with the addition of useful features, middleware, and plugins. Several of these frameworks already support features like end-to-end type safety, automatic API documentation generation, and authentication support.

Each framework has its own philosophy and design principles, so ultimately you'll need to evaluate each one to see if it meets the needs of your application. Here's a quick list of some of the features you'll find that may be important for your application:

  • Fast routing with parameter support: all the frameworks use some form of fast router that can quickly map a URL and HTTP method to a handler, and extract parameters from the URL.
  • Typescript support: some frameworks have the ability to define Typescript types for URL parameters and request/response bodies. Some even have end-to-end type support, by providing a client that can share types with your backend.
  • Automatic API documentation: some frameworks can automatically document your APIs in Swagger/OpenAPI format based on the API definition and Typescript types.
  • Middleware/Plugins: the ability to extend your API's features by adding third-party middleware or plugins.

The fetch Event

Before we dive into specific web-standard frameworks, let's talk about how web-standard HTTP request handling works. The standard Web Fetch API defines an event-driven programming model where every incoming HTTP request is presented to your application as a fetch event. One of the benefits of this model is that it abstracts away the idea of a "server", and allows HTTP handlers to run in different physical contexts including on a server or "serverless function", in an "edge function" running close to the user in a CDN, and even in the user's browser in a "service worker".

Since the Ampt runtime is based on the Fetch API standard, you can handle HTTP requests without installing a single dependency, by calling addEventListener():

javascript
addEventListener('fetch', (event) => { event.respondWith( new Response(‘Hello world', { headers: { 'content-type': ‘text/plain' } }) ) })

The event listener listens for the "fetch" event, and has a synchronous (not async) event handler that calls the event's respondWith() method, with a new Response object. Although the handler is synchronous, it can call respondWith with a Response or a Promise that resolves to a Response.

Note that in theory you could add more than one "fetch" listener, but we don't recommend it since you'll likely want to just use a web framework and have that framework handle all your HTTP requests. If you have multiple listeners, the first one that calls event.respondWith() is the one that will get used.

Using web-standard frameworks

Now let's take a look at some specific web-standard frameworks. These frameworks ultimately are just "fetch" event handlers, but they are more fully featured and provide features like URL based routing with parameters, type-safety, and so on.

Any web framework that can handle a web-standard Request object and return a Response object will work with Ampt. Let's take a closer look at three of the more popular frameworks: Itty Router, Hono and Elysia.

Itty Router

Itty Router bills itself as being the smallest "feature-rich" router out there, and at 450 bytes it's kinda hard to argue with that. It has a clean and simple approach that defers creating the response until after all the middleware and handlers have run, which makes your code very concise.

Setting it up with Ampt is easy. The Router object has a handle method that you can use to handle the fetch event:

typescript
import { error, text, Router } from 'itty-router'; const router = Router(); router.get('/hello', () => 'Hello world'); addEventListener('fetch', (event: FetchEvent) => { event.respondWith(router.handle(event.request).then(text).catch(error)); });

Hono

Hono is a fast yet fully featured web framework with the familiar style of returning a Response from your handlers. Your handlers receive a "Context" object that provides some helpers for building responses. It also supports middleware and includes a few out of the box for authentication, caching, CORS and so on. Hono supports JSX for returning server-rendered HTML, which is fully supported in Ampt. which won't work yet with Ampt, but is coming soon to the Ampt runtime.

Setting up Hono with Ampt is easy thanks to its app.fire() method, which calls "addEventListener()" under the hood, so using Hono with Ampt is as simple as:

typescript
import { Hono } from 'hono'; const app = new Hono(); app.get('/', (c) => { return c.text('Hello Hono!'); }); app.fire();

Elysia

Elysia is another fast web-standard framework that is targeted at Bun users, but also works on any standard-compliant runtime. It has support for end-to-end type safety so you can write type-safe client-side code with auto-complete. It also has a long list of plugins for many common use cases including authorization, GraphQL, and tRPC.

To set it up with Ampt, you can use Elysia's fetch method:

typescript
import { Elysia } from 'elysia'; const app = new Elysia().get('/', () => 'Hello Elysia'); addEventListener('fetch', (event: FetchEvent) => { event.respondWith(app.fetch(event.request)); });

Conclusion

We've only touched on a few of the many web-standard frameworks that are available for building APIs. Others that we are aware of include Bao.js, Sunder, and Worktop. If you get a chance to try these or others with Ampt let us know. There are also several full-stack frameworks that use web standards for their server rendering, like Remix, Astro, and SvelteKit. The landscape is constantly changing and frameworks are constantly improving.

With their smaller footprint, portability, and growing feature sets, web-standard frameworks should be your first choice when building an API with Ampt. I hope this article has helped you understand what web-standard frameworks are and why you should consider them for your next project.

Happy building, and be sure to join our Discord community to ask any questions and share what you've built!

References:

The fastest way to get things done in the cloud!