通过HTTP Link标头实现页面资源预加载(preload)

本文介绍一种采用HTTP Link响应标头的资源预加载方式http-preload,通过预先定义preload manifest文件来描述哪个页面需要预加载哪些资源,并使用Node.js, Tomcat, Nginx等多种服务端的middleware/filter读取preload manifest按照其中的描述规则来实现页面资源预加载。

背景

Chrome 103新增了对HTTP状态码 103 (Early Hints)的支持。在此之前的四五年,HTTP状态码 103只是个传说,因为没有浏览器支持它。现在虽有浏览器支持它,但服务端支持HTTP status 103的框架/库却寥寥无几。

操作

第一步:定义Preload Manifest

{
  "$schema": "https://raw.githubusercontent.com/http-preload/manifest/master/preload-v1.schema.json",
  "manifestVersion": 1,
  "conditions": {
    "supportsModulepreload": "(userAgentData, headers) => userAgentData.brands.some((e)=>e.brand==='Chromium'&&parseInt(e.version)>=66)"
  },
  "resources": {
    "/index.html": [
      {"rel": "preload", "href": "/assets/index.css", "as": "style"},
      {"rel": "dns-prefetch", "href": "https://example.com/"}
    ],
    "/index.html supportsModulepreload": [
      {"rel": "modulepreload", "href": "/src/foobar.js"},
      {"rel": "modulepreload", "href": "/lib/foo.js"},
      {"rel": "modulepreload", "href": "/lib/bar.js"},
      {"rel": "modulepreload", "href": "/src/qux.js"}
    ]
  }
}

其中:

  • "$schema"指的是JSON Schema URL,也可以用相对路径指向离线版的preload-v1.schema.json,用以在IDE(如Visual Studio Code)中提供内容辅助、格式校验。
  • "manifestVersion"的值应与所用json schema对版本的要求相匹配
  • "conditions"中每个key是JavaScript标识符(仅ASCII子集),每个value应为函数表达式或箭头函数。
    • 其中参数userAgentData会是类似于Client Hints User Agent API navigator.userAgentData一样的对象,但不限于安全上下文(https协议)
    • 参数headers会是一个包含所有请求头的对象(在Node.js HTTP/2实现中还包含伪请求头:method, :path, :scheme等)
  • “resources"中每个key是页面文件的URI,可选地加一个空格” "和一个已在"conditions"中定义的条件标识符。

该描述文件的作用为:
当服务端收到URI(不含querystring)为"/index.html"的HTTP请求时(或从"/“转发而来),”/index.html"对应的资源列表将被无条件地列为预加载Link请求头,而"/index.html supportsModulepreload"对应地资源列表是否应该发送到客户端取决于函数调用supportsModulepreload(userAgentData, headers)的返回值是否等效于true

详细说明请参见 manifest

第二步:安装使用Preload Filter / Middleware

preload-middleware支持在Node.js serve-index, express, koa, local-web-server使用http-preload

preload-servlet4-filter preload-servlet-filter分别支持在Java 1.8 + Tomcat 9, Java 11 + Tomcat 10中使用http-preload

还有preload-njs-filter,支持在Nginx+njs环境中使用的部分http-preload特性(需要手动重新改njs源码并编译njs;尚不支持HTTP status 103 Early Hints)

P.S. Nginx生态虽有模块ngx_http_early_hints声称支持103 Early Hints,但它在HTTP/2.0协议中不可用,更要命的是它很久没得到更新,不兼容较新的Nginx 1.22.0。

最好让http-preload与HTTP/2.0配套使用,因为预加载会使得但并发请求增多,使用HTTP/1.1协议容易导致并发连接过多时HTTP请求出现排队现象,从而有违预加载的初衷。

第三步:测试预加载的效果

检出并运行上述preload filter/middleware git仓库并运行示例程序,打开浏览器DevTools,并访问本地https://127.0.0.1/ 你将发现之前ES模块加载的依赖链变平了,页面用的到资源都会预先加载。

通过HTTP Link: 标头的方式来实现预加载理论上比通过HTML <link>标签的方式来得更及时,但也会略微增加每个请求的TTFB(Time to First Byte),因为服务端要多增加一层过滤器,多执行至少2个if判断。因此不能保证采用http-preload会比采用<link>标签效果更好,开发者是否采用,应以实际测验结果为依据。一般来说,在网络延迟较高的环境下采用http-preload,页面整体的加载速度优势会明显一些。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值