SSR
Nuxt UI 原生支持 Vue SSR。本指南将帮助你完全启用该功能。
使用
当与 Nuxt 框架一起使用 Nuxt UI 时,SSR 服务器可以开箱即用地完全工作。但是,当与纯 Vue 一起使用时,你需要关注一些细节,以使其按预期运行。
颜色变量注入
Nuxt UI 默认会向文档的 <head> 注入所有组件使用的颜色变量。在 Vue SSR 中,文档不是由 UI 库管理的,因此你需要手动注入这些变量。
你可以通过以下方式使用 @unhead 完成注入:
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 '@nuxt/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 Nuxt 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 '@nuxt/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 Nuxt 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 }
)
颜色方案检测
颜色方案检测也是如此。为避免 SSR 中因所选颜色方案差异导致的闪烁,你需要在应用初始化之前检测用户的颜色方案。
将下面的脚本添加到文档的 <head> 中,可以检测用户是否使用深色主题,并相应地在 SSR 中也以深色主题渲染。
<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>
图标显示
Nuxt UI 会将其使用的图标打包到你的构建中,因此一旦你在本地安装图标集合,它们就会在 SSR 期间渲染并完全离线工作,无需请求 Iconify API。请参阅 图标 集成来设置此功能并打包你自己的图标。