Skip to content

Commit

Permalink
feat: improve vue-query example to show maximum rendering time on SSR v…
Browse files Browse the repository at this point in the history
  • Loading branch information
pdanpdan committed Jun 7, 2024
1 parent 0c95334 commit 63a7ef5
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 50 deletions.
54 changes: 5 additions & 49 deletions examples/vue-query/pages/index/+Page.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
<template>
<h1>Star Wars Movies</h1>
<ol>
<template v-if="isPending">
<li>Loading...</li>
</template>
<template v-else-if="isError">
<li>Error: {{ error }}</li>
</template>
<template v-else>
<li v-for="item in data!" :key="item.id">
{{ item.title }} ({{ item.release_date }})
</li>
</template>
</ol>
<p>Source: <a href="https://brillout.github.io/star-wars">brillout.github.io/star-wars</a>.</p>
<p>
While initial data is fetched on the server, the client will refresh after rendering.<br>
<code>
Refreshing: {{ isFetching ? 'Yes' : 'No' }}
</code>
</p>
<!-- put the suspensible components in Suspense -->
<Suspense>
<MoviesList />
</Suspense>
<p>
This page is:
</p>
Expand All @@ -30,34 +14,6 @@
</template>

<script lang="ts" setup>
import { onServerPrefetch } from 'vue'
import type { Movie, MovieDetails } from './types'
import { useQuery } from '@tanstack/vue-query'
import Counter from '../../components/Counter.vue'
const components = { Counter }
const { isError, isPending, isFetching, data, error, suspense } = useQuery({
queryKey: ['movies'],
queryFn: fetchMovies,
select: (data) => minimize(data),
})
// this will be called on the server to prefetch the data
onServerPrefetch(suspense)
async function fetchMovies() {
const response = await fetch('https://brillout.github.io/star-wars/api/films.json')
const moviesData = (await response.json()) as MovieDetails[]
// simulate slow network on client
await new Promise((resolve) => setTimeout(resolve, import.meta.env.SSR ? 0 : 3000))
return moviesData
}
function minimize(movies: MovieDetails[]): Movie[] {
return movies.map((movie) => {
const { title, release_date, id } = movie
return { title, release_date, id }
})
}
import MoviesList from './MoviesList.vue'
</script>
64 changes: 64 additions & 0 deletions examples/vue-query/pages/index/MoviesList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<template v-if="isPending">
<p>Loading...</p>
</template>
<template v-else-if="isError">
<p>Error: {{ error }}</p>
</template>
<ol v-else>
<li v-for="item in data!" :key="item.id">
{{ item.title }} ({{ item.release_date }})
</li>
</ol>
<p>Source: <a href="https://brillout.github.io/star-wars">brillout.github.io/star-wars</a>.</p>
<p>
While initial data is fetched on the server, the client will refresh after rendering.<br>
<code>
Refreshing: {{ isFetching ? 'Yes' : 'No' }}
</code>
</p>
</template>

<script lang="ts" setup>
import type { Movie, MovieDetails } from './types'
import { useQuery } from '@tanstack/vue-query'
const ALLOWED_SSR_DELAY = 300
const { isError, isPending, isFetching, data, error, suspense } = useQuery({
queryKey: ['movies'],
queryFn: fetchMovies,
select: (data) => minimize(data),
staleTime: 3000
})
// await for `useQuery`'s `suspense` but only as much as you want to wait on SSR
await new Promise(async (resolve) => {
setTimeout(() => {
resolve(false)
}, ALLOWED_SSR_DELAY)
await suspense()
resolve(true)
})
async function fetchMovies() {
const delay = Math.ceil(import.meta.env.SSR ? 2 * ALLOWED_SSR_DELAY * Math.random() : 500 + 3000 * Math.random())
console.log(`[${ import.meta.env.SSR ? 'SERVER' : 'CLIENT' }] Fetch movies network delay: ${ delay }${ import.meta.env.SSR && delay < ALLOWED_SSR_DELAY ? ' - PREFETCH' : ''}`)
const tsStart = Date.now()
const response = await fetch('https://brillout.github.io/star-wars/api/films.json')
const moviesData = (await response.json()) as MovieDetails[]
// simulate slow network on client
await new Promise((resolve) => setTimeout(resolve, Math.max(0, delay - Date.now() + tsStart)))
return moviesData;
}
function minimize(movies: MovieDetails[]): Movie[] {
return movies.map((movie) => {
const { title, release_date, id } = movie
return { title, release_date, id }
})
}
</script>
2 changes: 1 addition & 1 deletion examples/vue-query/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"strict": true,
"module": "ES2020",
"module": "ES2022",
"moduleResolution": "Node",
"target": "ES2020",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
Expand Down

0 comments on commit 63a7ef5

Please sign in to comment.