导读:本期聚焦于布兰登创作的《如何在Nginx中配置HTTP/2服务器推送为日记页面预加载CSS和JS?》,敬请观看详情。访问日记站点时,浏览器通常先取回HTML,再逐个请求CSS和脚本,多一轮往返就多一层延迟。Nginx从1.13.9版本开始支持HTTP/2服务器推送,允许服务端在响应主文档时主动把关联资源发给客户端。本文将围绕http2_push指令展开,说明如何在Nginx配置文件中声明推送资源,如何用响应头Link配合http2_push_preload实现自动推送,以及如何避免在带Cookie的动态请求上重复推送。文中包含完整的location配置片段、响应头示例和验证方法,也会讨论推送缓存的命中条件、MIME类型限制和常见配置错误。如果日记页面需要加载样式表、图标或首屏脚本,合理使用Server Push能减少一次完整往返,提升弱网环境下的打开速度。

HTTP/2的多路复用解决了连接数限制,但页面加载仍然遵循请求-响应节奏:客户端先拿到HTML,解析后才发现还需要样式、脚本和图片。Nginx从1.13.9版本开始提供http2_push指令,允许服务端在返回主文档时主动向客户端推送关联资源。对日记类站点来说,首页通常由一份HTML、一份CSS、少量JavaScript和头像图片组成,如果这些静态资源能随HTML一起到达,浏览器就不必再发出第二轮请求。本文会结合一个可运行的配置示例,说明如何用Nginx完成这组推送。

如何在Nginx中配置HTTP/2服务器推送为日记页面预加载CSS和JS?

需要先明确一点:Server Push只工作在HTTPS之上。浏览器通过TLS协商启用HTTP/2协议后,服务端才能发送PUSH_PROMISE帧。若Nginx仍以明文HTTP访问,配置了http2_push也不会产生任何效果。下面先看一个最小化的server配置。

一、开启HTTP/2并认识http2_push指令

要让Nginx具备服务端推送能力,第一步是让站点监听在支持HTTP/2的HTTPS端口上。较老版本的Nginx需要在listen指令中直接携带http2参数,写法如下。

server {
    listen 443 ssl http2;
    server_name diary.ipipp.com;

    ssl_certificate     /etc/nginx/ssl/diary.crt;
    ssl_certificate_key /etc/nginx/ssl/diary.key;

    root /var/www/diary;
    index index.html;
}

较新版本的Nginx将HTTP/2开关从listen参数中拆分出来,可以改为listen 443 ssl;再在server块里写http2 on;。无论哪种写法,只有确认浏览器与Nginx使用HTTP/2进行通信,后续的http2_push指令才有意义。

http2_push的作用是在响应主请求时,额外向客户端推送一个同源资源。它可以在http、server或location上下文中使用,参数是站点的相对URI。比如首页需要用到一张头像图片,可以在对应location中这样写:

location = /diary/ {
    http2_push /assets/diary.css;
    http2_push /assets/diary.js;
    http2_push /assets/avatar.png;
}

这里要注意,http2_push只能接收站内相对路径,路径必须以/开头,不能携带查询字符串,更不能写成https://cdn.ipipp.com/xxx.css这种完整外部地址。如果推了一个不存在的文件,客户端在收到PUSH_PROMISE后会发起匹配请求,最终可能看到一条失败记录。

二、为日记首页配置静态资源推送

日记首页通常位于/diary/或根路径。为了让CSS和JS随HTML一并到达,可以把http2_push放到匹配该页面的location中。下面是一份相对完整的Nginx配置片段,既推送首屏资源,也保证静态资源目录可正常访问。

server {
    listen 443 ssl http2;
    server_name diary.ipipp.com;

    ssl_certificate     /etc/nginx/ssl/diary.crt;
    ssl_certificate_key /etc/nginx/ssl/diary.key;

    root /var/www/diary;
    index index.html;

    location = /diary/ {
        http2_push /assets/diary.css;
        http2_push /assets/diary.js;
        http2_push /assets/favicon.ico;
    }

    location /assets/ {
        expires 7d;
        try_files $uri =404;
    }
}

在这个配置中,只有精确访问/diary/时才会触发推送,而/assets/目录仍然按照正常请求处理。这样做的意义在于,推送资源并没有绕过正常请求流程,它只是提前告诉浏览器这些资源马上需要,浏览器后续接收时可以直接使用缓存中的响应。

