gpt 给我搞懵了,是我对 Suspense 理解有误吗?

90 天前
 xiaoming1992

我在考虑博客首页优化的时候,灵机一动想要先响应前 10 条博客,然后流式响应剩下的。就问了一下 gpt 。除了第一问以外,后续都是在跟 gpt 争论。。。

与 gpt 的聊天

我认为在博文只有 100 条左右的时候,/api/posts

应该没有明显差距(尤其是 posts 接口还不获取内容,只获取标题、简介、发布日期之类的东西)

我假设都需要 200ms.

那么按 gpt 的意思来干的话,页面会是

|-- 白屏
|--|-- 200ms 后接口获取到数据,渲染 html 输出到前端
|--|-- 同时 Suspense 显示 fallback
|--|-- 同时请求第二个 get 接口,
|--|--|-- 再 200ms 后接口获取到数据,渲染 html 输出到前端

按我的意思的话,页面会是

|-- Suspense 立即显示 fallback
|-- 同时请求 get 接口,
|--|-- 200ms 后接口获取到数据,渲染 html 输出到前端

这不是明显我的方案更优吗,省了 200ms 的白屏。可 gpt 非说它的更好。

大佬们帮我看看,是不是我理解得不到位。

'use server'

async function Posts({ start, count }: { start: number; count?: number }) {
  const data = await get('/api/posts', {
    start,
    // 假设 count 为空的时候获取后续所有
    count,
  })

  return <RenderPosts data={data} />
}

// gpt 的意思是这样
export function Page() {
  return <>
    <Posts start={0} count={10} />
    <Suspense fallback={<div>loading</div>}>
      <Posts start={10} />
    </Suspense>
  </>
}

// 我的意思是这样
export function Page() {
  return <>
    <Suspense fallback={<div>loading</div>}>
      <Posts start={0} />
    </Suspense>
  </>
}
2185 次点击
所在节点    React
10 条回复
liwenka1
90 天前
然后等 AllPosts 完全 resolve (也就是所有 100 篇数据都 fetch 完成并渲染完)。
我的理解不就是先渲染 10 条能早点看见内容吗?然后请求 100 条的时间会更长(因为响应时间更长)
xiaoming1992
90 天前
@2020583117 我的意思是,应该并不能早点看到内容吧?

两者都是 200ms 后取到数据,然后开始渲染,渲染完成后响应给浏览器,差距无非是渲染时间,应该可以忽略不计吧
jlak
90 天前
gpt 可能假设你 page.js 之前还有一层 loading.js
xiaoming1992
90 天前
@jlak 我已经把我的伪代码给他了,就是提问中末尾那段
renmu123
90 天前
如果你重视 首屏体验(首屏是指用户真正看到有意义的内容)
xiaoming1992
90 天前
@renmu123 问题是按照 gpt 说的,前 200ms 是白屏啊,我不过是把白屏的时间换成 loading 罢了(应该是这样吧?)
SanjinGG
90 天前
Gpt 只是 posts count10 不在 suspense 里,不然白屏也是 loading ,gpt 的方案应该是先请求 10 条,这样是可以更快看到内容的,后续的 post 应该是滚动加载的,但 gpt 直接一次性请求了,正常应该是 gpt 体验更好,但现在的网速,这么少量的数据差距不是很大
zizon
89 天前
> 假设都需要 200ms.

gpt 把这个丢了吧.
认为两类请求代价不同.
xiaoming1992
89 天前
@zizon 我没太理解,不都是在服务端发的请求吗?
rocmax
86 天前
suspense 标签内的组件需要支持流式传输,你可以用 use hook 或者 react query 和 useSuspenseQuery 来实现,表明不用等待 suspense 内部的处理,其他内容渲染完就可以发送。
你现在的实现在服务器端等待从 API 获取数据然后渲染,这种情况下 suspense 没有意义,你直接渲染全部然后发送就完了。
如果希望 suspense 有效,个人推荐的方式是在服务器组件中 prefetch ,然后添加 hydration boundary ,在 suspense 内的组件中使用 usesuspensequery 。
如果想精确实现你的需求,那么在服务器组件中 await 获取前 10 条,然后用 react query 发起另一个 prefetch 请求获取后面的但不要 await ,最后在 suspense 内部使用 usesuspensequery 。这样很麻烦没太大意义。如果条目多不如考虑 react query 的 infiniteQuery 实现滚动加载。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1137197

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX