譯者按: 盆友們,是時候擁抱新一代HTTP協議了!javascript
Node.js 8.4.0已經開始支持HTTP/2,執行node命令時,加上--expose-http2
選項就可使用了。css
在這篇博客中,咱們會介紹如何使用HTTP/2進行服務器推送(server push),另外,咱們還寫了一個簡單的Node.js示例。html
HTTP/2是新一代HTTP協議,支持**多路複用(MultiPlexing)、header壓縮、服務器推送(server push)**等特性,有效減小了時延。對HTTP/2感興趣的話,能夠查看 Introduction to HTTP/2。前端
HTTP/2服務器推送容許服務器在瀏覽器請求資源以前推送資源,減小頁面加載時間。這裏,咱們不妨對比一下HTTP/1和HTTP/2。java
客戶端發送請求給服務器,服務器返回請求的資源,一般是HTML文件,HTML文件包含一些資源連接(好比.js, .css等)。瀏覽器解析HTML文件,獲取資源連接,而後分別請求這些資源。node
下面的圖片展現了這個過程,注意:timeline中有3個獨立的請求,bundle1.js和bundle2.js的請求的initiator是(index)Parser。git
HTTP/1是這樣工做的,咱們已經這樣作不少年了,那爲何要改變呢?問題在於,用戶須要等待瀏覽器解析HTML文件,獲取連接而後請求資源。這會延緩前端渲染,增長頁面加載時間。將一些資源嵌入HTML是一個解決方法,可是那會使得第一次請求變得很大很慢。github
下面的圖片顯示了當服務器啓用HTTP/2以後的網站加載過程。由timeline和initiator可知,多路複用減小了請求個數,並且bundle1.js和bundle2.js在第一次請求時就推送給前端了。web
使用內置的http2模塊,咱們能夠建立一個http2服務器。有趣的一點在於,當index.html
被請求時,咱們會主動推送其餘資源:bundle1.js和bundle2.js。這樣的話,bundle1.js和bundle2.js能夠在瀏覽器請求它們以前就推送過去了。瀏覽器
const http2 = require('http2')
const server = http2.createSecureServer(
{ cert, key },
onRequest
)
function push (stream, filePath) {
const { file, headers } = getFile(filePath)
const pushHeaders = { [HTTP2_HEADER_PATH]: filePath }
stream.pushStream(pushHeaders, (pushStream) => {
pushStream.respondWithFD(file, headers)
})
}
function onRequest (req, res) {
// Push files with index.html
if (reqPath === '/index.html') {
push(res.stream, 'bundle1.js')
push(res.stream, 'bundle2.js')
}
// Serve file
res.stream.respondWithFD(file.fileDescriptor, file.headers)
}
複製代碼
完整的示例能夠查看GitHub倉庫:RisingStack/http2-push-example
Node.js啓用HTTP/2特性能夠幫助咱們優化客戶端與服務端的交互性能。使用服務器推送,咱們能夠在瀏覽器請求資源以前,將資源推送給瀏覽器,這樣能夠減小頁面加載時間,提升用戶體驗。