Hey API Dev, tired of building express apps that don't perform well under high loads? Want something that feels a bit cleaner and modern to build your next multi-million dollar project?
You may have heard of Bun, the newest JS runtime before, but have you heard of an ergonomic developer-friendly API framework that uses Bun?
If not, this article is for you 🎉
There's a few contenders out there but the one that really stood out to me is Elysia.
What is Elysia?
Elysia is a HTTP API framework written on Bun with developer experience being the main motivation of the framework.
Essentially, a faster Express.js replacement.
Elysia is set up for you to write functions and returns for your API. Need to send a response to the client? Just return your data in the callback function. No need to rely on req/res explicitly.
A basic Elysia endpoint could look like this:
Which will return a 200 and the string Test
inside the response body.
The implementation syntax looks similar to express but cleaner, in my opinion.
Elysia Paths
You can leverage all the regular HTTP Methods and also add your own:
Or if you don't care about the method, you can use .all
instead of .get .post
etc.
You can also handle 404 errors like so:
Need dynamic paths? No worries:
Need multiple dynamic variables on an endpoint? They got you:
What about wildcards? Don't worry about it:
As you can see, Elysia has a lot of power baked in. But what about returning data?
Elysia's Handler Function
Those callbacks you saw in the code-snippets are the "handler". A handler is a callback function as the second argument in an endpoint. As you saw, we can extract params, path, and the request context by destructuring the request object:
The request object isn't lost to us tho. To alter request headers or redirects, we can leverage set
like so:
More info on request context here.
Elysia Responses
Elysia will automatically create the response object for you from whatever you return in your handler function.
If you want, you can also return a new Response()
object and Elysia will handle it.
Want to move your routes to different files? Leverage Elysia's plugin system.
Need some additional functionality? Checkout the community.
Life Cycle Events
I won't go into too much detail here but this is an illustration of what's going on under the hood.
When a request is made and accepted, the system will transform the request to the object we receive in our handler function.
If we have validation in place, that occurs next. The handler function is executed and returns data in form of a HTTP Response.
If this all makes sense, let's move on to a demo!
API Demo
💻 Completed code here
Let's start by creating a new Elysia app!
You can easily create a new Elysia app by running bun create elysia app
in your terminal where "app" is the name of your new application. If you don't have Bun installed, you can install it via curl curl -fsSL https://bun.sh/install | bash
.
Next, cd into the new directory and run the app with bun run dev
. A dev server should start up at localhost:3000
.
Building Our Endpoints
For this demo, we're going to be connecting to the Trefle plant API. This API contains a very wide variety of plants and we'll be performing get requests for the purpose of this demo.
We're going to make a few endpoints to get our plant data.
1. Get 30 plants
2. Search by query
3. Search by plant genus
4. Search by plant species
First off, we'll add those endpoints to index.ts
Don't worry about the handler function for now, we'll add those later after we complete the next step.
Next, let's create the file that'll contain these functions in src/api.ts
. Add these functions below:
But before we can attach these functions to the plant API, we need to get a token to authenticate. If you create an account here, you'll be granted with an API token to use their API.
Once you get your token, add it to .env
inside our project as API_TOKEN
. We'll leverage Bun to securely access our secrets. No dotenv package needed! Env variables are available via Bun with Bun.env.${YOUR_ENV}
.
After your token has been added, let's kill the current server and restart with bun run dev
. Now our value for the env variable should be accessible.
Next we will connect our API to Trefle with a generate URL function. This function will construct a new URL object and dynamically append any query params to the string.
Now that we have a way to construct our url to the Trefle API, let's start getting some data. We'll need to complete those handler functions I mentioned earlier.
For each handler, call the generateUrl function we created. For the specifics on getting plants, refer to the screenshot below. The purpose of this article isn't to use the Trefle API, just to demonstrate how to setup an Elysia instance.
Cool, if your code looks similar to the snippet above, let's move on to wrapping up the endpoints inindex.ts
.
We just need to import the handler functions and assign them to the proper endpoints.
After that's done, if we go to localhost:3000/plants
in our browser, we should see a JSON object returned with 30 plants 🎉 🌿
Test out the other endpoints to get specific genus or species data! That about sums up the demo.
Additional Things About Elysia
There's still a lot about the framework that we couldn't cover in this article. Here are some quick links if anything catches your eye.
Cookies in Elysia
Swagger docs
Websockets
Lazy loading
Dos and donts
E2E type safety
Resources / Thank you
Thanks for taking the time to read! What did you think? Are you going to be trying Elysia anytime soon? Let me know in the comments!
If you want to know more about the API framework, checkout these links below.
Elysia Docs
Elysia Github
Official Plugins
Demo Repo
Image credits go to the Elysia repository image author. I did not create the banner image on this post