Ao usar o Nitro UI com o framework Nuxt, o SSR do servidor funcionará totalmente por padrão. No entanto, ao usá-lo com Vue puro, você precisará prestar atenção a alguns detalhes para que funcione como esperado.
Por padrão, o Nitro UI injeta no <head> do documento as variáveis de cor usadas por todos os componentes. Como o documento não é gerenciado pela biblioteca de UI no SSR do Vue, você precisará injetá-las manualmente.
Você pode fazer isso usando o @unhead da seguinte forma:
import { createHead, renderSSRHead } from '@unhead/vue/server'
// Create the header with unhead
const head = createHead()
// Render SSR header and append it to the SSR application instance
const payload = await renderSSRHead(head)
app.head.push(payload.headTags)
import { createInertiaApp } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import ui from '@nitro/ui/vue-plugin'
import { createHead, renderSSRHead } from '@unhead/vue/server'
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers'
import { createSSRApp, h } from 'vue'
import { renderToString } from 'vue/server-renderer'
import type { DefineComponent } from 'vue'
const appName = import.meta.env.VITE_APP_NAME || 'Laravel x Nitro UI'
createServer(
(page) => {
const head = createHead()
return createInertiaApp({
page,
render: renderToString,
title: (title) => (title ? `${title} - ${appName}` : appName),
resolve: (name) =>
resolvePageComponent(
`./pages/${name}.vue`,
import.meta.glob<DefineComponent>('./pages/**/*.vue')
),
setup: ({ App, props, plugin }) =>
createSSRApp({ render: () => h(App, props) })
.use(plugin)
.use(head)
.use(ui)
}).then(async (app) => {
const payload = await renderSSRHead(head)
app.head.push(payload.headTags)
return app
})
},
{ cluster: true }
)
import { createInertiaApp } from '@inertiajs/vue3'
import createServer from '@inertiajs/vue3/server'
import ui from '@nitro/ui/vue-plugin'
import { createHead, renderSSRHead } from '@unhead/vue/server'
import { resolvePageComponent } from '@adonisjs/inertia/helpers'
import { createSSRApp, h } from 'vue'
import { renderToString } from 'vue/server-renderer'
import type { DefineComponent } from 'vue'
const appName = import.meta.env.VITE_APP_NAME || 'AdonisJS x Nitro UI'
createServer(
(page) => {
const head = createHead()
return createInertiaApp({
page,
render: renderToString,
title: (title) => (title ? `${title} - ${appName}` : appName),
resolve: (name) =>
resolvePageComponent(
`../pages/${name}.vue`,
import.meta.glob<DefineComponent>('../pages/**/*.vue')
),
setup: ({ App, props, plugin }) =>
createSSRApp({ render: () => h(App, props) })
.use(plugin)
.use(head)
.use(ui)
}).then(async (app) => {
const payload = await renderSSRHead(head)
app.head.push(payload.headTags)
return app
})
},
{ cluster: true }
)
O mesmo vale para a detecção do esquema de cores. Para evitar piscadas no SSR por causa da diferença do esquema de cores selecionado, você precisará detectar o esquema de cores do usuário antes da inicialização da aplicação.
Adicionar o script abaixo ao <head> do seu documento detectará se o usuário está usando o tema escuro e, portanto, renderizará o SSR também no tema escuro.
<script>
const theme = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (theme === 'dark' || (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@inertiaHead
@vite('resources/js/app.ts')
<script>
const theme = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (theme === 'dark' || (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
</head>
<body>
<div class="isolate">
@inertia
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
@inertiaHead()
@vite(['inertia/app/app.ts', `inertia/pages/${page.component}.vue`])
<script>
const theme = localStorage.getItem('vueuse-color-scheme') || 'auto'
if (theme === 'dark' || (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
</script>
</head>
<body>
@inertia({ class: 'isolate' })
</body>
</html>
O Nitro UI empacota os ícones que usa no seu build, então eles são renderizados durante o SSR e funcionam totalmente offline assim que você instala a coleção de ícones localmente, sem nenhuma requisição à API do Iconify. Veja a integração de Ícones para configurar isso e empacotar seus próprios ícones.