⚠
vite-plugin-ssr has been renamed Vike, see migration guide.

renderPage()

Environment: server.

The renderPage() function enables you to integrate and embed vite-plugin-ssr into any server. It's optional (it's only needed if you use SSR).

From the perspective of the server, vite-plugin-ssr is just a middleware:

// renderPage() doesn't depend on Node.js and can be used in any JavaScript environment:
// AWS, Cloudflare, Vercel, Node.js, Deno, Bun, Lagon, ...
import { renderPage } from 'vite-plugin-ssr/server'

// Can be any server: Express.js, Fastify, Hono, Cloudflare Worker, AWS Lambda Function, ...
server.addMiddleware({
  method: 'GET',
  route: '*', // Catch-all
  async handler(request) {
    const pageContextInit = { urlOriginal: request.url }
    const pageContext = await renderPage(pageContextInit)
    const { body, statusCode, headers } = pageContext.httpResponse
    const response = { body, statusCode, headers }
    return response
  }
})

The vite-plugin-ssr middleware is versatile and can be used within any server environment.

Alternatively, you can pre-render your pages to 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 } from 'vite-plugin-ssr/server'

const isProduction = process.env.NODE_ENV === 'production'
const root = `${__dirname}/..`

startServer()

async function startServer() {
  // Create an Express.js server
  const app = express()

  // Vite integration
  if (!isProduction) {
    // We instantiate Vite's development server and integrate its middleware to our server.
    // ⚠️ We instantiate it only in development. (It isn't needed in production and it
    // would unnecessarily bloat our production server.)
    const vite = await import('vite')
    const viteDevMiddleware = (await vite.createServer({
      root,
      server: { middlewareMode: true }
    })).middlewares
    app.use(viteDevMiddleware)
  } 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 (e.g. some RPC middleware such as Telefunc)
  // ...

  // Vite-plugin-ssr middleware. It should always be our last middleware (because it's a
  // catch-all middleware superseding any middleware placed after it).
  app.get('*', async (req, res, next) => {
    const pageContextInit = { urlOriginal: req.originalUrl }
    const pageContext = await renderPage(pageContextInit)
    if (pageContext.httpResponse === null) return next()
    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 render() hook with additional <script> and <style> tags automatically injected by vite-plugin-ssr.

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

The pageContext.httpResponse value is null if:

  • An error occured while rendering the page and no error page is defined.
  • An error occured while rendering the error page.
  • Vite-plugin-ssr skips certain URLs, such as /favicon.ico (because browsers automatically make favicon requests).

The renderPage() function doesn't depend on Node.js and you can use renderPage() (and therefore embed vite-plugin-ssr) 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.

See also:

Optional

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

  • Vite-plugin-ssr automatically embeds itself into Vite's development server ($ vite/$ vite dev) and Vite's preview server ($ vite preview).
  • During pre-rendering ($ vite build/$ vite-plugin-ssr prerender) vite-plugin-ssr automatically renders your pages.

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 vite-plugin-ssr into your server.