Рендеринг на стороне сервера (SSR)
Совет
Если вы используете Nuxt.js, то вместо этого необходимо прочитать эти инструкции.
Создание хранилищ с помощью Pinia должно работать из коробки для SSR, если вы вызываете свои функции useStore() в верхней части функций setup, getters и actions:
<script setup>
// это работает, потому что pinia знает, какое приложение
// запущено внутри `setup`
const main = useMainStore()
</script>Использование хранилища за пределами setup()
Если необходимо использовать хранилище в другом месте, то в вызов функции useStore() необходимо передать экземпляр pinia, который был передан приложению:
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
router.beforeEach((to) => {
// ✅ Это будет работать, если убедиться, что используется правильное хранилище для
// текущего запущенного приложения
const main = useMainStore(pinia)
if (to.meta.requiresAuth && !main.isLoggedIn) return '/login'
})Pinia удобно добавляет себя как $$piniaв ваше приложение, так что вы можете использовать его в таких функциях, какserverPrefetch():
export default {
serverPrefetch() {
const store = useStore(this.$pinia)
},
}Обратите внимание, что при использовании onServerPrefetch() ничего особенного делать не нужно:
<script setup>
const store = useStore()
onServerPrefetch(async () => {
// ✅ это работает
await store.fetchData()
})
</script>Гидратация состояния
Чтобы гидратировать начальное состояние, вам нужно убедиться, что rootState вставлено где-то в HTML, чтобы Pinia могла его позже обнаружить. В зависимости от того, что вы используете для SSR, вам необходимо экранировать состояние по соображениям безопасности. Мы рекомендуем использовать @nuxt/devalue, который используется в Nuxt.js:
import devalue from '@nuxt/devalue'
import { createPinia } from 'pinia'
// получение значения rootState на стороне сервера
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
// после рендеринга страницы, корневое состояние построено и может быть прочитано
// непосредственно из `pinia.state.value`.
// сериализовать, экранировать (ОЧЕНЬ важно, если содержимое состояния может быть изменено
// пользователем, а это почти всегда так), и поместить его куда-нибудь на
// странице, например, в качестве глобальной переменной.
devalue(pinia.state.value)В зависимости от того, что вы используете для SSR, вы установите переменную начального состояния, которая будет сериализована в HTML. Также вам следует защититься от атак XSS. Вы можете использовать другие альтернативы вместо @nuxt/devalue в зависимости от ваших потребностей, например, если вы можете сериализовать и десереализировать состояние с помощью JSON.stringify()/JSON.parse(), то можно существенно улучшить производительность.
Если вы не используете Nuxt, вам придется самостоятельно обрабатывать сериализацию и гидратацию состояния. Вот несколько примеров:
Адаптируйте эту стратегию под свою среду выполнения. Убедитесь, что вы восстанавливаете состояние Pinia перед вызовом функции useStore() на стороне клиента. Например, если мы сериализуем состояние в тег <script>, чтобы сделать его доступным глобально на клиентской стороне через window.__pinia, мы можем написать следующее:"
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
// `isClient` зависит от среды выполнения, например, в Nuxt это `import.meta.client`
if (isClient) {
pinia.state.value = JSON.parse(window.__pinia)
}