# Nuxt and Server-Side Rendering — Vue.js

Source: https://www.skillbyai.com/en/vue/x-nuxt

> When to render on the server.

## SSR, hydration and Nuxt

A plain Vue app renders in the browser, so the first HTML is nearly empty until JavaScript runs. **Server-side rendering (SSR)** renders the HTML on the server for faster first paint and better crawlability, then **hydrates** it in the browser to make it interactive. The server and client output must match, so browser-only APIs (`window`, `localStorage`) belong in `onMounted`, which does not run on the server. **Nuxt** is the full-stack framework built on Vue that provides SSR, static generation, file-based routing in `pages/`, auto-imports, server API routes in `server/` and data helpers such as `useFetch` and `useAsyncData`. Choose it for content sites, SEO-sensitive pages and full-stack apps; a Vite SPA is simpler for apps behind a login. Nuxt conventions differ between major versions, so check the docs for your version.

## A Nuxt page with server data

File-based routing and useFetch.

```vue
<!-- pages/products/[id].vue  ->  route /products/:id -->
<script setup>
const route = useRoute()               // auto-imported in Nuxt

// runs on the server during SSR; the result is transferred to the client
const { data: product, error } = await useFetch(`/api/products/${route.params.id}`)

useHead({ title: () => product.value?.name ?? 'Product' })
</script>

<template>
  <p v-if="error">Product not found</p>
  <article v-else-if="product">
    <h1>{{ product.name }}</h1>
    <p>{{ product.description }}</p>
  </article>
</template>

<!-- server/api/products/[id].get.js would implement the API route -->
```

## A printed menu versus a chalkboard

SSR hands guests a printed menu as they sit down (ready HTML); a client-rendered app gives them a blank chalkboard that a waiter fills in after arriving (JavaScript).

**Quiz:** Why should code that uses window or localStorage go in onMounted in an SSR app?

- [ ] window is faster inside lifecycle hooks
- [ ] onMounted runs before the server responds
- [x] onMounted runs only in the browser, not during server rendering
- [ ] SSR disables all other hooks

*Answer:* onMounted runs only in the browser, not during server rendering. The server has no browser globals.
