Architecture

In the spirit of do-one-thing-do-it-well, Vike focuses on being an excellent frontend framework while not interfering with the rest of your stack.

With Vike, your application's architecture is composed of independent core constituents with a clear separation of concerns.

We believe it's paramount for user freedom and fostering innovation resulting in high-quality tools.

renderPage()

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)
    if (!pageContext.httpResponse) return null
    // `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.

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).

Vike can easily be embedded into any server architecture and any deployment strategy.

onRenderHtml() & onRenderClient()

The Vike extensions vike-react/vike-vue/vike-solid integrate UI frameworks. Instead, you can use the hooks onRenderHtml() and onRenderClient() for a bespoke integration of your favorite UI framework.

// /renderer/+onRenderHtml.js
// Environment: server
 
export { onRenderHtml }
 
import { renderToHtml } from 'some-ui-framework' // React, Vue, Solid, Preact, Svelte, ...
import { escapeInject, dangerouslySkipEscape } from 'vike/server'
 
async function onRenderHtml(pageContext) {
  const { Page } = pageContext
  const pageHtml = await renderToHtml(Page)
  return escapeInject`<!DOCTYPE html>
    <html>
      <head>
        <title>My Vike app</title>
      </head>
      <body>
        <div id="root">${dangerouslySkipEscape(pageHtml)}</div>
      </body>
    </html>`
}
// /renderer/+onRenderClient.js
// Environment: browser
 
export { onRenderClient }
 
import { renderToDom } from 'some-ui-framework'
 
async function onRenderClient(pageContext) {
  const { Page } = pageContext
  await renderToDom(Page, document.getElementById('#root'))
}

Not only do you control the UI framework integration, but you also control the integration of data-fetching tools such as RPC and GraphQL.

For example, you can integrate Relay in ways that aren't possible with other frameworks.

Configuration

Vike's config inheritance and extensibility enable mighty Vike extensions and user customizations.

You can even use completely different rendering strategies (e.g. React + SSR for some pages, and Vue + SPA for other pages) within the same app.