原文:Easy HTTP/2 Server with Node.js and Express.js
做者:Azat Mardan
代碼:http2-express前端
現代互聯網的 TCP/IP
協議發佈於1975年,這項技術在41年前是多麼使人驚訝。自它發佈開始大部分形式,咱們使用 HTTP
和 後續接任者 HTTP/1.1
來實現客戶端和服務端的通信。它能很不錯的傳輸 Web
,但今時今日的開發者創建網站的方式已經發生了巨大的改變。存在各式各樣的外部資源連接例如圖片、CSS
文件、JavaScript
資源。資源的種類數量只會持續增加。node
HTTP/2
是針對表現一直不錯的舊協議 HTTP
自從1991年發佈以來這15年的第一次大的升級改動!它爲優化現代瀏覽器而生。性能更加優越並且不用使用複雜的行爲例如域名分片
(經過多個域名發送資源)或者資源文件合併`(提供一個整合的大資源而不是多個小資源)git
HTTP/2
是當前 web
的新標準,其雛形是 Google 的 SPDY
協議。當前已經被大多數主流瀏覽器支持,且不少網站已經經過該協議實現。例如訪問 Yahoo 的 Flickr
在使用的是 HTTP/2
協議(截圖時間爲2016年7月).github
HTTP/2
和 HTTP/1.1
的使用沒什麼區別,仍然能夠在 body
中使用類 xml
的語法,使用 header
協議頭字段, 狀態碼, cookies, methods, URLs, 等等。開發者熟悉使用的東西都還能夠繼續在 HTTP/2
使用。web
HTTP/2
的優點以下:express
多路複用傳輸(Multiplexing):容許瀏覽器在單個TCP鏈接中包含多個請求,從而使瀏覽器可以並行地請求全部的資源;npm
服務器推送(Server push):服務器能夠在瀏覽器知道須要該資源前,推送給瀏覽器(如:CSS、JS、Image),從而經過減小請求數量來加速頁面加載時間;json
流傳輸優先級(Stream priority):容許瀏覽器去控制資源的加載優先級,例如,瀏覽器先請求 HTML
渲染再去加載其餘的 CSS
和 JS
文件;瀏覽器
頭部壓縮(Header compression): HTTP/1.1
請求的頭部老是重複同樣的內容,而 HTTP/2
則強制對全部請求的頭部進行了去重壓縮;緩存
實際的強制加密(De facto mandatory encryption):雖然加密不是硬性要求的,可是大多數瀏覽器只支持 TLS(HTTPS)
上的 HTTP/2
。
雖然目前對於 HTTP/2
還不能徹底知足一些苛求,可是直到更好的技術出現之前,當前是一項明顯的技術進步。讓咱們來看看,做爲 Web
開發者須要瞭解的必要知識。大部分適用於 HTTP/1.1
的優化技巧在 HTTP/2
中變成多餘的,其中一些甚至反而會影響 HTTP/2
上的網站性能,例如:
資源文件合併;
你也應該中止使用精靈圖(image sprites)、CSS和JS打包,由於只要其中一小部分有改動就會影響客戶端的緩存的做用;在 HTTP/2
協議上更好的方式是使用多個的小文件,而不是一個大文件。
做者但願前端構建工具,如 Grunt
、 Gulp
、 Webpack
將會所以特性被放棄使用,他們使 Web
開發更高的複雜度,極高的學習曲線,以及管理項目的依賴關係。
另外一個適用於 HTTP/1.1
不適用於 HTTP/2
的是,域名分片(爲了繞過TCP並行請求數量限制)。雖然它不必定在全部狀況下有害,但對於 HTTP/2
的多路複用傳輸,這樣作也已經沒好處了。之因此建議不在 HTTP/2
使用域名分片,還由於每一個域名會帶來額外的查詢負載。若是真的有須要,那麼更好的方式是解析多個域名到同一個IP,並且保證你使用的是通配符證書或整合了多域名的證書,從而減小域名查詢的時間。
若想了解更多關於 HTTP/2
的介紹,能夠看看官網。
如今,讓咱們看看怎麼經過 Node.js
搭建 HTTP/2
服務器。
建立一個新文件夾以及本身簽發的 SSL
證書。
$ mkdir http2-express $ cd http2-express $ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 ... $ openssl rsa -passin pass:x -in server.pass.key -out server.key writing RSA key $ rm server.pass.key $ openssl req -new -key server.key -out server.csr ... Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:California ... A challenge password []: ... $ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
當你訪問服務器的時候,由於瀏覽器默認不信任本身簽發的證書,請確保選擇 「高級」 和 「繼續訪問 localhost (不安全)」 或者將 localhost 設置成不安全訪問的例外。
經過 npm
,初始化項目 package.json
,安裝依賴 spdy
和 express
:
npm init npm i express spdy --save
建立應用的入口文件 index.js
,主要是引用以及實例化
const port = 3000 const spdy = require('spdy') const express = require('express') const path = require('path') const fs = require('fs') const app = express()
實現 Express.js
的 route
app.get('*', (req, res) => { res .status(200) .json({message: 'ok'}) })
經過 fs.readFileSync()
讀取證書
const options = { key: fs.readFileSync(__dirname + '/server.key'), cert: fs.readFileSync(__dirname + '/server.crt') }
而後,設置證書選項到 Express
對象:
spdy .createServer(options, app) .listen(port, (error) => { if (error) { console.error(error) return process.exit(1) } else { console.log('Listening on port: ' + port + '.') } })
最後,node .
啓動服務器
經過瀏覽器的開發者工具查看協議,就如剛剛咱們查看 Yahoo 的 Flickr
協議同樣。
能夠看到,使用 Node.js 和 Express.js 配合庫 node-spdy 實現 HTTP/2
簡單易懂。大多數狀況下,對你的業務代碼是基本不須要修改的,想必,你的網站也已經使用了 HTTPS/SSL
(除非你的服務器只提供靜態資源,不然你應該使用安全的 HTTPS/SSL
),即便是不使用 HTTP/2 你也能夠替換 HTTP/1.1 而使用 SPDY
固然,在 Node.js 的大環境中,有不少的庫,不僅是 node-spdy 提供 HTTP/2
實現,例如:node-http2
HTTP/2
提供了更多更優的好處,並且不用使用複雜的優化技巧。開始享受 HTTP/2
給你帶來的這些好處。展望光明的將來!
PS:
本文源代碼地址在 http2-express
個人博客