Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/.config/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

name: srvx
shortDescription: Universal Server API
description: Based on web platform standards and works seamlessly with Deno, Bun and Node.js and more.
description: Built atop web platform standards to integrate seamlessly with Deno, Bun, Node.js, and more.
github: h3js/srvx
themeColor: red
socials:
Expand Down
2 changes: 2 additions & 0 deletions docs/1.guide/.navigation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
icon: i-ph:book-open-duotone
title: Guide
58 changes: 58 additions & 0 deletions docs/1.guide/0.index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
icon: pixel:play
---

# Getting Started

> Get to know srvx and familiarize yourself with basic usage.

Simply put, **srvx** is a compatibility layer for Node APIs. What this means is that it acts as a unified standard API to create HTTP servers based on the standard web platform primitives ([Fetch][Fetch], [Request][Request], and [Response][Response]) which integrates seamlessly with [Deno][Deno], [Bun][Bun], [Node.js][Node], and more.

For Deno and Bun (and [others](/guide/advanced/experimental)), **srvx** provides this unified interface at zero overhead by wrapping Node in as lithe an abstraction as possible.
This abstractive wrapper then consumes any [node:IncomingMessage][IncomingMessage] as a web standard [Request][Request] object and converts its final state of a [node:ServerResponse][ServerResponse] into the web standard [Response][Response] object.
This is the lightweight compatibility layer

## Quick Start

First, create an HTTP server using the `serve` function from the `srvx` package.

```js [server.mjs]
import { serve } from "srvx";

const server = serve({
fetch(request) {
return new Response("👋 Hello there!");
},
});
```

Then, install `srvx` as a dependency:

:pm-install{name="srvx"}

Finally, run the server using your favorite runtime:

::code-group

```bash [node]
node server.mjs
```

```bash [deno]
deno run --allow-env --allow-net server.mjs
```

```bash [bun]
bun run server.mjs
```

::

