Next.js 服务端组件及其加载
'use server'
async function ServerComponentWithTimeout() {
await sleepMs(1000)
return <>
这个组件将会在 1000ms 后响应给前端
</>
}
export async function App() {
/**
* 这个 await 会阻塞整个 response,
* 一直到它完成,前端才能得到(其下的内容的)响应;
* 且一旦它抛错,前端就会抛 500;
* 可以 catch 错误,以避免 500
*/
await fetch('xxx').catch(/* catch 能避免 500 */)
/**
* Next.js 修复了,现在能 catch 住了
* --- 下面这一段已过时 ---
* 基本同上,但无法通过 catch 错误来避免 500;
* (try cache 也一样 500)
* 所以你需要确保该方法不会抛错
*/
await serverActionFunc().catch(/* catch 无效,不能避免 500 */)
// 上面的阻塞完成之后,服务端将会流式响应下列内容
return <>
<>这一行文本会立即响应给客户端</>
<Suspense fallback={<>
当其内的异步服务端组件构建时,这一个 fallback 会立即响应给前端,
且暂时不会触发 DOMContentLoaded,
表现上就是浏览器 tab 栏上还能看见转圈圈
</>}>
{/*
该服务端组件构建完成后,会流式地响应给前端;
如果该组件抛 server error,会转发到最近的 error.tsx
*/}
<ServerComponentWithTimeoutA />
</Suspense>
<Suspense fallback={<>
这个 fallback 和上面那个 fallback 是一起响应给前端的
</>}>
{/*
该服务端组件会和上面那个服务端组件同时发起构建;
该服务端组件构建完成后,会流式地响应给前端;
如果该组件抛 server error,会转发到最近的 error.tsx
*/}
<ServerComponentWithTimeoutB />
</Suspense>
{/*
应尽量避免或减少 ServerComponent 直接暴露,
会阻塞**整个**页面的加载;
如果该组件抛 server error,会转发到最近的 error.tsx;
可以像上面那样用 Suspense 包裹;
除非你:从业务上的确需要阻塞加载,或者你不在乎阻塞;
*/}
<ServerComponentWithTimeoutC />
{/*
所有响应均已完成,此时才会触发 DOMContentLoaded,表现上就是 tab 栏不转圈圈了
(不考虑其他组件/子组件)
*/}
</>
}