HTTP/2 的服务器推送

648 阅读5分钟

HTTP/2 的服务器推送(Server Push)是一种允许服务器在客户端请求之前主动发送资源的技术。这可以显著提高性能,特别是对于那些客户端稍后肯定会请求的资源(如 CSS、JavaScript、图片等)。

HTTP/2 服务器推送的原理

  1. 客户端请求: 客户端像往常一样向服务器发送一个请求(例如,请求一个 HTML 页面)。

  2. 服务器响应和推送:

    • 服务器首先发送对初始请求的响应(例如,HTML 内容)。
    • 紧接着,服务器 预测 客户端将需要哪些额外的资源(例如,HTML 中引用的 CSS 和 JavaScript 文件)。
    • 服务器主动创建 推送流(Push Stream),并在这些流上发送预测的资源,而无需等待客户端的显式请求。
    • 服务器发送一个特殊的 PUSH_PROMISE 帧,其中包含推送资源的请求头信息(例如,URL、方法等)。这告诉客户端:“我将要推送这个资源,你做好准备。”
  3. 客户端处理:

    • 客户端收到初始响应(例如,HTML)。
    • 客户端解析 HTML,发现对 CSS 和 JavaScript 的引用。
    • 客户端 检查 是否已经收到了这些资源的 PUSH_PROMISE 帧。
    • 如果已经收到,客户端会使用推送流中的数据,而无需再次向服务器发送请求。
    • 如果没有收到,客户端会像往常一样发送对这些资源的请求。

关键点:

  • 服务器推送是 预测性 的。服务器根据经验或配置来猜测客户端可能需要的资源。
  • 客户端可以 拒绝 推送的资源。如果客户端已经缓存了资源,或者由于某种原因不需要它,它可以发送一个 RST_STREAM 帧来取消推送流。
  • 服务器推送必须遵循 同源策略。服务器只能推送与初始请求相同来源的资源。
  • PUSH_PROMISE 帧非常重要。它允许客户端在解析 HTML 之前 就知道哪些资源将被推送。

前端需要做什么

从前端开发的角度来看,利用 HTTP/2 服务器推送通常 不需要 编写特殊的 JavaScript 代码。主要工作是在服务器端配置。以下是前端可以做的一些事情:

  1. 优化资源依赖关系:

    • 确保 HTML 中引用的资源(CSS、JavaScript、图片等)是 真正 需要的,并且按照正确的顺序加载。
    • 使用 <link rel="preload"><link rel="prefetch"> 来提示浏览器预加载或预取资源。这可以与服务器推送结合使用,但它们是不同的机制。
  2. 处理推送的资源(可选):

    • 虽然通常不需要特殊处理,但如果需要,你可以使用 fetch() API 或 XMLHttpRequest 来监听 PUSH_PROMISE 帧或处理推送流。但这通常是比较高级的用法,大多数情况下不需要。
  3. 监控和测试:

    • 使用浏览器的开发者工具(例如,Chrome DevTools 的 Network 面板)来检查服务器是否正确推送了资源,以及客户端是否正确使用了它们。
    • 测试不同网络条件下的性能,以确保服务器推送真正带来了好处。

服务器端配置(示例)

服务器推送的配置取决于你使用的 Web 服务器。以下是一些常见服务器的示例:

  • Node.js (with http2 module):

    const http2 = require('http2');
    const fs = require('fs');
    
    const server = http2.createServer();
    
    server.on('stream', (stream, headers) => {
        const path = headers[':path'];
    
        if (path === '/') {
            // 1. 发送 index.html
            stream.respondWithFile('./index.html', {
                'content-type': 'text/html'
            });
    
            // 2. 推送 style.css (假设它在 index.html 中被引用)
            stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
                if (err) throw err;
                pushStream.respondWithFile('./style.css', {
                    'content-type': 'text/css'
                });
            });
              // 2. 推送 index.js (假设它在 index.html 中被引用)
            stream.pushStream({ ':path': '/index.js' }, (err, pushStream) => {
                if (err) throw err;
                pushStream.respondWithFile('./index.js', {
                    'content-type': 'text/css'
                });
            });
    
            // (可以推送更多资源)
        } else if (path === '/style.css') {
            //常规的/style.css 请求
           stream.respondWithFile('./style.css', {
              'content-type': 'text/css'
           });
        }
         else if(path === '/index.js'){
           stream.respondWithFile('./index.js', {
                    'content-type': 'text/css'
                });
         }
    });
    
    server.listen(8080);
    
    
  • Apache (with mod_http2):

    <IfModule http2_module>
        Protocols h2 http/1.1
        H2Push on
        H2PushResource /css/style.css
        H2PushResource /js/script.js
    </IfModule>
    

可以在 .htaccess文件中或者在主配置文件中配置.

  • Nginx (with http2_push directive):

    http {
        server {
            listen 443 ssl http2;
            server_name example.com;
    
            ssl_certificate     /path/to/certificate.pem;
            ssl_certificate_key /path/to/private-key.pem;
    
            location / {
                root /path/to/your/website;
                http2_push /css/style.css;
                http2_push /js/script.js;
                # (可以推送更多资源)
                index index.html;
            }
        }
    }
    
    

使用 HTTP/2 协议的网站地址前缀

使用 HTTP/2 协议的网站地址前缀仍然是 https://。HTTP/2 是 HTTP 协议的升级版,但它仍然建立在 TLS/SSL 加密连接之上。因此,你需要一个有效的 SSL 证书才能使用 HTTP/2。

总结

  • HTTP/2 服务器推送是一种强大的性能优化技术,但它主要依赖于服务器端的配置。
  • 前端开发人员通常不需要编写特殊的代码来利用服务器推送,但可以优化资源依赖关系和监控推送效果。
  • 使用 HTTP/2 的网站仍然使用 https:// 前缀。
  • 确保你的服务器和客户端都支持 HTTP/2。大多数现代浏览器和 Web 服务器都已经支持。

如何检查网站是否使用 HTTP/2

  1. 浏览器开发者工具:

    • 打开 Chrome DevTools (F12 或右键 -> 检查)。
    • 切换到 "Network" 面板。
    • 刷新页面。
    • 在 "Protocol" 列中,你应该会看到 "h2"(表示 HTTP/2)或 "http/1.1"。
  2. 在线工具:

    • 有一些在线工具可以检查网站是否使用 HTTP/2,例如 HTTP/2 Check

如果你的网站仍然使用 HTTP/1.1,你可能需要升级你的 Web 服务器或联系你的托管服务提供商。