一、NextJs的SSR渲染优化
在传统的 Server-Side Rendering(SSR)过程中,服务器会等待整个 HTML 字符串构建完毕后一次性发送给客户端。这意味着,尽管某些部分内容已经准备好,用户也必须等待所有内容完成渲染才能看到任何反馈。
而 Next.js 实现的SSR采用了一种称为“流式渲染”(Streaming)的技术,它可以做到在服务器端渲染尚未完全完成之前就向客户端发送部分内容,客户端就能够开始显示部分内容,从而加快页面内容的可视时间。参考:nextjs.net.cn/docs/app/bu…
其工作原理如下:
- **逐步发送(**Chunked Transfer Encoding):服务器在构建 HTML 的过程中,并不是等到整个页面渲染完毕才开始发送数据,而是边渲染边发送。一旦一个 HTML 片段(chunk)准备好了,它就会立即通过 HTTP 响应流发送给客户端,无需等待整个页面完成。
- 早期反馈(Early Hints): Next.js还利用了HTTP的Early Hints功能,可以在主要响应之前发送资源提示(如JavaScript、CSS文件),让浏览器提前开始下载必要的资源,进一步加快页面加载速度。
- 交互式体验优先:通过这种方式,用户可以更早地看到页面的顶部内容(即俗称的“内容之上优先”或“ Above-The-Fold”内容),即便页面的其他部分还在服务器上渲染。这显著提高了用户体验,尤其是对于那些依赖快速首屏加载的网站。
除了Next.js,还有一些其他知名的前端框架和库支持服务器端渲染(SSR)中的流式渲染技术,旨在提高首次内容渲染速度(FCP)和提升用户体验。比如:
-
Nuxt.js:作为Vue.js的通用应用框架,Nuxt.js不仅支持SSR,还通过其
nuxt-start
模块实现了类似流式渲染的功能,它可以提前发送HTML内容给客户端,从而加速页面加载。 -
SvelteKit:Svelte的全栈框架SvelteKit也支持SSR,并且在处理路由和预加载数据方面采用了现代的流式渲染策略,提高了首屏加载速度。
-
Remix:这是一个新兴的React框架,专为构建现代web应用设计,强调最佳实践和优化,其中包括服务器渲染和流式HTML响应,以提供更快的页面加载体验。
-
Angular Universal:Angular的服务器端渲染解决方案也支持流式渲染。通过其平台服务器功能,开发者可以生成静态或动态服务器渲染的应用,并通过Node.js服务器发送流式响应。
-
Razzle:这是一个零配置的Universal JavaScript Web应用框架,支持React和其他库,它通过其服务器渲染能力提供了流式HTML输出的可能。
二、什么是流式渲染?
流式渲染(Streaming Rendering)是一种优化网页加载速度的技术,特别关注于改善用户感知的页面加载性能。在传统的网页渲染过程中,服务器通常会等到整个HTML文档生成完毕后才一次性发送给客户端浏览器。这意味着用户需要等待所有内容准备就绪,包括HTML结构、CSS样式、JavaScript脚本及数据,才能开始看到页面内容。
相比之下,流式渲染改变了这一过程,它允许服务器在生成HTML文档的同时就开始向客户端发送部分已完成的内容。这意味着浏览器可以立即开始解析已接收的部分HTML,逐步显示页面内容给用户,而无需等待整个页面完全下载。这一技术利用了HTTP协议的 chunked transfer encoding 特性,允许数据分块传输。
流式渲染的好处主要体现在:
- 提高首屏加载速度(First Contentful Paint, FCP):用户能更快看到页面的初始内容,提升用户体验。
- 更好的交互体验:即使剩余内容还在加载,用户已经可以与已渲染的部分进行交互。
- 减少渲染阻塞:部分内容的早期呈现减少了用户感受到的等待时间。
在服务器端渲染(Server-Side Rendering, SSR)的上下文中,流式渲染尤为重要,因为它能显著加快单页应用(SPA)或重渲染页面的首次加载速度。然而,实现流式渲染需要细致的规划,确保CSS和JavaScript的加载不会阻碍初始内容的显示,并且需要处理好数据的异步加载与页面组件的逐步渲染之间的协调。
三、什么是Early Hints?
Early Hints,也称为"103 Early Hints",是一个HTTP响应状态码,它允许服务器在最终的HTTP响应之前发送一些初步的响应头信息给客户端。这是HTTP/1.1协议的一个扩展功能,最初由HTTP Working Group在RFC 8297中定义。其目的是为了进一步优化网页加载速度,特别是在涉及资源预加载的情况下。
在没有Early Hints的情况下,浏览器通常需要先完整接收HTML文档,然后解析文档以发现需要的外部资源(如CSS、JavaScript文件),之后再发起这些资源的请求。这个过程可能会导致延迟,尤其是在网络状况不佳或资源较大的情况下。
使用Early Hints机制,服务器可以在实际的HTML内容传输之前,提前告知浏览器即将需要的一些关键资源。这样,浏览器可以更早地开始预加载这些资源,从而减少页面渲染的总时间。常见的提示类型包括预加载 CSS、JavaScript文件,或者指示浏览器优先处理某个资源。
简而言之,Early Hints通过允许服务器提前发送资源的提示信息,使浏览器能够更早启动资源加载过程,进而提升了网页的加载速度和用户体验。不过需要注意的是,当前并非所有浏览器和服务器都支持Early Hints特性。
如何在项目中使用 Early Hints?
要在项目中使用 Early Hints,你需要确保你的服务器支持发送 103 Early Hints 响应,并且前端代码能够利用这些提示进行资源预加载。下面是实现这一功能的基本步骤,主要针对服务器配置和支持 Early Hints 的现代浏览器环境:
服务器端配置
1. Nginx 服务器
Nginx 1.19.0 及以后版本支持 Early Hints 功能。可以在 Nginx 配置文件中使用 early_hints
指令来发送 Early Hints。
示例配置:
http {
early_hints on;
server {
listen 80;
server_name example.com;
location / {
# 假设 index.html 中会引用 style.css 和 script.js
early_hints /style.css;
early_hints /script.js;
root /var/www/html;
index index.html;
}
}
}
在这个例子中,Nginx 会在发送 HTML 文件内容之前,先发送对 /style.css
和 /script.js
的 Early Hints。
2. 使用其他服务器
对于 Apache 或自建的服务器,你可能需要查阅最新的文档或使用第三方模块来支持 Early Hints 功能,因为它们可能没有内置此功能。
客户端(前端)代码
1. 自动处理
大多数现代浏览器(如 Chrome)会自动处理服务器发送的 Early Hints,无需前端代码显式操作。浏览器会在接收到提示后,自动开始预加载指定的资源。
2. 显式预加载
虽然不是直接针对 Early Hints,但也可以在 HTML 中使用 <link rel="preload">
来手动预加载资源,这与 Early Hints 的目标一致,但不是通过 103 状态码实现。
<head>
<link rel="preload" href="/path/to/style.css" as="style">
<link rel="preload" href="/path/to/script.js" as="script">
</head>
测试
使用支持 Early Hints 的浏览器访问站点,并使用开发者工具的 Network 面板观察资源加载情况,确认资源是否如预期般被提前加载。
尽管 Early Hints 可以提升性能,但也应谨慎使用,避免无谓的资源预加载增加带宽消耗和服务器负载,确保只预加载对首屏渲染至关重要的资源。