uNode is a high-performance Node.js web api framework built on top of uWebSockets.js with multi-threading support. It is designed to be simple, fast, and easy to use. uNode is inspired by Express.js and ASP.NET Core minimal API.
- Blazing fast performance
- Multi-threading
- Simple and intuitive API
- Route groups
- Middleware
- File serving
- Streaming
- Cookies
- Request body parsing
npm i "@oki.gg/unode"
uNode is built on top of uWebSockets.js, which has specific constraints regarding asynchronous operations within route handlers. You must not access the request object (req) after using await or returning a promise. This is due to the fact that the request object is not valid after the asynchronous operation completes.
Attempting to access the request object after an asynchronous operation will result in an error like the following:
Error: uWS.HttpRequest must not be accessed after await or route handler return. See documentation for uWS.HttpRequest and consult the user manual.
To work around this limitation, extract all necessary information from the request object before performing any asynchronous operations. Here is an example:
.get('/', async (req, res) => {
const someHeader = req.getHeader('someHeader')
const body = await req.body()
await new Promise((resolve) => setTimeout(resolve, 1000))
res.json({ someHeader, body })
})
const app = new App({ threads: 4 }) // defaults to 1 thread if not specified
new App()
.get('/', () => 'Hello World!')
.listen(3000)
const app = new App()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})
app.post('/', async (req, res) => {
const body = await req.body()
res.json(body)
})
const group = new Router()
.get('', () => 'Get all')
.post('', () => 'Created')
.get('/:id', () => 'Get by id')
.delete('/:id', () => 'Deleted')
app
.group('/api', group)
.listen(3000)
app.use((req, res, next) => {
console.log('Middleware')
next()
})
app.get('/file', (req, res) => {
res.sendFile('path/to/file')
})
app.get('/*', serveStatic('path/to/directory'))
app.get('/:id', (req, res) => {
const id = req.params.id
const query = req.getQueryParams()
res.json({ id, query })
})
app.get('/', (req, res) => {
// Get cookie
const cookie = req.getCookie('name')
// Set cookie
res.setCookie('name', 'value', {
maxAge: 3600,
secure: true,
httpOnly: true,
sameSite: 'strict'
})
res.send(cookie)
})
All tests where done using Apache JMeter on a Windows 11 PC, WSL 2 ubuntu 22.04, AMD Ryzen 5 5600X 3,7GHz 6-core 12-thread CPU, 32GB RAM
100 concurrent users, 1 seconds ramp-up period, 60 seconds test duration.
"Hello world" plain text response.
160091.185 requests/second (multi-threaded, 4 threads)
77227.514 requests/second (single-threaded)
160091.185 requests/second
131820.081 requests/second
123631.414 requests/second
78089.792 requests/second
77227.514 requests/second
65598.721 requests/second
64097.835 requests/second
63300.917 requests/second
32322.931 requests/second
9322.392 requests/second