服务器端渲染 (SSR)
提示
如果您使用的是 **Nuxt.js**,您需要阅读 这些说明。
只要您在 setup
函数、getter
和 action
的顶部调用 useStore()
函数,使用 Pinia 创建 Store 应该在 SSR 中开箱即用。
<script setup>
// this works because pinia knows what application is running inside of
// `setup`
const main = useMainStore()
</script>
在 setup()
之外使用 Store
如果您需要在其他地方使用 Store,您需要将传递给应用程序的 pinia
实例 传递给应用程序 传递给 useStore()
函数调用。
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
router.beforeEach((to) => {
// ✅ This will work make sure the correct store is used for the
// current running app
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 () => {
// ✅ this will work
await store.fetchData()
})
</script>
状态水合
要使初始状态水合,您需要确保根状态包含在 HTML 中的某个位置,以便 Pinia 稍后可以获取它。根据您用于 SSR 的内容,**您应该出于安全原因对状态进行转义**。我们建议使用 @nuxt/devalue,这是 Nuxt.js 使用的。
import devalue from '@nuxt/devalue'
import { createPinia } from 'pinia'
// retrieve the rootState server side
const pinia = createPinia()
const app = createApp(App)
app.use(router)
app.use(pinia)
// after rendering the page, the root state is built and can be read directly
// on `pinia.state.value`.
// serialize, escape (VERY important if the content of the state can be changed
// by the user, which is almost always the case), and place it somewhere on
// the page, for example, as a global variable.
devalue(pinia.state.value)
根据您用于 SSR 的内容,您将设置一个 *初始状态* 变量,该变量将在 HTML 中序列化。您还应该保护自己免受 XSS 攻击。您可以使用 其他替代方案 来代替 @nuxt/devalue
,具体取决于您的需求,例如,如果您可以使用 JSON.stringify()
/JSON.parse()
序列化和解析您的状态,**您可以大幅提高性能**。
如果您没有使用 Nuxt,您将需要自己处理状态的序列化和水合。以下是一些示例
将此策略调整到您的环境。**确保在客户端调用任何 useStore()
函数之前使 Pinia 的状态水合**。例如,如果我们将状态序列化到 <script>
标签中,使其通过 window.__pinia
在客户端全局可用,我们可以这样写
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
// `isClient` depends on the environment, e.g. on Nuxt it's `import.meta.client`
if (isClient) {
pinia.state.value = JSON.parse(window.__pinia)
}