Skip to content

Commit e61657e

Browse files
authored
fix: improve conditions for missed payload case (#1648)
1 parent 699868d commit e61657e

File tree

2 files changed

+25
-16
lines changed

2 files changed

+25
-16
lines changed

app/pages/package/[[org]]/[name].vue

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,15 @@ const { data: readmeData } = useLazyFetch<ReadmeResponse>(
106106
const version = requestedVersion.value
107107
return version ? `${base}/v/${version}` : base
108108
},
109-
{ default: () => ({ html: '', mdExists: false, playgroundLinks: [], toc: [] }) },
109+
{
110+
default: () => ({
111+
html: '',
112+
mdExists: false,
113+
playgroundLinks: [],
114+
toc: [],
115+
defaultValue: true,
116+
}),
117+
},
110118
)
111119
112120
const playgroundLinks = computed(() => [
@@ -259,18 +267,19 @@ const nuxtApp = useNuxtApp()
259267
const route = useRoute()
260268
const hasEmptyPayload =
261269
import.meta.client &&
262-
nuxtApp.isHydrating &&
263270
nuxtApp.payload.serverRendered &&
264271
!Object.keys(nuxtApp.payload.data ?? {}).length
265-
const isSpaFallback = shallowRef(hasEmptyPayload && !nuxtApp.payload.path)
272+
const isSpaFallback = shallowRef(nuxtApp.isHydrating && hasEmptyPayload && !nuxtApp.payload.path)
266273
const isHydratingWithServerContent = shallowRef(
267-
hasEmptyPayload && nuxtApp.payload.path === route.path,
274+
nuxtApp.isHydrating && hasEmptyPayload && nuxtApp.payload.path === route.path,
268275
)
276+
const hasServerContentOnly = shallowRef(hasEmptyPayload && nuxtApp.payload.path === route.path)
277+
269278
// When we have server-rendered content but no payload data, capture the server
270279
// DOM before Vue's hydration replaces it. This lets us show the server-rendered
271280
// HTML as a static snapshot while data refetches, avoiding any visual flash.
272281
const serverRenderedHtml = shallowRef<string | null>(
273-
isHydratingWithServerContent.value
282+
hasServerContentOnly.value
274283
? (document.getElementById('package-article')?.innerHTML ?? null)
275284
: null,
276285
)
@@ -279,7 +288,6 @@ if (isSpaFallback.value || isHydratingWithServerContent.value) {
279288
nuxtApp.hooks.hookOnce('app:suspense:resolve', () => {
280289
isSpaFallback.value = false
281290
isHydratingWithServerContent.value = false
282-
serverRenderedHtml.value = null
283291
})
284292
}
285293
@@ -733,27 +741,26 @@ const showSkeleton = shallowRef(false)
733741
<!-- Scenario 1: SPA fallback — show skeleton (no real content to preserve) -->
734742
<!-- Scenario 2: SSR with missing payload — preserve server DOM, skip skeleton -->
735743
<PackageSkeleton
736-
v-if="
737-
isSpaFallback || (!isHydratingWithServerContent && (showSkeleton || status === 'pending'))
738-
"
744+
v-if="isSpaFallback || (!hasServerContentOnly && (showSkeleton || status === 'pending'))"
739745
/>
740746

741747
<!-- During hydration without payload, show captured server HTML as a static snapshot.
742748
This avoids a visual flash: the user sees the server content while data refetches.
743749
v-html is safe here: the content originates from the server's own SSR output,
744-
captured from the DOM before hydration — it is not user-controlled input. -->
750+
captured from the DOM before hydration — it is not user-controlled input.
751+
We also show SSR output until critical data is loaded, so that after rendering dynamic
752+
content, the user receives the same result as he received from the server-->
745753
<article
746-
v-else-if="isHydratingWithServerContent && serverRenderedHtml"
754+
v-else-if="
755+
isHydratingWithServerContent ||
756+
(hasServerContentOnly && serverRenderedHtml && (!pkg || readmeData?.defaultValue))
757+
"
747758
id="package-article"
748759
:class="$style.packagePage"
749760
v-html="serverRenderedHtml"
750761
/>
751762

752-
<article
753-
v-else-if="status === 'success' && pkg"
754-
id="package-article"
755-
:class="$style.packagePage"
756-
>
763+
<article v-else-if="pkg" id="package-article" :class="$style.packagePage">
757764
<!-- Package header -->
758765
<header
759766
class="sticky top-14 z-1 bg-[--bg] py-2 border-border"

shared/types/readme.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export interface TocItem {
2828
* Response from README API endpoint
2929
*/
3030
export interface ReadmeResponse {
31+
/** Whether the response is the default value */
32+
defaultValue?: boolean
3133
/** Whether the README exists */
3234
mdExists?: boolean
3335
/** Rendered HTML content */

0 commit comments

Comments
 (0)