跳至内容

服务器端渲染 (SSR)

提示

如果您使用的是 **Nuxt.js**,您需要阅读 这些说明

只要您在 setup 函数、getteraction 的顶部调用 useStore() 函数,使用 Pinia 创建 Store 应该在 SSR 中开箱即用。

vue
<script setup>
// this works because pinia knows what application is running inside of
// `setup`
const main = useMainStore()
</script>

setup() 之外使用 Store

如果您需要在其他地方使用 Store,您需要将传递给应用程序的 pinia 实例 传递给应用程序 传递给 useStore() 函数调用。

js
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() 等函数中使用它。

js
export default {
  serverPrefetch() {
    const store = useStore(this.$pinia)
  },
}

请注意,在使用 onServerPrefetch() 时,您无需执行任何特殊操作。

vue
<script setup>
const store = useStore()
onServerPrefetch(async () => {
  // ✅ this will work
  await store.fetchData()
})
</script>

状态水合

要使初始状态水合,您需要确保根状态包含在 HTML 中的某个位置,以便 Pinia 稍后可以获取它。根据您用于 SSR 的内容,**您应该出于安全原因对状态进行转义**。我们建议使用 @nuxt/devalue,这是 Nuxt.js 使用的。

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 在客户端全局可用,我们可以这样写

ts
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)
}