---
title: 战略性的 Suspense 边界
impact: HIGH
impactDescription: 更快的首次绘制
tags: async, suspense, streaming, layout-shift
---
## 战略性的 Suspense 边界
不要在异步组件中等待数据后再返回 JSX,而应使用 Suspense 边界在数据加载期间更快地展示外层 UI。
**错误做法(外层 UI 被数据请求阻塞):**
```tsx
async function Page() {
const data = await fetchData() // 阻塞整个页面
return (
)
}
```
整个布局都要等待数据,即使只有中间部分需要它。
**正确做法(外层 UI 立即显示,数据流式传入):**
```tsx
function Page() {
return (
)
}
async function DataDisplay() {
const data = await fetchData() // 仅阻塞该组件
return {data.content}
}
```
Sidebar、Header 和 Footer 立即渲染。只有 DataDisplay 等待数据。
**备选方案(在组件间共享 Promise):**
```tsx
function Page() {
// 立即发起请求,但不等待
const dataPromise = fetchData()
return (
)
}
function DataDisplay({ dataPromise }: { dataPromise: Promise }) {
const data = use(dataPromise) // 解包 Promise
return {data.content}
}
function DataSummary({ dataPromise }: { dataPromise: Promise }) {
const data = use(dataPromise) // 复用同一个 Promise
return {data.summary}
}
```
两个组件共享同一个 Promise,因此只发起一次请求。布局立即渲染,同时两个组件一起等待。
**何时不应使用此模式:**
- 影响布局决策的关键数据(影响定位)
- 首屏之上对 SEO 至关重要的内容
- 小型、快速的查询,Suspense 开销不值得
- 当你想避免布局偏移时(加载 → 内容跳变)
**权衡取舍:** 更快的首次绘制 vs 潜在的布局偏移。根据你的用户体验优先级进行选择。