Node integration for Vike.
With this extension, your server-side code is transpiled with Vite.
In development, the server process is restarted when a change is detected in some of your server files.
Installation
Standalone build
External packages
Caching and compression
Custom pageContext
Framework examples
Migration guide
-
npm install vike-node express
-
Extend
vite.config.js
:// vite.config.js importvikeNodefrom'vike-node/plugin' exportdefault{ //... plugins:[vikeNode('server/index.js')] }
-
Create
server/index.js
:// server/index.js importexpressfrom'express' importvikefrom'vike-node/connect' startServer() functionstartServer(){ constapp=express() app.use(vike()) constport=process.env.PORT||3000 app.listen(port,()=>console.log(`Server running at http://localhost:${port}`)) }
You can enable standalone builds by settingstandalone
totrue
.
After build, the outputdist
folder will contain everything for a deployment.
With standalone mode, the production environment only needs thedist
folder to be present.
Example start script:NODE_ENV=production node dist/server/index.mjs
// vite.config.js
importvikeNodefrom'vike-node/plugin'
exportdefault{
//...
plugins:[
vikeNode({
entry:'server/index.js',
standalone:true
})
]
}
Packages that import native binaries/custom assets need to be added toexternal
.
When building withstandalone
enabled,external
packages and their assets are copied to the outputdist
directory.
By default, theexternal
setting includes:
sharp
@prisma/client
@node-rs/*
// vite.config.js
importvikeNodefrom'vike-node/plugin'
exportdefault{
//...
plugins:[
vikeNode({
entry:'server/index.js',
standalone:true,
external:['my-rust-package']
})
]
}
In production,vike-node
:
- compresses all Vike responses
- caches the compressed static assets(.js,.css).
On a request, if the asset(.js,.css) is not in the cache,vike-node
compresses it with a fast compression level, sends it in the response, then recompresses it with a high compression level and finally caches the compressed data.
You can disable compression/caching:
app.use(
vike({
compress:false,
static:{
cache:false
}
})
)
CustompageContext:
You can define custompageContextproperties:
app.use(
vike({
pageContext:(req)=>({
user:req.user
})
})
)
vike-node
includes middlewares for the most popular web frameworks:
- Express
- Fastify
- Hono
- H3
- Elysia (Bun)
Express:
// server/index.js
importexpressfrom'express'
importvikefrom'vike-node/connect'
startServer()
functionstartServer(){
constapp=express()
app.use(vike())
constport=process.env.PORT||3000
app.listen(port,()=>console.log(`Server running at http://localhost:${port}`))
}
Fastify:
// server/index.js
importfastifyfrom'fastify'
importvikefrom'vike-node/fastify'
startServer()
functionstartServer(){
constapp=fastify()
app.register(vike())
constport=+(process.env.PORT||3000)
app.listen({port},()=>console.log(`Server running at http://localhost:${port}`))
}
Hono:
// server/index.js
import{serve}from'@hono/node-server'
import{Hono}from'hono'
importvikefrom'vike-node/hono'
startServer()
functionstartServer(){
constapp=newHono()
app.use(vike())
constport=+(process.env.PORT||3000)
serve(
{
fetch:app.fetch,
port
},
()=>console.log(`Server running at http://localhost:${port}`)
)
}
H3:
// server/index.js
import{createApp,toNodeListener}from'h3'
import{createServer}from'http'
importvikefrom'vike-node/h3'
startServer()
asyncfunctionstartServer(){
constapp=createApp()
app.use(vike())
constport=process.env.PORT||3000
constserver=createServer(toNodeListener(app)).listen(port)
server.on('listening',()=>{
console.log(`Server running at http://localhost:${port}`)
})
}
Elysia (Bun):
// server/index.js
import{Elysia}from'elysia'
importvikefrom'vike-node/elysia'
startServer()
functionstartServer(){
constapp=newElysia()
app.use(vike())
constport=+(process.env.PORT||3000)
app.listen(port,()=>console.log(`Server running at http://localhost:${port}`))
}
// server/index.js
-import { renderPage } from 'vike/server'
+import { vike } from 'vike-node/connect'
-if (isProduction) {
-app.use(express.static(`${root}/dist/client`))
-} else {
-const vite = await import('vite')
-const viteDevMiddleware = (
-await vite.createServer({
-root,
-server: { middlewareMode: true }
-})
-).middlewares
-app.use(viteDevMiddleware)
-}
-app.get('*', async (req, res, next) => {
-const pageContextInit = {
-urlOriginal: req.originalUrl
-}
-const pageContext = await renderPage(pageContextInit)
-const { httpResponse } = pageContext
-if (!httpResponse) {
-return next()
-} else {
-const { statusCode, headers } = httpResponse
-headers.forEach(([name, value]) => res.setHeader(name, value))
-res.status(statusCode)
-httpResponse.pipe(res)
-}
-})
+app.use(vike())
// package.json
"scripts": {
-"dev": "node./server",
+"dev": "vite",
}