首页 > 解决方案 > Sveltekit 和 SSR

问题描述

在 sveltekit 的上下文中,我需要一些帮助来理解 SSR。我注意到该load方法在服务器和客户端上都被调用,我无法解决这个问题。我想它需要初始化客户端组件的状态,但为什么不将 SSR 产生的道具传递给客户端呢?

如果在 SSR 期间需要完成数据库请求怎么办?现在从客户端重复相同的数据库请求?如果这甚至不可能呢?我知道我可以使用browserfrom$app/env在服务器和浏览器上运行不同的代码,但是我返回什么道具?有没有办法将数据从服务器端调用load传递到客户端调用?

标签: server-side-renderingsveltesveltekit

解决方案


为什么不把 SSR 产生的 props 传递给客户端呢?

为此,道具需要可序列化。你不能——例如——做这样的事情:

<script context="module">
  export async function load({ fetch }) {
    const data = await fetch('/data.json').then(r => r.json());
    const model = create_model(data);

    return {
      props: { model }
    };
  }
</script>

<script>
  export let model;
</script>

<h1>{$model.title}</h1>

或者您可能需要在一种情况下动态导入一个组件,在另一种情况下动态导入不同的组件,并将其作为道具传递。

序列化输出还有另一个缺点load(SvelteKit 的前身 Sapper 就是这种情况)——在某些情况下,您最终可能会序列化比您需要的更多的数据:

<script context="module">
  export async function load({ fetch }) {
    const compressed = await fetch('/compressed-data.json').then(r => r.json());
    const data = decompress(compressed);

    return {
      props: { data }
    };
  }
</script>

所以 SvelteKitload在服务器和客户端上运行。但这并不意味着您正在发出不必要的网络请求。fetch您在函数中的任何内容都load被烘焙到服务器渲染的 HTML 中,这意味着 a)所有内容都包含在一个请求中,b)用于服务器和客户端渲染的数据保证是一致的,以及 c)出现在获取的任何字符串由于 gzip(或 brotli),数据和出现在标记中的数据基本上是“免费的”。

如果在 SSR 期间需要完成数据库请求怎么办?

您不应该直接与 中的数据库对话load,您应该创建一个端点并使用fetch. (我们将来可能会添加一种自动生成这些端点的方法,但它目前不在路线图上。)


推荐阅读