Naive UI — это современная Vue 3-библиотека компонентов, ориентированная на легкость кастомизации и полный контроль над стилями. При работе с серверным рендерингом (SSR, Server-Side Rendering) её использование требует внимательного подхода, так как многие UI-компоненты изначально рассчитывают на работу в браузерной среде.
При SSR компоненты Naive UI должны корректно обрабатывать отсутствие
объектов, специфичных для браузера, таких как window,
document или navigator. Некоторые встроенные
элементы библиотеки (например, n-popover,
n-tooltip, n-dialog) используют динамическое
позиционирование, основанное на DOM, и их рендеринг на сервере может
привести к ошибкам.
Рекомендации:
v-if="process.client"
или аналогичными проверками для элементов, зависящих от DOM.Naive UI применяет CSS-in-JS подход, который позволяет динамически генерировать стили компонентов. При SSR важно учитывать:
createTheme и provideTheme на уровне
приложения.useTheme внутри компонента на сервере
должно выполняться с правильным контекстом, иначе могут появляться
предупреждения о несовпадении идентификаторов стилей.Пример инициализации темы для SSR:
import { createApp } from 'vue'
import { createSSRApp } from 'vue'
import { createTheme, NConfigProvider } from 'naive-ui'
const theme = createTheme({
common: {
primaryColor: '#42b983',
}
})
const app = createSSRApp({
setup() {
return () => h(NConfigProvider, { theme }, [h(App)])
}
})
Компоненты с динамическим поведением, такими как
n-dropdown или n-calendar, создают
DOM-элементы и слушатели событий только после монтирования на клиенте.
На сервере они рендерятся в виде статических контейнеров.
Ключевые моменты:
onMounted для инициализации обработчиков
событий.n-modal,
n-popover) указывать контейнер рендеринга через
teleport и проверять наличие document на
сервере.Пример условного использования портала:
<template>
<n-popover v-if="mounted" :to="container">
<template #trigger>
<button>Открыть</button>
</template>
<div>Содержимое Popover</div>
</n-popover>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const mounted = ref(false)
let container
onMounted(() => {
container = document.body
mounted.value = true
})
</script>
При SSR важна корректная гидратация на клиенте. Несовпадение
структуры DOM между сервером и клиентом может вызвать предупреждения
hydration mismatch.
window или
сторонних API, необходимо использовать v-if или отдельный
клиентский рендеринг (client-only).Naive UI оптимизирован для быстрого рендеринга, но при SSR нужно учитывать:
process.client.onMounted.NConfigProvider и createTheme.Этот подход обеспечивает стабильный SSR с Naive UI, предотвращает ошибки на сервере и сохраняет плавное клиентское взаимодействие.