[Deno]: https://deno.com/
[Bun]: https://bun.sh/
[Node]: https://nodejs.org/
[Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request
[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response
[IncomingMessage]: https://nodejs.org/api/http.html#http_class_http_incomingmessage
[ServerResponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse
2 changes: 2 additions & 0 deletions docs/1.guide/1.basics/.navigation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
icon: ph:book-open-duotone
title: Guide
71 changes: 71 additions & 0 deletions docs/1.guide/1.basics/0.why.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
icon: clarity:rack-server-outline-alerted
---

# Why srvx?

> Why does srx exist and why would you want to use it?

### Making the Case

When creating a new HTTP server with [Node.js][Node], you must either use the [node:http](https://nodejs.org/api/http.html) module or a library derived from it.

**Ex.** - Node.js HTTP server ([learn more](https://nodejs.org/en/learn/getting-started/introduction-to-nodejs)):

```js
import { createServer } from "node:http";

createServer((req, res) => {
res.end("Hello, Node.js!");
}).listen(3000);
```

Whenever a new request is received, the request event is called with two Node objects:

- Request (conventionally `req`), which is of the type [node:IncomingMessage][IncomingMessage], and passed in as the first argument of the event and enables access to the HTTP request details.
- Response (conventionally `res`), which is of the type [node:ServerResponse][ServerResponse], and passed in as the second argument of the event and allows preparing and sending of an HTTP response.

Other popular server frameworks such as [Express][Express] and [Fastify][Fastify] also leverage the Node.js server API in their internals.

:read-more{to="/guide/advanced/node" title="Node.js support"}

With the recent arrival of new JavaScript server runtimes, [Deno][Deno] and [Bun][Bun], we've seen them implement a different approach when defining a server, which bears more in common with the web [Fetch][Fetch] API.

**Ex.** - Deno HTTP server ([learn more](https://docs.deno.com/api/deno/~/Deno.serve)):

```js
Deno.serve({ port: 3000 }, (_req, info) => new Response("Hello, Deno!"));
```

**Ex.** - Bun HTTP server ([learn more](https://bun.sh/docs/api/http)):

```js
Bun.serve({ port: 3000, fetch: (req) => new Response("Hello, Bun!") });
```

As you may have noticed, there is a difference between Node.js and Deno/Bun. With the latter two, the incoming request is a web [Request][Request] object and the server response is a web [Response][Response] object.
Accessing headers, the request path, and preparing the response is completely different from Node's implementation.

And while Deno and Bun servers are both based on web standards, there are differences between them as well. Some examples: how they provide options, server lifecycles, and accessing request info such as the client IP (which is not part of the web Request standard).

**Thus, the main use-case of this library is for tools and frameworks that wish to be runtime agnostic.**
Instead of depending on idiosyncratic runtime APIs, we can use **srvx** as a standardized server layer, and help drive the JavaScript ecosystem towards web standards and greater consistency!

### How is it Different?

You might ask, what is the difference between **srvx** and these other HTTP frameworks?

**srvx** provides a simple, low-level, and universal API, very similar to Deno and Bun's. It comes with **no conventions**, utilities, or router, and in most cases, introduces no overhead.

The core of **srvx** was extracted from an early development branch of the v2 for the [h3](https://h3.dev/) server framework and released to the broader ecosystem to encourage the adoption of web platform standards without enforcing its own conventions.

[Node]: https://nodejs.org/
[Deno]: https://deno.com/
[Bun]: https://bun.sh/
[Express]: https://expressjs.com/
[Fastify]: https://fastify.dev/
[Fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
[Request]: https://developer.mozilla.org/en-US/docs/Web/API/Request
[Response]: https://developer.mozilla.org/en-US/docs/Web/API/Response
[IncomingMessage]: https://nodejs.org/api/http.html#http_class_http_incomingmessage
[ServerResponse]: https://nodejs.org/api/http.html#http_class_http_serverresponse
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
102 changes: 0 additions & 102 deletions docs/1.guide/1.index.md

This file was deleted.

2 changes: 2 additions & 0 deletions docs/1.guide/2.advanced/.navigation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
icon: gis:cube-3d
title: Advanced
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ icon: akar-icons:node-fill

> Learn more about Node.js support with srvx.

> [!NOTE]
> This is an advanced section, explaining internal mechanism of srvx for Node.js support.
## View from Above

As explained in the [why srvx](/guide/why) section, [Node.js][Node.js] uses different API for handling incoming http requests and sending responses.
As explained in the [Why srvx?](/guide/basics/why) page, [Node.js][Node.js] uses different APIs for handling incoming http requests and sending responses.

srvx internally uses a lightweight proxy system that wraps [node:IncomingMessage][IncomingMessage] as [Request][Request] and converts the final state of [node:ServerResponse][ServerResponse] to a [Response][Response] object.
The internal mechanisms of **srvx** use a lightweight proxy system that wraps the [node:IncomingMessage][IncomingMessage] in a [Request][Request] and converts its final state of [node:ServerResponse][ServerResponse] to a [Response][Response] object.

## How Node.js Compatibility Works

Expand Down
74 changes: 74 additions & 0 deletions docs/1.guide/2.advanced/1.experimental.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
icon: game-icons:soap-experiment
---

# Experimental Support

> See what the team is working on to improve srvx's core offering.

## Caution! Scientists at work!

Currently, **srvx** provides support for two experimental adapters: [Cloudflare][Cloudflare] and the web [Service Worker API][Service Worker].
The aim is to enable engineers to leverage **srvx** in any conceivable server environment,
even those that impose specific handling of requests/responses, such as Cloudflare's Edge Network or browser-based Service Workers.
**srvx**'s lean ergonomics and middleware are maintained to ensure the same experience across adapters.

## Cloudflare

The Cloudflare brand has rapidly established a name that developers trust,
so it only serves to reason that their Worker runtime environment would be a desirable target for **srvx** users.
The framework provides its universal compat layer for any requests in the Worker Environment by utilizing Cloudflare's Fetch Handler API,
ensuring that Cloudflare-specific properties, environment variables, and execution context are all accommodated.
Care is taken to preserve access to critical capabilities, like `waitUntil()` for background tasks, and
runtime metadata is attached to identify the execution context. This enables any application making use of **srvx**
to be deployed as a Cloudflare Worker while maintaining the niceties of the web standard API.

Upcoming: Handling IP addresses

**Ex.** - Cloudflare Workers ([learn more](https://www.cloudflare.com/developer-platform/products/workers/)):

```js
import { serve } from "srvx/adapters/cloudflare";

export default serve({
fetch(request) {
return new Response(`<h1>Hello from Cloudflare!</h1>`, {
headers: { "Content-Type": "text/html; charset=UTF-8" },
});
},
});
```

## Service Workers

Anytime a Browser application has need for a proxy server to act in the absence of network availability, Service Workers are turned to. Whether completing computationally intensive tasks,
intercepting network requests, creating offline experiences, sending push notifications, or running background sync APIs, these are the purview of the
Service Worker. Retaining this core functionality is of crucial importance as any dev reaching for a Service Worker solution will expect consistency.
To this end, **srvx** smartly detects if it's running in a Browser or Service Worker context and delivers the commensurate behavior for each environment.
The entire Service Worker lifecycle is supported and managed as **srvx** self-registers, activates, and unregisters automatically. Critical features,
such as `waitUntil` capability for background operations, "claim immediately" behavior, and per-update page reloads so that new clients can be claimed.
During self-registration scenarios, any heavier application logic should be lazy loaded when performance implications are a concern (but when aren't they...? :smirk:).

> [!NOTE]
> As a safety measure, 404 responses and requests for static assets (i.e. URLs with file extensions) are skipped to avoid breaking normal browser behaviors.

Upcoming: An option for 404 handling will be explored

**Ex.** - Service Workers ([learn more](https://stackblitz.com/github/h3js/srvx/tree/main/playground?file=app.mjs)):

```js
import { serve } from "../node_modules/srvx/dist/adapters/service-worker.mjs";

// Internally the service worker is implemented by passing it as an option to the `serve()` function alongside `fetch()`
serve({
serviceWorker: { url: import.meta.url },
fetch(_request) {
return new Response(`<h1>👋 Hello there!</h1>`, {
headers: { "Content-Type": "text/html; charset=UTF-8" },
});
},
});
```

[Cloudflare]: https://www.cloudflare.com/
[Service Worker]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
10 changes: 10 additions & 0 deletions docs/1.guide/2.advanced/2.plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
icon: bi:plugin
---

# Plugins

> Learn more about how we leverage plugins to extend the srvx foundation with new functionalities.

> [!NOTE]
> More to come!! Keep watching this space...
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "srvx",
"version": "0.8.0",
"description": "Universal Server API based on web platform standards. Works seamlessly with Deno, Bun and Node.js.",
"description": "Universal Server API built atop web platform standards to integrate seamlessly with Deno, Bun, Node.js, and more.",
"homepage": "https://srvx.h3.dev",
"repository": "h3js/srvx",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion test/bench-node/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Node.js Cmpatibility Benchmarks
# Node.js Compatibility Benchmarks

Simple benchmarks primarily focus on how closely we can approach native `node:http` performance while using a web standards compatibility layer.

Expand Down