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

Architecture

Vite-plugin-ssr provides an frontend architecture that is both flexible and robust.

Do-one-thing-do-it-well

Vite-plugin-ssr's architecture is designed with meticulous care and follows what we call a "do-one-thing-do-it-well architecture": vite-plugin-ssr focuses on being an excellent frontend framework while not interfering with the rest of your stack.

With vite-plugin-ssr, you can choose:

  • Any UI framework (React/Vue/Solid/...)
  • Any server (Express.js, Deno, HatTip, ...)
  • Any deployment (AWS, Cloudflare Workers, Vercel, ...)

With vite-plugin-ssr, your application's architecture is composed of loosely coupled core constituents with a clear separation of concerns.

We believe it's paramount for the web that these core constituents are developed mostly independent of each other. Providing freedom for the user, and fostering a vibrant ecosystem with an innovation-driven competition delivering high-quality tools for the users.

onRenderHtml() & onRenderClient()

Packages such as vike-react, vike-vue and vike-solid integrate UI frameworks so that you don't have to write any integration code.

But, if you want, instead of using a vike-* package you can use the hooks onRenderHtml() and onRenderClient() for complete control over how pages are rendered.

Not only can you manually integrate with any UI framework you want and however you want, you can also deeply integrate with your favorite data fetching tools. For example, you can integrate with Relay in ways that aren't possible with other frameworks.

// /renderer/+onRenderHtml.js
// Environment: server

export default onRenderHtml

import { renderToHtml } from 'some-ui-framework'
import { escapeInject, dangerouslySkipEscape } from 'vite-plugin-ssr/server'

async function onRenderHtml(pageContext) {
  const { Page } = pageContext
  const pageHtml = await renderToHtml(Page)
  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>My VPS app</title>
      </head>
      <body>
        <div id="root">${dangerouslySkipEscape(pageHtml)}</div>
      </body>
    </html>`
}
// /renderer/+onRenderClient.js
// Environment: browser

export default onRenderClient

import { renderToDom } from 'some-ui-framework'

async function onRenderClient(pageContext) {
  const { Page } = pageContext
  await renderToDom(Page, document.getElementById('#root'))
}

renderPage()

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.

Vite-plugin-ssr can easily be embedded into any server architecture and any deployment strategy.