HTTP/2引入了服务器推送(Server Push),即服务端向客户端发送比客户端请求更多的数据。这允许服务器直接提供浏览器渲染页面所需资源,而无须浏览器在收到、解析页面后再提起一轮请求,节约了加载时间。

详见:Introducing HTTP/2 Server Push with NGINX 1.13.9

使用

最简单的用法

server {
    # Ensure that HTTP/2 is enabled for the server
    listen 443 ssl http2;


    ssl_certificate /ssl/certificate.pem;
    ssl_certificate_key /ssl/key.pem;

    root /var/www/html;

    # whenever a client requests demo.html, also push
    # /style.css, /image1.jpg and /image2.jpg
    location = /demo.html {
        http2_push /style.css;
        http2_push /image1.jpg;
        http2_push /image2.jpg;
    }
}

另一用法

以推送main.cssmain.js两个文件为例,按照下列配置。开启 http2_push_preload。更多 Link 字段请查看 W3C 文档

server {
    # Ensure that HTTP/2 is enabled for the server
    listen 443 ssl http2;


    ssl_certificate /ssl/certificate.pem;
    ssl_certificate_key /ssl/key.pem;

    root /var/www/html;

    # Intercept Link header and initiate requested Pushes
    location = /myapp {
        proxy_pass http://upstream;
        http2_push_preload on;
        add_header Link "</main.css>; as=style; rel=preload, </main.js>; as=script; rel=preload";
    }
}

有选择的向客户端推送资源,利用 cookie 只有首次访问才会推送资源,防止浪费。

server {
    listen 443 ssl http2 default_server;

    ssl_certificate ssl/certificate.pem;
    ssl_certificate_key ssl/key.pem;

    root /var/www/html;
    http2_push_preload on;

    location = /demo.html {
        add_header Set-Cookie "session=1";
        add_header Link $resources;
    }
}

map $http_cookie $resources {
    "~*session=1" "";
    default "</main.css>; as=style; rel=preload, </main.js>; as=script; rel=preload";
}

顺手启用了 Brotli 压缩算法(火星救援.png),发现貌似只对 .html 的 text/html 起作用,其它的倒是没问题,还好和 gzip 可以一起用。