Sveltekit 和 SSR

jpf*_*ius 4 server-side-rendering svelte sveltekit

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

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

Ric*_*ris 9

为什么不直接将 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>
Run Code Online (Sandbox Code Playgroud)

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

序列化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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 但是如果你需要用 urql 或 apollo 来获取怎么办...那么你如何传递数据呢?它不使用获取... (3认同)