Integrating Fastify with VitePress
Fastify is a modern, fast, and low overhead web framework for Node.js. In this post, we’ll explore how to integrate Fastify with VitePress using a custom Vite plugin, providing a high-performance server-side solution for your documentation site.
Why Choose Fastify?
Fastify offers several advantages over traditional web frameworks:
- Performance: One of the fastest web frameworks available
- TypeScript Support: Built-in TypeScript support
- Schema-based Validation: JSON Schema validation out of the box
- Plugin System: Highly extensible through plugins
- Low Overhead: Minimal impact on your application’s performance
Setting Up the Fastify Plugin
Let’s create a custom Vite plugin that will integrate Fastify with our VitePress application.
1. Create the Fastify Plugin
Create a new file docs/.vitepress/plugins/fastify.js
:
import Fastify from 'fastify'
import cors from '@fastify/cors'
export function createFastifyPlugin(options = {}) {
const {
corsOptions = {
origin: '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
},
} = options
return {
name: 'vite-plugin-fastify',
async configureServer(server) {
const fastify = Fastify({
logger: true,
})
// Enable CORS
await fastify.register(cors, corsOptions)
// Example route
fastify.get('/api/hello', async (request, reply) => {
return { message: 'Hello from Fastify!' }
})
// Example POST route
fastify.post('/api/submit', async (request, reply) => {
const data = request.body
return { success: true, data }
})
// Use Fastify as middleware in Vite’s server
server.middlewares.use(async (req, res, next) => {
// Skip Fastify handling for non-API routes
if (!req.url.startsWith('/api')) {
return next()
}
try {
const response = await fastify.inject({
method: req.method,
url: req.url,
headers: req.headers,
payload: req.body,
})
// Set response headers
Object.entries(response.headers).forEach(([key, value]) => {
res.setHeader(key, value)
})
// Set status code
res.statusCode = response.statusCode
// Send response
res.end(response.payload)
} catch (error) {
next(error)
}
})
},
}
}
2. Configure VitePress
Update your docs/vite.config.js
to use the Fastify plugin:
import { createFastifyPlugin } from './.vitepress/plugins/fastify'
export default {
plugins: [
createFastifyPlugin({
corsOptions: {
origin: 'http://localhost:5173', // VitePress default port
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
allowedHeaders: ['Content-Type', 'Authorization'],
},
}),
],
}
How It Works
The integration works by:
- Creating a custom Vite plugin that initializes a Fastify application
- Using Vite’s middleware system to integrate Fastify with the development server
- Running Fastify routes on the same port as VitePress (default: 5173)
The key to making this work is the middleware implementation:
server.middlewares.use(async (req, res, next) => {
// Skip Fastify handling for non-API routes
if (!req.url.startsWith('/api')) {
return next()
}
try {
const response = await fastify.inject({
method: req.method,
url: req.url,
headers: req.headers,
payload: req.body,
})
// Set response headers
Object.entries(response.headers).forEach(([key, value]) => {
res.setHeader(key, value)
})
// Set status code
res.statusCode = response.statusCode
// Send response
res.end(response.payload)
} catch (error) {
next(error)
}
})
This implementation:
- Only handles routes that start with
/api
- Properly forwards all other routes to VitePress
- Correctly sets response headers and status codes
- Handles errors appropriately
Testing the Integration
- Start your VitePress development server:
npm run docs:dev
- You should now be able to:
- Visit your VitePress site at
http://localhost:5173
- Access the Fastify API endpoint at
http://localhost:5173/api/hello
- Visit your VitePress site at
You should receive a JSON response:
{
"message": "Hello from Fastify!"
}
Adding Custom Routes
You can add your own routes by modifying the createFastifyPlugin
function. Here’s an example of adding a POST endpoint with schema validation:
fastify.post('/api/submit', {
schema: {
body: {
type: 'object',
required: ['name', 'email'],
properties: {
name: { type: 'string' },
email: { type: 'string', format: 'email' }
}
}
}
}, async (request, reply) => {
const data = request.body
return { success: true, data }
})
Benefits of Using Fastify
- Performance: Fastify is one of the fastest web frameworks available
- Schema Validation: Built-in JSON Schema validation for request/response
- TypeScript Support: Excellent TypeScript support out of the box
- Plugin Ecosystem: Rich ecosystem of plugins for various functionalities
- Developer Experience: Great developer experience with detailed error messages
Considerations
- This setup is primarily for development. For production, you might want to consider:
- Running Fastify as a separate service
- Using a reverse proxy (like Nginx)
- Implementing proper security measures
- Remember that VitePress is still a static site generator, so this integration is most useful during development or when you need specific server-side functionality
Conclusion
Integrating Fastify with VitePress using a custom Vite plugin provides a high-performance way to add server-side functionality to your documentation site. This approach combines the simplicity of VitePress with the speed and features of Fastify.
Remember to check out the VitePress documentation and Fastify documentation for more information about both technologies.