Environment: server.

The renderPage() function enables you to embed Vike into any server.

You only need renderPage() if you use SSR, see Optional.

From the perspective of a server, Vike is just a middleware:

// renderPage() doesn't depend on Node.js and can be used within any JavaScript environment:
// Node.js, AWS, Cloudflare, Vercel, Deno, Bun, Lagon, ...
import { renderPage } from 'vike/server'
 
// Any server: Express.js, Cloudflare Worker, AWS Lambda Function, Fastify, Hono, Nitro, ...
server.addMiddleware({
  method: 'GET',
  route: '*', // catch-all
  async handler(request) {
    const pageContextInit = { urlOriginal: request.url }
    const pageContext = await renderPage(pageContextInit)
    // `body` is the HTML of the page with a route matching pageContextInit.urlOriginal
    const { body, statusCode, headers } = pageContext.httpResponse
    const response = { body, statusCode, headers }
    return response
  }
})

You can embed renderPage() into any server and any deployment environment.

Alternatively, instead of using renderPage(), you can pre-render your pages and remove the need for a production server (and deploy to a static host instead).

Examples

Usage

// server/index.js
 
// In this example we use Express.js but we could use any other server framework
import express from 'express'
import { renderPage, createDevMiddleware } from 'vike/server'
 
const isProduction = process.env.NODE_ENV === 'production'
const root = `${__dirname}/..`
 
startServer()
 
async function startServer() {
  // Create an Express.js server
  const app = express()
 
  // Dev/prod middleware
  if (!isProduction) {
    const { devMiddleware } = await createDevMiddleware({ root })
    app.use(devMiddleware)
  } else {
    // In production, we need to serve our static assets ourselves.
    // (In dev, Vite's middleware serves our static assets.)
    app.use(express.static(`${root}/${outDir}/client`))
  }
 
  // ...
  // Other middlewares (authentication, REST/GraphQL/RPC middleware, ...)
  // ...
 
  // SSR middleware.
  // Note: it should always be the last middleware, because it's a catch-all
  // middleware that supersedes any middleware placed after it.
  app.get('*', async (req, res) => {
    const pageContextInit = {
      // Required: the URL of the page
      urlOriginal: req.originalUrl
 
      // Optional: the HTTP Headers
      headersOriginal: req.headers,
 
      // Optional: information about the logged-in user (when using an
      // Express.js authentication middleware that defines `req.user`).
      user: req.user
 
      // ... we can provide any additional information about the request here ...
    }
 
    const pageContext = await renderPage(pageContextInit)
 
    const { body, statusCode, headers } = pageContext.httpResponse
    headers.forEach(([name, value]) => res.setHeader(name, value))
    res.status(statusCode).send(body)
  })
 
  const port = 3000
  app.listen(port)
  console.log(`Server running at http://localhost:${port}`)
}

The pageContext.httpResponse.body value is the HTML string returned by the onRenderHtml() hook with additional <script> and <style> tags automatically injected by Vike.

You can control where and what Vike injects using API > injectFilter().

For HTML streams use httpResponse.pipe() instead of pageContext.httpResponse.body, see HTML Streaming.

Optionally, you can use pageContext.httpResponse.earlyHints for adding early hints (103 Early Hint), see Guides > Preloading > Early hints.

The renderPage() function doesn't depend on Node.js and you can use renderPage() (and therefore embed Vike) anywhere:

  • Any server environment (Express.js, HatTip, Deno, Fastify, Vite's development server, Node.js's HTTP server, ...)
  • Any deployment provider (AWS, Cloudflare Workers, Vercel, ...)

When modifying your server, you may need to manually restart your server for your changes to take effect. See #562.

Optional

If you pre-render all your pages then you don't need to use renderPage(), because:

  • Upon development ($ vike dev), Vike automatically embeds itself into Vite's development server.
  • Upon pre-rendering ($ vike build/$ vike prerender), Vike automatically renders all your pages.

But, if you use Server-Side Rendering (SSR) and you don't pre-render all your pages, then you need a production server and you need to use renderPage() in order to embed Vike into your server. See Guides > Pre-rendering (SSG).

See also