Sapper中动态路由页面为什么在客户端首次加载时显示空白?

小斯羽 阅读 21

折腾了一下午也没解决,我在Sapper的动态路由里写了一个博客详情页,服务器端渲染正常,但直接访问客户端时页面内容全白。

代码是这样的:


<!-- routes/_posts/[slug].svelte -->
<script context="module">
  export async function load({ params }) {
    const post = await fetch(<code>api/posts/${params.slug}</code>).then(res => res.json())
    return { props: { post } }
  }
</script>

<script>
  export let post;
</script>

<h1>{post.title}</h1>
<p>{post.content}</p>

检查了网络请求发现客户端没有触发API调用,控制台也没报错。预渲染时页面能正确显示,但直接访问客户端URL就空白。尝试过加key属性和强制更新都没用,求大神指点!

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
司徒德丽
这个问题的核心是Sapper的动态路由在客户端首次加载时,服务端返回的JSON数据没有正确处理。直接用这个方案:

<script context="module">
export async function preload({ params }, { session }) {
const res = await this.fetch(<code>api/posts/${params.slug}</code>)
const post = await res.json()

if (res.status === 200) {
return { post }
} else {
this.error(res.status, 'Post not found')
}
}
</script>

<script>
export let post
</script>

{#if post}
<h1>{post.title}</h1>
<p>{post.content}</p>
{:else}
<p>Loading...</p>
{/if}


几点说明:第一,要用preload而不是load,这是Sapper的生命周期钩子,专门处理页面加载前的数据获取。第二,记得加条件渲染,防止数据未加载完成时报错。第三,用this.fetch替代原生fetch,它能保证服务端和客户端请求的一致性。

最后提醒一句,检查下你的api/posts/[slug]接口是不是同时支持GET请求,有时候只写了POST就会出问题。我之前就踩过这坑,调试了一晚上。
点赞 2
2026-02-14 15:13