For each page, we can choose a different render mode:
SPA
SSR
HTML-only
Pre-rendering (SSG)
For example, we can render an admin panel as SPA while rendering marketing pages with SSR.
What "SPA", "SSR", "HTML-only" and "SSG" mean, and which one should be used, is explained at SPA vs SSR (and more).
The Vike boilerplates do SSR by default, which is a sensible default that works for most apps.
Instead of manually integrating Render Modes yourself, you can use a UI framework Vike extension (vike-react/vike-vue/vike-solid) which already integrates Render Modes. You can use Bati to scaffold an app that uses vike-react/vike-vue/vike-solid.
SPA
Rendering a page as SPA means that the page is loaded and rendered only in the browser.
To achieve that:
We set Page's meta configenv to { server: false, client: true } instead of { server: true, client: true }.
We adapt our onRenderHtml() and onRenderClient() hooks.
1. Page meta config
By setting Page's meta config env to { client: true, server: false } we tell Vike to load +Page.js only in the browser.
vite-plugin-ssr was the previous name of Vike. Contribution welcome to fork and update the Vue example.
2. Render hooks (SPA only)
If we only have SPA pages, then we adapt our onRenderHtml() and onRenderClient() hooks like the following.
Client-side onRenderClient() hook:
See What is Hydration? for understanding the difference between "rendering to the DOM" and "hydrating the DOM".
We also adapt our server-side onRenderHtml() hook:
This is the key difference between SPA and SSR: in SPA div#root is empty, whereas with SSR div#root contains our Page's root component pageContext.Page rendered to HTML.
This means that, with SPA, we use our server-side onRenderHtml() hook to generate HTML that is just an empty shell:
the HTML doesn't contain the page's content.
For production, we usually want to pre-render the HTML of our SPA pages in order to remove the need for a production Node.js server.
We can also use our server-side onRenderHtml() hook to render <head>:
If we have both SPA and SSR pages, then we adapt our onRenderHtml() and onRenderClient() hooks like this:
If we set the Page meta config env to { server: false, client: true } instead of
{ server: true, client: true } in config.js, then pageContext.Page is
only defined in the browser.