服务器端获取的数据出现,消失并在VUE 3 / NUXT 3生产上重新出现
更新 - 对Google Chrome的性能选项卡的额外见解
,我注意到每当网络请求资产时,元素的消失就会发生。
例如:
- 由于在服务器端
- 客户端加载了徽标徽标徽标
- 徽标消失的
- 客户端已完成徽标
- 徽标重新出现,
但徽标已在那里,尽管客户端启动是预期的行为,我仍然相信,我仍然相信应用程序足够聪明,可以理解徽标资产与服务器端相同。我有机会避免这种消失的内容吗?
在我的NUXT 3/VUE 3 SSR项目中介绍
,我有一个server/api/prismic.js
文件,可以从Prismic(无头CMS)中获取我们的应用程序内容。
然后,在我们的页面/[... uid] .vue
文件中,我获取数据并渲染切片。 这神奇地起作用;就像在网站中一样,加载迅速。
但是..问题在于,在我们的动态页面完成加载之前,我会立即出现故障。因此,我将获得以下内容:
- 页面加载
- 页面立即包含带有内容
- 页面的组件消失的
- 页面再次出现在相同的数据中出现,
不幸的是 没有工作:仅在服务器端获取数据。因为那时我最终有一个空白页。
该问题确实 在localhost上发生:3000
用YARN BUILD& amp;测试。纱线开始
,但仅在Heroku上的部署版本上。
我知道这个问题可能是因为客户正在开始,但是我仍然想知道是否有人可以帮助或指导我问题。这是NUXT 3问题吗?还是特定于vue-router
的东西?
我在应用程序级别上发现的内容
,我还从api/prismic
端点获取以获取导航和页脚内容。我注意到导航和页脚也出现,消失并重新出现。使用导航&页脚参考
仍然包含相同的内容。
这消除了我的一些理论,例如将对象传递给我的动态组件的事实是罪魁祸首。
代码
app.vue
<template>
<div id="wrapper">
<Navigation :nav="navigation" />
<main id="page">
<NuxtPage :key="$route.path" />
</main>
<Footer :footer="footer" />
</div>
</template>
<script setup>
const { data: navigation } = await useFetch(
'/api/prismic?type=single&uid=header',
{ key: 'header' },
)
const { data: footer } = await useFetch(
'/api/prismic?type=single&uid=footer',
{ key: 'footer' },
)
</script>
server/api/prismic.js
export default defineEventHandler(async (event) => {
const query = useQuery(event)
const { repo, type, uid } = query
const qTypes = {
id: 'document.id',
page: 'my.page.uid',
single: 'document.type',
}
const { access_token, endpoint } = import.meta.env
let params = { access_token }
const prismicRef = await $fetch(endpoint, { params })
params.ref = prismicRef.refs[0].ref
params.q = `[[at(${qTypes[type] || 'document.id'}, "${uid}")]]`
const document = await $fetch(`${endpoint}/documents/search`, { params })
if (document.results && document.results.length > 0) {
return document.results[0].data
}
return null
})
pages/[... uid] .vue
<template>
<div id="slices">
<component
v-for="(slice, index) in page.body"
:is="slice.slice_type"
:key="`${$route.path}-${index}`"
:slice="slice"
/>
</div>
</template>
<script setup>
definePageMeta({ middleware: ['default'], pageTransition: { name: 'fade' } })
const route = useRoute()
const uid = ref(route.params.uid[0] || 'home')
const { data: page } = await useFetch(
`/api/prismic?type=page&uid=${uid.value}`,
{ key: uid.value },
)
</script>
Update - extra insights
Looking into the performance tab of Google Chrome, I noticed that the disappearing of elements happen whenever the network is requesting an asset.
For example:
- The logo is there due to being loaded on server side
- Client side fetches the logo asset
- Logo disappears
- Client side has finished fetching the logo
- Logo re-appears
Although the client-side kicking in is expected behavior, I would still believe that the app would be smart enough to understand the logo asset is the same as the server side. Any chance I can avoid this disappearing of the content?
Intro
In my Nuxt 3 / Vue 3 SSR project, I have a server/api/prismic.js
file that fetches our application content from Prismic (Headless CMS).
Then, in our pages/[...uid].vue
file, I fetch that data and render the slices.
This works magically; as in the website loads blazing fast.
However.. the problem is that I'm getting a glitch right before our dynamic page is finished loading. So I get the following:
- Page loads
- Page immediately contains components loaded with content
- Page disappears
- Page appears again with the same data
What unfortunately doesn't work: only fetching the data on a server-side. Because then I end up having a blank page.
The issue does not happen on localhost:3000
tested with yarn build && yarn start
, but only on the deployed version on Heroku.
I'm aware this issue is probably because the client is kicking in, but I was still wondering if anyone could help or guide me what the issue might be. Is this a Nuxt 3 issue? Or maybe something specific to vue-router
?
What I discovered
On app level, I also fetch from my api/prismic
endpoint to fetch the navigation and footer content. I noticed that the navigation and footer also appear, disappear and re-appear; with the navigation & footer ref
both still containing the same content content.
This removes a few theories that I had, such as the fact that passing an object to my dynamic component is the culprit.
Code
app.vue
<template>
<div id="wrapper">
<Navigation :nav="navigation" />
<main id="page">
<NuxtPage :key="$route.path" />
</main>
<Footer :footer="footer" />
</div>
</template>
<script setup>
const { data: navigation } = await useFetch(
'/api/prismic?type=single&uid=header',
{ key: 'header' },
)
const { data: footer } = await useFetch(
'/api/prismic?type=single&uid=footer',
{ key: 'footer' },
)
</script>
server/api/prismic.js
export default defineEventHandler(async (event) => {
const query = useQuery(event)
const { repo, type, uid } = query
const qTypes = {
id: 'document.id',
page: 'my.page.uid',
single: 'document.type',
}
const { access_token, endpoint } = import.meta.env
let params = { access_token }
const prismicRef = await $fetch(endpoint, { params })
params.ref = prismicRef.refs[0].ref
params.q = `[[at(${qTypes[type] || 'document.id'}, "${uid}")]]`
const document = await $fetch(`${endpoint}/documents/search`, { params })
if (document.results && document.results.length > 0) {
return document.results[0].data
}
return null
})
pages/[...uid].vue
<template>
<div id="slices">
<component
v-for="(slice, index) in page.body"
:is="slice.slice_type"
:key="`${$route.path}-${index}`"
:slice="slice"
/>
</div>
</template>
<script setup>
definePageMeta({ middleware: ['default'], pageTransition: { name: 'fade' } })
const route = useRoute()
const uid = ref(route.params.uid[0] || 'home')
const { data: page } = await useFetch(
`/api/prismic?type=page&uid=${uid.value}`,
{ key: uid.value },
)
</script>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最终解决了这个问题;这里有一些背景:
在我最初的问题和此答案之间的时间里,我已经移至使用NUXT SSG而不是SSR,并遇到了完全相同的问题。
在与NUXT 3玩了很多时,我终于能够找到真正的罪魁祸首:Cloudflare。
最终是CF在HTML代码上的缩小。 CF正在删除Vue的评论片段,例如
&lt;! - ] - &gt;
,显然使Vue 3不需要单个根元素。由于这些片段在缩小过程中被删除,因此该应用程序没有应有的反应。
在使用此解决方案之前,我已经发布了 nuxt 3的repo ,哪个问题包含有关该问题的完整解释。
Finally resolved the issue; here's some background:
In the time between my initial question and this answer, I already moved to using Nuxt SSG instead of SSR and encountered the exact same problem.
After a lot of playing around with Nuxt 3, I finally was able to find the real culprit: CloudFlare.
It ended up being CF's minification on the HTML code. CF was removing Vue's comment fragments such as
<!--]-->
, which apparently enables Vue 3 not to require a single root element.Since those fragments got removed during minification, the app didn't react as it should've.
Before coming with this solution, I had already posted an issue on Nuxt 3's repo, which contains full explanation on the issue.