Warning
This package is in beta and will have relatively frequent breaking changes.
Server integration for Vike.
With this extension, your server is transpiled with Vite. So that you don't need ts-node
/tsx
anymore.
In development, the server process is restarted when a change is detected.
Installation
Custom pageContext
Standalone build
External packages
Compression
Version history
Overview
Add to existing server
Supported servers
Example of adding vike-node
and Express.js to a Vike app that doesn't use a server yet.
Note
- See Add to existing server if you already have a server.
- See Supported servers for installing
vike-node
with a server other than Express.js.
npm install vike-node express
- Extend
vite.config.js
:// vite.config.js import vikeNode from 'vike-node/plugin' export default { // ... plugins: [vikeNode('server/index.js')] }
- Create
server/index.js
:// server/index.js import express from 'express' import vike from 'vike-node/express' startServer() function startServer() { const app = express() app.use(vike()) const port = 3000 app.listen(port, () => console.log(`Server running at http://localhost:${port}`)) }
- Add production
script
:// package.json "scripts": { "dev": "vite", "build": "vite build", + "prod": "NODE_ENV=production node dist/server/index.mjs" }
If you already have a server:
// server/index.js
- import { renderPage } from 'vike/server'
+ import vike from 'vike-node/express'
- 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": {
"build": "vite build",
- "dev": "node ./server/index.js",
+ "dev": "vite",
- "prod": "NODE_ENV=production node ./server/index.js"
+ "prod": "NODE_ENV=production node dist/server/index.mjs"
}
vike-node
includes middlewares for all commonly used server frameworks.
See complete list of supported servers.
// server/index.js
import express from 'express'
import vike from 'vike-node/express'
startServer()
function startServer() {
const app = express()
app.use(vike())
const port = 3000
app.listen(port, () => console.log(`Server running at http://localhost:${port}`))
}
// server/index.js
import fastify from 'fastify'
import vike from 'vike-node/fastify'
startServer()
function startServer() {
const app = fastify()
app.all('/*', vike())
const port = 3000
app.listen({ port }, () => console.log(`Server running at http://localhost:${port}`))
}
// server/index.js
import { serve } from '@hono/node-server'
import { Hono } from 'hono'
import vike from 'vike-node/hono'
startServer()
function startServer() {
const app = new Hono()
app.use(vike())
const port = 3000
serve(
{
fetch: app.fetch,
port
},
() => console.log(`Server running at http://localhost:${port}`)
)
}
// server/index.js
import { createApp, toNodeListener } from 'h3'
import { createServer } from 'http'
import vike from 'vike-node/h3'
startServer()
async function startServer() {
const app = createApp()
app.use(vike())
const port = 3000
const server = createServer(toNodeListener(app)).listen(port)
server.on('listening', () => {
console.log(`Server running at http://localhost:${port}`)
})
}
// server/index.js
import { Elysia } from 'elysia'
import vike from 'vike-node/elysia'
startServer()
function startServer() {
const app = new Elysia()
app.get('/*', vike())
const port = 3000
app.listen(port, () => console.log(`Server running at http://localhost:${port}`))
}
You can define custom pageContext properties:
import { type RuntimeAdapter } from 'vike-node/express';
app.use(
vike({
pageContext(runtime: RuntimeAdapter) {
return {
user: runtime.req.user
}
}
})
)
Note
See RuntimeAdapter
(vike-node
uses universal-middleware under the hood).
Note
The runtime
object is also available at pageContext.runtime
so that, even without the custom pageContext
function above,
you can retrieve pageContext.runtime.req.user
in Vike hooks and UI components (with usePageContext()
).
You can enable standalone builds by setting standalone
to true
.
After build, the output dist
folder will contain everything for a deployment.
With standalone mode, the production environment only needs the dist
folder to be present.
Example start script: NODE_ENV=production node dist/server/index.mjs
// vite.config.js
import vikeNode from 'vike-node/plugin'
export default {
// ...
plugins: [
vikeNode({
entry: 'server/index.js',
standalone: true
})
]
}
Packages that import native binaries/custom assets need to be added to external
.
When building with standalone
enabled, external
packages and their assets are copied to the output dist
directory.
By default, the external
setting includes:
sharp
@prisma/client
@node-rs/*
// vite.config.js
import vikeNode from 'vike-node/plugin'
export default {
// ...
plugins: [
vikeNode({
entry: 'server/index.js',
standalone: true,
external: ['my-rust-package']
})
]
}
In production, vike-node
compresses all Vike responses.
You can disable it:
app.use(
vike({
compress: false
})
)