Vafast
2,454,631 reqs/sExpress
113,117
Measured in requests/second. Result from TechEmpower Benchmark Round 22 (2023-10-17) in PlainText
This guide is for Express users who want to see the differences between Express and Vafast, including syntax, and how to migrate an application from Express to Vafast by example.
Express is a popular Node.js web framework widely used to build web applications and APIs. It's known for its simplicity and flexibility.
Vafast is a high-performance TypeScript web framework that runs on Node.js, Bun and other runtimes, focused on type safety, a middleware system and performance. It's designed for simplicity and developer friendliness, with full TypeScript support.
Thanks to radix tree route matching and JIT-compiled validators, Vafast is significantly faster than Express.
113,117
Measured in requests/second. Result from TechEmpower Benchmark Round 22 (2023-10-17) in PlainText
Express and Vafast have similar routing syntax, but Vafast defines routes with configuration objects, providing better type safety and middleware support.
import express from 'express'
const app = express()
app.get('/', (req, res) => {
res.send('Hello World')
})
app.post('/id/:id', (req, res) => {
res.status(201).send(req.params.id)
})
app.listen(3000)Express uses
reqandresas the request and response objects
import { Server, defineRoute, defineRoutes } from 'vafast'
const routes = defineRoutes([
defineRoute({
method: 'GET',
path: '/',
handler: () => 'Hello World'
}),
defineRoute({
method: 'POST',
path: '/id/:id',
handler: ({ params }) => {
return { id: params.id }
}
})
])
const server = new Server(routes)
export default { fetch: server.fetch }Vafast defines routes with configuration objects, with type safety and middleware support
Express uses chained method calls:
app.get('/users', (req, res) => { ... })
app.post('/users', (req, res) => { ... })Vafast uses an array of configuration objects:
const routes = defineRoutes([
defineRoute({
method: 'GET',
path: '/users',
handler: () => { ... }
}),
defineRoute({
method: 'POST',
path: '/users',
handler: () => { ... }
})
])How the new framework works:
- Every route must be wrapped in
defineRoute- A handler is just a function; no more
createHandlerwrapper
Express uses the req and res objects:
app.get('/user/:id', (req, res) => {
const id = req.params.id
const query = req.query
res.json({ id, query })
})Vafast uses destructured parameters:
defineRoute({
method: 'GET',
path: '/user/:id',
handler: ({ params, query }) => {
return { id: params.id, query }
}
})Express uses app.use() and route-level middleware:
app.use(loggingMiddleware)
app.get('/admin', authMiddleware, (req, res) => {
res.send('Admin Panel')
})Vafast supports global and route-level middleware:
import { defineRoute, defineRoutes, defineMiddleware } from 'vafast'
const loggingMiddleware = defineMiddleware(async (req, next) => {
console.log(`${req.method} ${req.url}`)
return await next()
})
const routes = defineRoutes([
defineRoute({
method: 'GET',
path: '/admin',
handler: () => 'Admin Panel',
middleware: [authMiddleware]
}
])Express uses error-handling middleware:
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})Vafast has a built-in errorHandler; just throw err.xxx() in the handler:
import { err } from 'vafast'
defineRoute({
method: 'GET',
path: '/users/:id',
handler: ({ params }) => {
const user = findUser(params.id)
if (!user) throw err.notFound('User not found')
return user
},
})The framework injects
errorHandlerautomatically, so there's no need to write try/catch middleware.
npm install vafastConvert Express route definitions into Vafast's configuration object format:
// Express style
app.get('/api/users', (req, res) => {
const users = getUsers()
res.json(users)
})
// Vafast style
defineRoute({
method: 'GET',
path: '/api/users',
handler: () => {
return getUsers()
}
})Convert Express middleware into the Vafast middleware format:
// Express middleware
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization
if (!token) {
return res.status(401).send('Unauthorized')
}
next()
}
// Vafast middleware
import { defineMiddleware, json } from 'vafast'
const authMiddleware = defineMiddleware(async (req, next) => {
const token = req.headers.get('authorization')
if (!token) {
return json({ error: 'Unauthorized' }, 401)
}
return await next()
})// Express error handling
app.use((err, req, res, next) => {
res.status(500).json({ error: err.message })
})
// Vafast: built-in errorHandler; throw err.xxx() in the handler
import { err } from 'vafast'
defineRoute({
method: 'GET',
path: '/users/:id',
handler: ({ params }) => {
const user = getUserById(params.id)
if (!user) throw err.notFound('User not found')
return user
},
})import express from 'express'
import cors from 'cors'
import helmet from 'helmet'
const app = express()
app.use(cors())
app.use(helmet())
app.use(express.json())
app.get('/users', (req, res) => {
const users = getUsers()
res.json(users)
})
app.post('/users', (req, res) => {
const user = createUser(req.body)
res.status(201).json(user)
})
app.get('/users/:id', (req, res) => {
const user = getUserById(req.params.id)
if (!user) {
return res.status(404).json({ error: 'User not found' })
}
res.json(user)
})
app.listen(3000)import { Server, defineRoute, defineRoutes, json, err } from 'vafast'
import { cors } from '@vafast/cors'
const routes = defineRoutes([
defineRoute({
method: 'GET',
path: '/users',
handler: () => getUsers()
}),
defineRoute({
method: 'POST',
path: '/users',
handler: ({ body }) => json(createUser(body), 201)
}),
defineRoute({
method: 'GET',
path: '/users/:id',
handler: ({ params }) => {
const user = getUserById(params.id)
if (!user) {
throw err.notFound('User not found')
}
return user
}
})
])
const server = new Server(routes)
server.use(cors())
export default { fetch: server.fetch }How the new framework works:
- Every route is wrapped in
defineRoute- A handler is just a function; no more
createHandler- Global middleware uses
server.use()
| Feature | Express | Vafast |
|---|---|---|
| Type safety | ❌ Requires extra setup | ✅ Full TypeScript support |
| Performance | ⚠️ Moderate | High performance |
| Middleware system | ✅ Mature | ✅ Flexible and extensible |
| Route definitions | ⚠️ Chained calls | ✅ Configuration objects |
| Error handling | ✅ Middleware-based | ✅ Middleware chain |
| Bun support | ❌ Requires adaptation | ✅ Native |
Now that you know how to migrate from Express to Vafast, we suggest you:
If you run into any issues during migration, feel free to ask for help on GitHub Issues.