使用 HTTP/2 服务端推送技术加速 Node.js 应用 ========================================================= 四月份,我们宣布了对 [HTTP/2 服务端推送技术][3]的支持,我们是通过 HTTP 的 [Link 头部](https://www.w3.org/wiki/LinkHeader)来实现这项支持的。我的同事 John 曾经通过一个例子演示了[在 PHP 里支持服务端推送功能][4]是多么的简单。 ![](https://blog.cloudflare.com/content/images/2016/08/489477622_594bf9e3d9_z.jpg) 我们想让现今使用 Node.js 构建的网站能够更加轻松的获得性能提升。为此,我们开发了 [netjet][1] 中间件,它可以解析应用生成的 HTML 并自动添加 Link 头部。当在一个示例的 Express 应用中使用这个中间件时,我们可以看到应用程序的输出多了如下 HTTP 头: ![](https://blog.cloudflare.com/content/images/2016/08/2016-08-11_13-32-45.png) [本博客][5]是使用 [Ghost](https://ghost.org/)(LCTT 译注:一个博客发布平台)进行发布的,因此如果你的浏览器支持 HTTP/2,你已经在不知不觉中享受了服务端推送技术带来的好处了。接下来,我们将进行更详细的说明。 netjet 使用了带有定制插件的 [PostHTML](https://github.com/posthtml/posthtml) 来解析 HTML。目前,netjet 用它来查找图片、脚本和外部 CSS 样式表。你也可以用其它的技术来实现这个。 在响应过程中增加 HTML 解析器有个明显的缺点:这将增加页面加载的延时(到加载第一个字节所花的时间)。大多数情况下,所新增的延时被应用里的其他耗时掩盖掉了,比如数据库访问。为了解决这个问题,netjet 包含了一个可调节的 LRU 缓存,该缓存以 HTTP 的 ETag 头部作为索引,这使得 netjet 可以非常快的为已经解析过的页面插入 Link 头部。 不过,如果我们现在从头设计一款全新的应用,我们就应该考虑把页面内容和页面中的元数据分开存放,从而整体地减少 HTML 解析和其它可能增加的延时了。 任意的 Node.js HTML 框架,只要它支持类似 Express 这样的中间件,netjet 都是能够兼容的。只要把 netjet 像下面这样加到中间件加载链里就可以了。 ```javascript var express = require('express'); var netjet = require('netjet'); var root = '/path/to/static/folder'; express() .use(netjet({ cache: { max: 100 } })) .use(express.static(root)) .listen(1337); ``` 稍微加点代码,netjet 也可以摆脱 HTML 框架,独立工作: ```javascript var http = require('http'); var netjet = require('netjet'); var port = 1337; var hostname = 'localhost'; var preload = netjet({ cache: { max: 100 } }); var server = http.createServer(function (req, res) { preload(req, res, function () { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); res.end('