可水合数据
在 Svelte 中,当需要在服务器端渲染异步内容数据时,只需使用 await 即可。这很棒!但是,这存在一个缺陷:在客户端加载内容时,Svelte 必须重新执行异步操作,这会阻塞加载过程,阻塞时间取决于所需时间:
¥In Svelte, when you want to render asynchronous content data on the server, you can simply await it. This is great! However, it comes with a pitfall: when hydrating that content on the client, Svelte has to redo the asynchronous work, which blocks hydration for however long it takes:
<script>
import { getUser } from 'my-database-library';
// This will get the user on the server, render the user's name into the h1,
// and then, during hydration on the client, it will get the user _again_,
// blocking hydration until it's done.
const user = await getUser();
</script>
<h1>{user.name}</h1>这很愚蠢。如果我们已经在服务器端完成了获取数据的繁重工作,我们不希望在客户端水合过程中再次获取这些数据。hydratable 是一个底层 API,旨在解决此问题。你可能不会经常用到它 - 它会在你使用的任何数据获取库的后台运行。例如,它为 SvelteKit 中的远程函数 提供支持。
¥That’s silly, though. If we’ve already done the hard work of getting the data on the server, we don’t want to get it again during hydration on the client. hydratable is a low-level API built to solve this problem. You probably won’t need this very often -- it will be used behind the scenes by whatever datafetching library you use. For example, it powers remote functions in SvelteKit.
要修复上述示例:
¥To fix the example above:
<script>
import { hydratable } from 'svelte';
import { getUser } from 'my-database-library';
// During server rendering, this will serialize and stash the result of `getUser`, associating
// it with the provided key and baking it into the `head` content. During hydration, it will
// look for the serialized version, returning it instead of running `getUser`. After hydration
// is done, if it's called again, it'll simply invoke `getUser`.
const user = await hydratable('user', () => getUser());
</script>
<h1>{user.name}</h1>此 API 还可用于访问在服务器渲染和水合之间保持稳定的随机值或基于时间的值。例如,要获取一个在水合过程中不会更新的随机数:
¥This API can also be used to provide access to random or time-based values that are stable between server rendering and hydration. For example, to get a random number that doesn’t update on hydration:
import { import hydratablehydratable } from 'svelte';
const const rand: anyrand = import hydratablehydratable('random', () => var Math: MathAn intrinsic object that provides basic mathematics functionality and constants.
Math.Math.random(): numberReturns a pseudorandom number between 0 and 1.
random());如果你是库的作者,请务必在 hydratable 值的键前加上你的库名称作为前缀,以避免与其他库的键冲突。
¥If you’re a library author, be sure to prefix the keys of your hydratable values with the name of your library so that your keys don’t conflict with other libraries.
序列化(Serialization)
¥Serialization
hydratable 函数返回的所有数据都必须是可序列化的。但这并不意味着你只能使用 JSON — Svelte 使用 devalue,它可以序列化各种数据,包括 Map、Set、URL 和 BigInt。请查看文档页面以获取完整列表。除此之外,得益于 Svelte 的一些特性,你还可以放心地使用 Promise:
¥All data returned from a hydratable function must be serializable. But this doesn’t mean you’re limited to JSON — Svelte uses devalue, which can serialize all sorts of things including Map, Set, URL, and BigInt. Check the documentation page for a full list. In addition to these, thanks to some Svelte magic, you can also fearlessly use promises:
<script>
import { hydratable } from 'svelte';
const promises = hydratable('random', () => {
return {
one: Promise.resolve(1),
two: Promise.resolve(2)
}
});
</script>
{await promises.one}
{await promises.two}