HTTP/2.0 的 服务端推送(Server Push) 是它相较于 HTTP/1.x 引入的一项重要功能,旨在优化网页加载性能,尤其是首次加载时资源依赖的获取效率。

一、什么是服务端推送?

HTTP/2 Server Push 允许服务器主动将资源“推送”给客户端,而不是等待客户端明确请求。这在某些场景下可以预加载依赖资源、减少请求延迟,提升页面的首屏加载速度。

例如: 客户端请求了 HTML 页面,服务器可以在返回 HTML 的同时,主动推送页面所需的 CSS/JS 资源。

二、服务端推送的工作原理

流程概览:

  1. 浏览器发送主资源请求(如 HTML);
  2. 服务器识别该请求需要哪些依赖资源(如 CSS、JS);
  3. 服务器将这些资源 打包为 PUSH_PROMISE 帧 发送给客户端,声明它即将发送的资源;
  4. 客户端接收到 PUSH_PROMISE 后,会缓存该资源的响应
  5. 当浏览器稍后真正需要这个资源时,不会再发起真实请求,而是从缓存中获取推送的内容;
  6. 避免了请求的 RTT 往返延迟。

技术细节:

  • PUSH_PROMISE 是 HTTP/2 中新增的帧类型,用于声明服务器准备推送的资源;
  • 所有推送的资源都绑定到一个主请求流(主页面),不能独立存在;
  • 客户端可选择 拒绝(RST_STREAM) 不想要的推送资源;
  • 推送资源会根据缓存策略存储在浏览器的缓存中,不一定立即使用。

在使用 Nginx 部署 HTTP/2 服务时,可以通过 Link 响应头启用 Server Push:

location = /index.html {
  http2_push /style.css;
  http2_push /main.js;
}

或者使用 Link 响应头方式:

Link: </style.css>; rel=preload; as=style; nopush
Link: </main.js>; rel=preload; as=script
  • nopush 可用于告知浏览器只预加载但不使用服务端推送。

四、应用场景与优劣权衡

优点:

  • 减少资源加载的等待时间:服务端提前推送关键资源;
  • 避免 RTT 往返:客户端无需先请求才能获取资源;
  • 提升首屏加载速度,尤其适合 HTML 首次加载时依赖静态资源的场景;

局限与问题:

  • 浏览器支持不一致,某些浏览器(如 Chrome)已经限制或禁用该功能;
  • 无法精准判断客户端是否已有缓存,可能导致重复传输浪费带宽;
  • 容易造成推送资源冗余,如果客户端并不需要,反而降低性能;
  • 由于 HTTP/3(基于 QUIC)未保留 Server Push 功能,该机制正逐渐淡出主流优化策略。

五、现状与替代方案

尽管 HTTP/2 Server Push 曾被视为重要性能特性,但在实际大规模部署中遇到了许多现实问题。目前主流建议更倾向于:

  • 使用 <link rel="preload"> 进行客户端主导的资源预加载;
  • 配合 Webpack、Rollup 等构建工具做资源拆分与按需加载;
  • 利用 CDN 和缓存控制优化加载路径;
  • 等待更成熟的 HTTP/3 和 QUIC 技术普及。

常见考点

HTTP/2 的服务端推送(Server Push)是一个重要但实际使用率较低的特性。它允许服务器在客户端还未明确请求资源时,主动将资源“推送”给客户端,用于提前加载关键资源以加快页面渲染。

虽然 HTTP/3 取消了该功能,但面试中仍会从“机制原理 + 使用场景 + 弊端与替代方案”多个角度进行考察。

一、基础原理考察

1. 什么是 HTTP/2 的 Server Push?

  • 客户端发起一个主请求(如 HTML 页面)时,服务器可以在响应之前或同时,主动推送其它关联资源(如 CSS/JS)。
  • 客户端无需显式请求这些资源,它会缓存或使用服务端推送的内容。

2. 工作机制

  • 浏览器发起请求 → 服务器通过 PUSH_PROMISE 帧声明要推送哪些资源
  • 客户端接收到声明后,可选择接受或拒绝(缓存中已有则拒绝)
  • 服务器随后发送资源 → 客户端使用或缓存

二、使用场景考察

  • 页面关键资源预加载:如首页 HTML 加载时提前推送 CSS/JS
  • 提升首屏加载速度:配合缓存策略使用,在访问频繁页面中生效显著
  • 避免额外 RTT(请求-响应延迟)

三、配置与实现考察

1. Nginx 示例:

http2_push /styles.css;
http2_push /main.js;
res.set('Link', '</style.css>; rel=preload; as=style');

3. HTTP 响应头方式:

Link: </styles.css>; rel=preload; as=style

注意:这种方式只在支持 HTTP/2 Server Push 的服务端生效。

四、常见面试考点

问题回答要点
HTTP/2 的 Server Push 原理?主动发送 PUSH_PROMISE,减少 RTT,预加载资源
与浏览器 preload 的区别?preload 是客户端主动告知,Server Push 是服务端主动
Server Push 如何实现?使用 Link 头或服务器配置,依赖 HTTP/2
Server Push 有哪些缺陷?资源可能已缓存、浪费带宽、无法精准控制推送时机
Server Push 为什么在 HTTP/3 中被废弃?使用率低、不稳定、难以优化资源调度
如何替代 Server Push?使用 preload、prefetch、Service Worker 缓存等

五、缺陷与注意点考察

  • 缓存浪费问题:如果客户端已经缓存资源,服务端仍然推送 → 浪费带宽
  • 调度不可控:无法像 JS preload 那样设置优先级、资源时机
  • 对 CDN 不友好:CDN 无法判断是否应推送资源
  • 浏览器支持差异:部分浏览器已不再积极支持该特性
  • 现代替代方案更可控:如 <link rel="preload">、lazy loading