You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When doing SSR (Server Side Rendering) you want to wait for the data on the server to serialize it and retrieve it on the client side where it will displayed
3
+
:::tip
4
+
If you are using Nuxt.js, read the [Nuxt guide](./nuxt.md) instead, most of the things are already configured for you.
5
+
:::
4
6
5
-
## Vue 3 + Suspense
7
+
When doing SSR (Server Side Rendering) you want to wait for the data on the server to serialize it and retrieve it on the client side where it will displayed. VueFire already waits for the data for you if you use the composables within components:
6
8
7
-
By serializing the data on the server (using a store like [Pinia](https://pinia.vuejs.org) for example) and `await`ing the returned `promise` of `useDocument()` you can ensure your data is loaded when rendering the page on the server and hydrating on the client.
Make sure your component is the descendant of [`<Suspense>`](https://vuejs.org/guide/built-ins/suspense.html) in order to use `await` within `<script setup>`.
19
-
:::
22
+
```vue
23
+
<script setup>
24
+
import { doc, getDoc } from 'firebase/firestore'
25
+
import { useDocument, useFirestore } from 'vuefire'
26
+
27
+
const db = useFirestore()
28
+
// automatically waits for the data to be loaded on the server
You only need to escape and serialize the data to the client and handle state hydration. This depends on what you are using to do SSR but should look similar to this example using [the Vitesse template](https://github.com/antfu/vitesse):
// on the server we ensure all the data is retrieved in this object
57
+
initialState.vuefire=useSSRInitialState()
58
+
}
59
+
}
60
+
```
61
+
62
+
Note that by default, vite-ssg (used by Vitesse) uses `JSON.stringify()` to serialize the state, which is faster but doesn't support some values like `Date` objects and also exposes your application to some attacks **if your data comes from the user**. You can use a custom `transformState` function to handle this:
63
+
64
+
```ts
65
+
// src/main.ts
66
+
importdevaluefrom'@nuxt/devalue'
67
+
import { ViteSSG } from'vite-ssg'
68
+
importAppfrom'./App.vue'
69
+
70
+
exportconst createApp =ViteSSG(
71
+
App,
72
+
{ routes },
73
+
({ app, router, initialState }) => {
74
+
// ...
75
+
},
76
+
{
77
+
transformState(state) {
78
+
returnimport.meta.env.SSR?devalue(state) :state
79
+
},
80
+
},
81
+
)
82
+
```
83
+
84
+
Web Security is a broad topic that we cannot cover here. We recommend you te read these resources to dive deeper:
85
+
86
+
-[State Serialization in vite-ssg](https://github.com/antfu/vite-ssg#state-serialization)
87
+
-[SSR Best practices for Vue.js](https://vuejs.org/guide/best-practices/security.html#server-side-rendering-ssr)
88
+
89
+
## Usage outside of components
90
+
91
+
If you are using VueFire composables outside of components, e.g. using `useDocument()` within a [Pinia](https://pinia.vuejs.org) store, you need to manually wait for the data to be loaded on the server as VueFire cannot call `onServerPrefetch()` for you. This means you also need to [use `<Suspense>`](https://vuejs.org/guide/built-ins/suspense.html#suspense) to be able to use `await` within `setup()`. VueFire exposes a function to retrieve all pending promises created by the different composables (`useDocument()`, `useObject()`, etc). Await it inside of **any component that uses the data**:
92
+
93
+
```vue
94
+
<script setup>
95
+
import { useQuizStore } from '~/stores/quiz'
96
+
import { usePendingPromises } from 'vuefire'
97
+
98
+
// this store internally calls `useDocument()` when created
99
+
const quizStore = useQuizStore()
100
+
101
+
// since `useDocument()` has been called
102
+
await usePendingPromises()
103
+
</script>
104
+
```
105
+
106
+
## Exclude from hydration
107
+
108
+
You can exclude data from hydration by passing `false` to the `ssrKey` option:
109
+
110
+
```ts
111
+
useDocument(..., { ssrKey: false })
112
+
useList(..., { ssrKey: false })
113
+
// etc
114
+
```
115
+
116
+
<!-- TODO: I wonder if we could attach effect scopes to applications so `onServerPrefetch()` is still awaited when attached -->
117
+
118
+
<!--
20
119
21
120
## Vue Router Data Loaders
22
121
@@ -26,6 +125,7 @@ Get the data once only on server
0 commit comments