推送资源的选择非常关键。日记首页如果拉取了编辑器的完整脚本、评论组件、统计代码,不一定全部都需要推送。首屏渲染真正依赖的CSS、暴露首屏交互的少量JS、favicon和头像往往收益最大。推送太多资源会占用带宽和并发流,部分客户端还可能因为缓存已有而发送RST_STREAM取消推送,反而增加开销。Nginx提供的http2_max_concurrent_pushes可以用来限制并发推送数量,通常设置为10以内比较稳妥。

另外,如果站点里有多个页面都匹配/diary/前缀,建议使用location = /diary/精确匹配首页,避免对/diary/edit、/diary/settings等页面也执行同一组推送。不同页面的依赖资源不同,分开配置更加清晰。

三、用http2_push_preload自动读取Link头

如果日记页面由后端模板或静态生成器输出,不能为每篇文章在Nginx配置中写死资源列表。此时可以通过响应头Link配合http2_push_preload on;实现自动推送。后端或Nginx在返回HTML时附带一个预加载头,Nginx解析其中的rel=preload项并转换为PUSH_PROMISE帧。

location /diary/ {
    http2_push_preload on;
    add_header Link "</assets/diary.css>; rel=preload; as=style";
    add_header Link "</assets/diary.js>; rel=preload; as=script";
}

上面的配置表示:凡是匹配/diary/前缀的响应,Nginx都会检查响应头中的Link字段。只要字段里出现rel=preload,Nginx就会把它当作推送目标。这样做的好处是,资源列表可以由后端动态决定,Nginx保持通用配置即可。后端程序也可以直接输出Link响应头,此时Nginx不需要再写add_header。

需要区分的是,rel=preload会被转换成服务端推送,而rel=prefetch不会。前者表示当前页面马上要用,后者只是下一跳可能要用。因此,如果只是想让浏览器空闲时提前下载,不要使用http2_push_preload触发推送,普通预加载即可。

as属性也很重要,它告诉浏览器资源的类型,从而影响请求优先级和后续使用方式。常见值包括style、script、font、image。比如首屏字体可以写as=font,头像图片可以写as=image。这个信息会随响应头传送给客户端,并不直接改变Nginx返回的Content-Type,但能帮助客户端更准确地处理资源。

四、验证推送效果与排错思路

配置完成后,单靠页面能打开并不能证明推送已经生效。最直观的方法是在浏览器开发者工具中打开Network面板,查看CSS或JS请求的Initiator字段。如果看到Push / Other,说明资源是由服务端主动推送而来;如果仍然是Parser或script,说明浏览器是在解析HTML标签后才发起的普通请求,Nginx的推送没有成功。

命令行验证可以使用nghttp工具。下面这条命令会访问日记主页,并把HTTP/2帧打印出来。

nghttp -ans https://diary.ipipp.com/diary/

如果输出中出现了PUSH_PROMISE帧,就说明Nginx确实发送了推送。没有看到时,可以从下面几个方面排查:

  • 站点是否使用HTTPS和HTTP/2协议,明文HTTP不会触发Server Push。
  • server_name与实际访问域名是否一致,证书是否有效。
  • http2_push是否写在了正确匹配请求的location中。
  • 推送路径是否以/开头,并且文件真实存在。
  • 使用反代或CDN时,Server Push可能在边缘节点丢失。

对日记类应用的实际建议是:推送资源控制在2到4个,以首屏CSS、JS和字体为主;用户自己的日记列表接口、文章详情内容、带会话状态的数据都不适合推送。这些内容经常变化,推送给客户端后往往会被取消,不会带来稳定的收益。静态资源推送则应配合expires等缓存头使用,并观察命中率。如果推送资源长期频繁被RST_STREAM取消,说明客户端已有缓存,此时可以把该资源从推送列表中移除。

HTTP/2 Server Push在合适的静态资源场景下能省去一次往返,但它不是所有页面都适用的灵丹妙药。配置http2_push时要把推送范围限制在首屏关键资源,并持续观察命中率和取消次数。对动态生成的日记页面,http2_push_preload on;配合响应头Link更为灵活,可以有效降低Nginx配置的维护成本。

Nginx HTTP/2推送http2_push服务器推送修改时间:2026-09-30 18:01:10

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0930/63919.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。