Skip to content

Commit f6fad9c

Browse files
authored
docs(integrations): add SSR page for Vue (#5512)
1 parent 20d99a9 commit f6fad9c

File tree

1 file changed

+183
-0
lines changed
  • docs/content/docs/1.getting-started/6.integrations

1 file changed

+183
-0
lines changed
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
---
2+
title: SSR
3+
description: 'Nuxt UI have first-party support for Vue.js SSR. This guide will help you have it fully enabled.'
4+
framework: vue
5+
navigation.icon: i-simple-icons-markdown
6+
---
7+
8+
## Usage
9+
10+
When using Nuxt UI with Nuxt.js framework, SSR server will fully work out of the box. However, when using it with pure Vue.js, you will need to pay attention to some details to make it function as expected.
11+
12+
### Color Variables Injection
13+
14+
Nuxt UI, by default, injects to the `<head>` of the document color variables that are used across all components. Since the document is not managed by the UI library in the Vue.js SSR, you will need to inject that manually.
15+
16+
17+
You can do that by using `@unhead` in the following way:
18+
19+
::code-group{sync="vite"}
20+
21+
```ts [ssr.ts]
22+
import { createHead, renderSSRHead } from '@unhead/vue/server'
23+
24+
// Create the header with unhead
25+
const head = createHead()
26+
27+
// Render SSR header and append it to the SSR application instance
28+
const payload = await renderSSRHead(head)
29+
app.head.push(payload.headTags)
30+
```
31+
32+
```ts [resources/js/ssr.ts (Laravel Inertia)] {4,14,27,29,30,31,32,33}
33+
import { createInertiaApp } from '@inertiajs/vue3'
34+
import createServer from '@inertiajs/vue3/server'
35+
import ui from '@nuxt/ui/vue-plugin'
36+
import { createHead, renderSSRHead } from '@unhead/vue/server'
37+
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'
38+
import { createSSRApp, DefineComponent, h } from 'vue'
39+
import { renderToString } from 'vue/server-renderer'
40+
import PersistentLayout from './layouts/PersistentLayout.vue'
41+
42+
const appName = import.meta.env.VITE_APP_NAME || 'Laravel x Nuxt UI'
43+
44+
createServer(
45+
(page) => {
46+
const head = createHead()
47+
return createInertiaApp({
48+
page,
49+
render: renderToString,
50+
title: title => (title ? `${title} - ${appName}` : appName),
51+
resolve: (name) =>
52+
resolvePageComponent(
53+
`./pages/${name}.vue`,
54+
import.meta.glob<DefineComponent>('./pages/**/*.vue'),
55+
),
56+
setup: ({ App, props, plugin }) =>
57+
createSSRApp({ render: () => h(App, props) })
58+
.use(plugin)
59+
.use(head)
60+
.use(ui),
61+
}).then(async (app) => {
62+
const payload = await renderSSRHead(head)
63+
app.head.push(payload.headTags)
64+
return app
65+
});
66+
},
67+
{ cluster: true },
68+
)
69+
```
70+
71+
```ts [inertia/app/ssr.ts (AdonisJS Inertia)] {4,14,27,29,30,31,32,33}
72+
import { createInertiaApp } from '@inertiajs/vue3'
73+
import createServer from '@inertiajs/vue3/server'
74+
import ui from '@nuxt/ui/vue-plugin'
75+
import { createHead, renderSSRHead } from '@unhead/vue/server'
76+
import { resolvePageComponent } from '@adonisjs/inertia/helpers'
77+
import { createSSRApp, DefineComponent, h } from 'vue'
78+
import { renderToString } from 'vue/server-renderer'
79+
import PersistentLayout from './layouts/PersistentLayout.vue'
80+
81+
const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS x Nuxt UI'
82+
83+
createServer(
84+
(page) => {
85+
const head = createHead()
86+
return createInertiaApp({
87+
page,
88+
render: renderToString,
89+
title: title => (title ? `${title} - ${appName}` : appName),
90+
resolve: (name) =>
91+
resolvePageComponent(
92+
`../pages/${name}.vue`,
93+
import.meta.glob<DefineComponent>('../pages/**/*.vue'),
94+
),
95+
setup: ({ App, props, plugin }) =>
96+
createSSRApp({ render: () => h(App, props) })
97+
.use(plugin)
98+
.use(head)
99+
.use(ui),
100+
}).then(async (app) => {
101+
const payload = await renderSSRHead(head)
102+
app.head.push(payload.headTags)
103+
return app
104+
});
105+
},
106+
{ cluster: true },
107+
)
108+
```
109+
110+
::
111+
112+
### Color Scheme Detection
113+
114+
The same goes to the color scheme detection. To avoid flashings in the SSR because of the selected color scheme difference, you will need to detect the user's color scheme before the application initialization.
115+
116+
Adding the script below to the `<head>` of your document will detect if the user is using dark theme, and therefore, render the SSR in the dark theme as well.
117+
118+
::code-group{sync="vite"}
119+
120+
```html [index.html]
121+
<script>
122+
const theme = localStorage.getItem('vueuse-color-scheme');
123+
if (theme === 'dark' || (theme === null && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
124+
document.documentElement.classList.add('dark');
125+
} else {
126+
document.documentElement.classList.remove('dark');
127+
}
128+
</script>
129+
```
130+
131+
```html [resources/views/app.blade.php (Laravel Inertia)] {8,9,10,11,12,13,14,15}
132+
<!DOCTYPE html>
133+
<html>
134+
<head>
135+
<meta charset="utf-8" />
136+
<meta name="viewport" content="width=device-width, initial-scale=1">
137+
@inertiaHead
138+
@vite('resources/js/app.ts')
139+
<script>
140+
const theme = localStorage.getItem('vueuse-color-scheme');
141+
if (theme === 'dark' || (theme === null && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
142+
document.documentElement.classList.add('dark');
143+
} else {
144+
document.documentElement.classList.remove('dark');
145+
}
146+
</script>
147+
</head>
148+
<body>
149+
<div class="isolate">
150+
@inertia
151+
</div>
152+
</body>
153+
</html>
154+
```
155+
156+
```html [resources/views/inertia_layout.edge (AdonisJS Inertia)] {8,9,10,11,12,13,14,15}
157+
<!DOCTYPE html>
158+
<html>
159+
<head>
160+
<meta charset="utf-8" />
161+
<meta name="viewport" content="width=device-width, initial-scale=1">
162+
@inertiaHead()
163+
@vite(['inertia/app/app.ts', `inertia/pages/${page.component}.vue`])
164+
<script>
165+
const theme = localStorage.getItem('vueuse-color-scheme');
166+
if (theme === 'dark' || (theme === null && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
167+
document.documentElement.classList.add('dark');
168+
} else {
169+
document.documentElement.classList.remove('dark');
170+
}
171+
</script>
172+
</head>
173+
<body>
174+
@inertia({ class: 'isolate' })
175+
</body>
176+
</html>
177+
```
178+
179+
::
180+
181+
### Icons Display
182+
183+
Unfortunately displaying icons with the SSR server of the Vue.js version is currently not supported. The icons will only be displayed after the application is initialized at the user's end.

0 commit comments

Comments
 (0)