感谢@three的评论让我找到了答案。
如果路由或_layout
组件导出preload()
,它总是在导航时被调用。所以我最终通过将获取的数据存储在第二个参数 to 中来做到preload()
这一点,这通常被称为session
并且似乎在所有组件之间共享。而且我只this.fetch()
在数据不存在时才打电话。
<!-- blog/index.svelte -->
<script context="module">
export async function preload (page, session) {
let {posts} = session;
if (undefined === posts) {
const response = await this.fetch('blog/posts.json');
posts = await response.json();
session.posts = posts
}
return {posts}
}
</script>
<script>
export let posts;
</script>
{#each posts as post}
<!-- ... -->
{/each}
然后[slug].svelte
检查session.posts
您要查找的帖子,如果不存在,请加载它。
<!-- blog/[slug].svelte -->
<script context="module">
export async function preload (page, session) {
const {slug} = page.params
const {posts} = session
let post
if (undefined === posts) {
const response = await this.fetch(`blog/${slug}.json`)
post = await response.json()
} else {
post = posts.find(p => p.slug === slug)
}
if (undefined === post) {
this.error(404, "Sorry we couldn\'t find that post")
}
return {post}
}
</script>
<script>
export let post
</script>
<!-- ... render post -->
现在导航是即时的。为了获得最终的稳健性,如果数据过时(比如超过 5 分钟,无论如何),您可以添加检查以重新加载。
编辑
本质上,您实际上并不需要使用会话。如果您只想使session
参数preload(page, session)
不是,undefined
您可以在以下位置使用它server.js
:
sapper.middleware({
// Define session parameter as an empty object
session: (req, res) => ({})
})