加载界面与流式传输

特殊文件 loading.js 可帮助您利用 React Suspense 创建有意义的加载界面。通过此约定,您可以在路由段内容加载时展示来自服务器的即时加载状态。渲染完成后,新内容会自动替换显示。

加载界面

即时加载状态

即时加载状态是导航时立即显示的备用界面。您可以预渲染加载指示器(如骨架屏和旋转器),或未来屏幕中有意义的小部分内容(如封面图、标题等)。这有助于用户理解应用正在响应,并提供更好的用户体验。

通过在文件夹内添加 loading.js 文件来创建加载状态。

loading.js 特殊文件
export default function Loading() {
  // 您可以在 Loading 中添加任何界面,包括骨架屏
  return <LoadingSkeleton />
}

在同一文件夹中,loading.js 会被嵌套在 layout.js 内。它会自动将 page.js 文件及其子内容包裹在 <Suspense> 边界中。

loading.js 概览

须知:

  • 即使采用以服务端为中心的路由,导航也是即时的。
  • 导航可被中断,这意味着切换路由时无需等待当前路由内容完全加载。
  • 共享布局在新路由段加载时仍保持可交互状态。

推荐: 对路由段(布局和页面)使用 loading.js 约定,因为 Next.js 对此功能进行了优化。

使用 Suspense 进行流式传输

除了 loading.js,您还可以为自己的界面组件手动创建 Suspense 边界。应用路由支持通过 Suspense 进行流式传输。

须知:

  • 某些浏览器会缓冲流式响应。如果响应小于 1024 字节,您可能看不到流式响应。这通常只影响 "hello world" 示例应用,而非实际应用。

什么是流式传输?

要理解流式传输在 React 和 Next.js 中的工作原理,首先需要了解服务端渲染 (SSR) 及其局限性。

使用 SSR 时,用户看到页面并与之交互前需要完成以下步骤:

  1. 首先,在服务端获取页面的所有数据。
  2. 服务端渲染页面的 HTML。
  3. 将页面的 HTML、CSS 和 JavaScript 发送到客户端。
  4. 使用生成的 HTML 和 CSS 展示非交互式界面。
  5. 最后,React 注水 (hydrate) 界面使其可交互。
未使用流式传输的服务端渲染示意图

这些步骤是顺序且阻塞的,意味着服务端只有在所有数据获取完成后才能渲染页面 HTML。而在客户端,React 只有在页面所有组件的代码下载完成后才能进行注水。

React 和 Next.js 的 SSR 通过尽快向用户展示非交互式页面,提升了感知加载性能。

未使用流式传输的服务端渲染

然而,由于服务端所有数据获取完成后才能向用户展示页面,这种方式仍然可能较慢。

流式传输允许将页面的 HTML 拆分为较小的块,并逐步从服务端发送到客户端。

使用流式传输的服务端渲染工作原理

这样可以在不等待所有数据加载的情况下,尽早显示页面的部分内容。

流式传输与 React 的组件模型配合良好,因为每个组件可视为一个块。优先级较高的组件(如产品信息)或不依赖数据的组件(如布局)可以优先发送,React 可以更早开始注水。优先级较低的组件(如评论、相关产品)可以在同一服务端请求中,在其数据获取完成后发送。

使用流式传输的服务端渲染示意图

流式传输特别有助于防止长时间的数据请求阻塞页面渲染,可减少首字节时间 (TTFB)首次内容绘制 (FCP),还能改善可交互时间 (TTI),尤其是在较慢的设备上。

示例

<Suspense> 的工作原理是包裹执行异步操作(如获取数据)的组件,在操作期间显示备用界面(如骨架屏、旋转器),操作完成后替换为您的组件。

import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (
    <section>
      <Suspense fallback={<p>加载动态中...</p>}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={<p>加载天气中...</p>}>
        <Weather />
      </Suspense>
    </section>
  )
}

使用 Suspense 可获得以下优势:

  1. 流式服务端渲染 - 逐步从服务端向客户端渲染 HTML。
  2. 选择性注水 - React 根据用户交互优先处理需要先交互的组件。

更多 Suspense 示例和用例,请参阅 React 文档

SEO

  • Next.js 会等待 generateMetadata 内的数据获取完成后再向客户端流式传输界面。这确保流式响应的第一部分包含 <head> 标签。
  • 由于流式传输是服务端渲染的,不会影响 SEO。您可以使用 Google 的富媒体搜索结果测试工具查看页面在 Google 网络爬虫中的呈现方式,并查看序列化后的 HTML(来源)。

状态码

流式传输时会返回 200 状态码表示请求成功。

服务端仍可通过流式内容本身向客户端传达错误或问题,例如使用 redirectnotFound 时。由于响应头已发送给客户端,无法更新响应状态码。这不影响 SEO。

平台支持

部署方式是否支持
Node.js 服务端
Docker 容器
静态导出
适配器取决于具体平台

了解如何配置流式传输以自托管 Next.js。

On this page