服务端渲染 (SSR)

TIP

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

使用Pinia创建stores对于SSR来说应该是开箱即用的,只要您在setup函数,gettersactions的顶部调用您的useStore()函数:

  1. export default defineComponent({
  2. setup() {
  3. // this works because pinia knows what application is running inside of
  4. // `setup()`
  5. const main = useMainStore()
  6. return { main }
  7. },
  8. })

不在 setup() 中使用 store

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

  1. const pinia = createPinia()
  2. const app = createApp(App)
  3. app.use(router)
  4. app.use(pinia)
  5. router.beforeEach((to) => {
  6. // ✅ This will work make sure the correct store is used for the
  7. // current running app
  8. const main = useMainStore(pinia)
  9. if (to.meta.requiresAuth && !main.isLoggedIn) return '/login'
  10. })

Pinia方便地将自己作为$Pinia添加到你的应用程序中,因此您可以在像serverPrefetch()这样的函数中使用它:

  1. export default {
  2. serverPrefetch() {
  3. const store = useStore(this.$pinia)
  4. },
  5. }

状态激活

为了激活初始状态,您需要确保在HTML的某个地方包含了rootState,以便Pinia以后可以获取它。根据您用于SSR的内容,出于安全原因,您应该转义该状态。我们建议使用Nuxt.js@nuxt/devalue 插件:

  1. import devalue from '@nuxt/devalue'
  2. import { createPinia } from 'pinia'
  3. // retrieve the rootState server side
  4. const pinia = createPinia()
  5. const app = createApp(App)
  6. app.use(router)
  7. app.use(pinia)
  8. // after rendering the page, the root state is build and can be read directly
  9. // on `pinia.state.value`.
  10. // serialize, escape (VERY important if the content of the state can be changed
  11. // by the user, which is almost always the case), and place it somewhere on
  12. // the page, for example, as a global variable.
  13. devalue(pinia.state.value)

根据您SSR使用的内容,您将设置一个将在HTML序列化的初始状态变量。您还应该保护自己免受XSS攻击。例如,使用vite-ssr库您就可以使用transformState方法@nuxt/devalue插件:

  1. import devalue from '@nuxt/devalue'
  2. export default viteSSR(
  3. App,
  4. {
  5. routes,
  6. transformState(state) {
  7. return import.meta.env.SSR ? devalue(state) : state
  8. },
  9. },
  10. ({ initialState }) => {
  11. // ...
  12. if (import.meta.env.SSR) {
  13. // this will be stringified and set to window.__INITIAL_STATE__
  14. initialState.pinia = pinia.state.value
  15. } else {
  16. // on the client side, we restore the state
  17. pinia.state.value = initialState.pinia
  18. }
  19. }
  20. )

您可以根据需要,使用其他替代@nuxt/devalue的方法,例如,如果您可以使用JSON.stringify()/JSON.parse()序列化和解析您的状态,则可以大大提高您的性能。

让这个策略适应您的环境。在客户端调用任何useStore()函数之前,请确保pinia的状态激活。例如,如果我们将状态序列化为一个<script>标签,并使其可以在客户端通过window.__pinia全局访问,我们可以这样写:

  1. const pinia = createPinia()
  2. const app = createApp(App)
  3. app.use(pinia)
  4. // must be set by the user
  5. if (isClient) {
  6. pinia.state.value = JSON.parse(window.__pinia)
  7. }