Server-Side Rendering (SSR) Guide
Relevant source files
The following files were used as context for generating this wiki page:
Server-Side Rendering (SSR) in wouter-vue allows Vue 3 applications to render routing logic on the server, providing faster initial page loads and improved SEO. The library leverages Vue's Composition API and @vue/server-renderer to generate static HTML strings that can be hydrated on the client side.
The SSR implementation focuses on providing a non-interactive environment where the router's state is derived from a provided path and search string rather than browser APIs like window.location. This is achieved through specialized SSR helpers and a custom entry point for server-side execution.
Sources: README.md:46, src/ssr.ts
SSR Architecture and Data Flow
The SSR flow in wouter-vue involves a Node.js server (typically Express) that intercepts incoming requests, uses Vite to load the server-side entry point, and passes the request URL to the Vue application.
Rendering Sequence
The following sequence diagram illustrates how a request is processed from the Express server through the Vue application to generate the final HTML response.
The server-side entry point is responsible for splitting the incoming URL into a path and a query string (search) before initializing the Vue app.
Sources: examples/example/server.js:46-75, examples/example/src/entry-server.js:5-18
Core SSR Components and Helpers
URL Parsing
In an SSR environment, the router cannot rely on the browser's location object. The render function must manually parse the incoming URL to provide the initial routing state.
export async function render(url) {
let path = url || '/';
let search = '';
if (typeof url === 'string') {
const qIdx = url.indexOf('?');
if (qIdx >= 0) {
path = url.slice(0, qIdx) || '/';
search = url.slice(qIdx + 1);
}
}
const app = createSSRApp(() => h(App, { ssrPath: path, ssrSearch: search }));
// ...
}
Sources: examples/example/src/entry-server.js:5-18
SSR Utility Functions
The library provides internal helpers to detect the environment and handle SSR-specific path logic.
| Function | Description | Source |
|---|---|---|
isSSR | Boolean check to determine if the code is executing in a server environment. | types/helpers.d.ts:13 |
isBrowser | Boolean check to determine if the code is executing in a browser environment. | types/helpers.d.ts:13 |
parseSsrPath | Normalizes and parses the URL string into components suitable for the router. | types/helpers.d.ts:13 |
Implementation Details
Server-Side Configuration
The server configuration uses Vite in middleware mode to handle transformation of the index.html and loading of the server entry. This allows for hot module replacement (HMR) during development while providing a path to production builds.
// Development: Vite transforms template and loads module
template = await vite.transformIndexHtml(url, template);
const serverEntry = await vite.ssrLoadModule('/src/entry-server.js');
render = serverEntry.render;
// Production: Import pre-built server bundle
render = (await import('./dist/server/entry-server.js')).render;
Sources: examples/example/server.js:53-65
Building for SSR
The project requires two separate build steps: one for the client-side assets and one for the server-side bundle.
| Build Command | Purpose | Configuration |
|---|---|---|
build:client | Generates the static assets and the client entry point. | vite build --outDir dist/client |
build:server | Generates the SSR-compatible bundle for the server. | vite build --ssr src/entry-server.js --outDir dist/server |
Sources: examples/example/package.json:7-9
Conclusion
The SSR implementation in wouter-vue provides a lightweight and efficient way to render Vue 3 applications on the server. By abstracting environmental differences through isSSR checks and providing a clear path for URL injection via ssrPath and ssrSearch props, the library maintains its minimalist philosophy while supporting complex rendering requirements. This architecture ensures high performance (72% higher throughput compared to standard routers) by minimizing overhead during the string-rendering phase.
Sources: README.md:46-60