为什么在Solid Start的SSR中,组件在客户端渲染时会重复执行server$函数?

翌萌 Dev 阅读 41

我在用Solid Start做SSR时遇到了奇怪的问题,布局组件里用server$获取数据后,切换页面再回来,发现server$函数又重新执行了,明明应该只在服务端跑啊。我检查过路由配置没问题,控制台也没报错,但网络请求明显重复了。

代码是这样写的:


// src/routes/layout.tsx
import { server$ } from '@solid-start/server';

export const data = server$(async () => {
  console.log('正在获取数据...'); // 客户端切换回来时会再打印
  return await fetch('https://api.example.com/data');
});

尝试过把server$移到组件内部,或者加use-server属性都不管用,这个重复请求到底是怎么回事啊?

我来解答 赞 10 收藏
二维码
手机扫码查看
2 条解答
♫樱潼
♫樱潼 Lv1
这问题我之前也踩过。你写的代码其实没错,但没搞明白 server$ 的执行时机。server$ 在 SSR 时确实只跑一次,但你把它定义在组件外部,组件每次加载都会重新触发它。布局组件在客户端切换回来时会重新 mount,你的 data 变量又执行了一次 server$,虽然实际请求不会真的发到服务端,但 console.log 会执行,所以你看着像是重复请求了。

要解决这个问题,把 server$ 移到组件内部,并结合 useServer 来用,这样它才能正确缓存。比如:

import { server$, useServer } from '@solid-start/server';

function Layout() {
const data = useServer(server$(async () => {
console.log('正在获取数据...');
return await fetch('https://api.example.com/data');
}));

return <div>{data().json}</div>
}


这样 data 就会被缓存住,组件重新渲染也不会重复执行。记住,server$ 本身不是缓存的,useServer 才是关键。
点赞 1
2026-02-07 03:01
秀莲 ☘︎
这是因为 server$ 的执行和组件的生命周期挂钩,每次组件重新挂载时都会重新调用。改成这样,用 memo 缓存数据:

import { server$, memo } from '@solid-start/server';

export const data = memo(server$(async () => {
console.log('正在获取数据...');
return await fetch('https://api.example.com/data');
}));


这样可以避免重复请求。如果还有问题,检查是否用了强制刷新状态的逻辑。
点赞 16
2026-01-28 17:48