自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

通過 Node.js, Express.js 實現(xiàn) HTTP/2 Server Push

開發(fā) 前端
HTTP/2 是 Web 開發(fā)的新標(biāo)準(zhǔn),擁有很多不錯的優(yōu)點能夠讓 Web 訪問更快且開發(fā)的工作更輕松簡單。比如,引入多路復(fù)用傳輸不用合并資源,服務(wù)器推送(Server Push)資源讓瀏覽器預(yù)加載。

什么是 HTTP/2 Server Push

HTTP/2 是 Web 開發(fā)的新標(biāo)準(zhǔn),擁有很多不錯的優(yōu)點能夠讓 Web 訪問更快且開發(fā)的工作更輕松簡單。比如,引入多路復(fù)用傳輸不用合并資源,服務(wù)器推送(Server Push)資源讓瀏覽器預(yù)加載。

該文不會講述 HTTP/2 的所有優(yōu)勢。你可以通過上篇文章了解更多{% post_link http2-node-express %}。該文主要關(guān)注于在 Node.js環(huán)境使用 Express.js 和 HTTP/2 庫 spdy。

服務(wù)器推送(Server Push)工作方式是通過在一個 HTTP/2 請求中捆綁多個資源。在底層,服務(wù)器會發(fā)送一個 PUSH_PROMISE,客戶端(包括瀏覽器)就可以利用它且不基于 HTML 文件是否需要該資源。如果瀏覽器檢測到需要該資源,就會匹配到收到的服務(wù)器推送的 PROMISE 然后讓該資源表現(xiàn)的就像正常的瀏覽器 Get 請求資源。顯而易見,如果匹配到有推送,瀏覽器就不需要重新請求,然后直接使用客戶端緩存。這推薦幾篇文章關(guān)于服務(wù)器推送(Server Push)的好處:

  • What’s the benefit of Server Push?
  • Announcing Support for HTTP/2 Server Push
  • Innovating with HTTP 2.0 Server Push

這是個關(guān)于在 Node.js 實現(xiàn)服務(wù)器推送(Server Push)實踐教程。為了更清晰精簡,我們只實現(xiàn)一個路由地址 /pushy 的 Node.js和 Express.js 服務(wù)器,它會推送一個 JS 文件,正如之前所說,我們會用到一個 HTTP/2 庫 spdy。

HTTP/2 和 Node.js

先解釋一下,為啥在 Node.js 環(huán)境選擇 HTTP/2 庫 spdy。當(dāng)前來說,為 Node.js 主要有兩個庫實現(xiàn)了 HTTP/2 :

  • spdy
  • http2

兩個庫都跟 Node.js 核心模塊的 http 和 https 模塊 api 很相似。這就意味著如果你不使用 Express ,這兩個庫就沒什么區(qū)別。然而, spdy 庫支持 HTTP/2 和 Express,而 http2 庫當(dāng)前不支持 Express。這就是為什么我們選擇使用 spdy , Express 是Node.js 適合搭配的實踐標(biāo)準(zhǔn)的服務(wù)框架。之所以叫 spdy是來自于 Google 的 SPDY 協(xié)議后來升級成 HTTP/2。

HTTPS密鑰和證書

要在瀏覽器(Firefox, Safari, Chrome, 或者 Edge)中訪問使用 HTTPS ,你需要生成密鑰和證書。去搜索 “ssl 密鑰生成” 或者按照以下步驟去生成密鑰、證書。在該文提供的源碼中沒有上傳生成的密鑰和證書

  1. $ mkdir http2-node-server-push  
  2. $ cd http2-node-server-push 
  3. $ openssl genrsa -des3 -passout pass:x -out server.pass.key 2048 
  4. ... 
  5. $ openssl rsa -passin pass:x -in server.pass.key -out server.key 
  6. writing RSA key 
  7. $ rm server.pass.key 
  8. $ openssl req -new -key server.key -out server.csr 
  9. ... 
  10. Country Name (2 letter code) [AU]:US 
  11. State or Province Name (full name) [Some-State]:California 
  12. ... 
  13. A challenge password []: 
  14. ... 
  15. $ openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt 

按照以上步驟,你就會產(chǎn)生三個 SSL 文件:

  • server.crt
  • server.csr
  • server.key

你就可以在 Node.js 的 server 腳本中讀取 server.key 和 server.crt。

搭建項目

首先,通過 package.json 初始化項目和下載項目依賴:

  1. npm init -y 
  2. npm i express@4.14.0 morgan@1.7.0 spdy@3.4.0 --save 
  3. npm i node-dev@3.1.1 --save-dev 

當(dāng)前的目錄結(jié)構(gòu)如下

  1. /http2-node-server-push 
  2. /node_modules 
  3. index.js 
  4. package.json 
  5. server.crt 
  6. server.csr 
  7. server.key 

然后,在 package.json 的 scripts 中添加兩個腳本行,去簡化命令(node-dev、自動重載):

  1. "start""./node_modules/.bin/node-dev ."
  2. "start-advanced""./node_modules/.bin/node-dev index-advanced.js" 

現(xiàn)在就可以開始使用 Node.js 、 Express.js 、 spdy 編寫這個簡單實現(xiàn)的帶服務(wù)器推送 HTTP/2 服務(wù)器

編寫腳本

首先,創(chuàng)建 index.js 腳本,并引入以及實例化依賴,看看查看上面的項目目錄結(jié)構(gòu)。其中,我使用了 ES6/ES2015 的語法 const來聲明依賴,如果你不熟悉該聲明語法,你可以進一步閱讀Top 10 ES6 Features Every Busy JavaScript Developer Must Know。

  1. const http2 = require('spdy'
  2. const logger = require('morgan'
  3. const express = require('express'
  4. const app = express() 
  5. const fs = require('fs'

然后,設(shè)置 morgan logger 來監(jiān)聽服務(wù)器服務(wù)了哪些請求。

  1. app.use(logger('dev')) 

設(shè)置主頁,該頁面顯示了 /pushy 是我們服務(wù)器推送的頁面。

  1. app.get('/'function (req, res) { 
  2.   res.send(`hello, http2! go to /pushy`) 
  3. }) 

服務(wù)器推送只需簡單的調(diào)用 spdy 實現(xiàn)的 res.push ,我們將文件路徑名傳輸進去作為第一個參數(shù),瀏覽器會使用這個路徑名來匹配push promise 資源。res.push() 的第一個參數(shù) /main.js 一定得跟 HTML 文件中需要的文件名相匹配。

而第二個參數(shù)是一個可選的對象,設(shè)置了該資源的一些資源信息描述。

  1. app.get('/pushy', (req, res) => { 
  2.   var stream = res.push('/main.js', { 
  3.     status: 200, // optional 
  4.     method: 'GET', // optional 
  5.     request: { 
  6.       accept: '*/*' 
  7.     }, 
  8.     response: { 
  9.       'content-type''application/javascript' 
  10.     } 
  11.   }) 
  12.   stream.on('error'function() { 
  13.   }) 
  14.   stream.end('alert("hello from push stream!");'
  15.   res.end('<script src="/main.js"></script>'
  16. }) 

你可以看到,stream 對象有兩個方法 on 和 end。前者監(jiān)聽了 error 和 finish 事件,而后者則監(jiān)聽完成傳輸 end,然后就會main.js 就會觸發(fā)彈窗。

或者,如果你擁有多個數(shù)據(jù)塊,你可以選擇使用 res.write() 然后最后使用 res.end(),其中 res.end() 會自動關(guān)閉結(jié)束response 而 res.write() 則讓它保持開啟。(該文的源碼中未實現(xiàn)這種情況)

最后,讀取 HTTPS 密鑰和證書并使用 spdy 啟動運轉(zhuǎn)服務(wù)器。

  1. var options = { 
  2.   key: fs.readFileSync('./server.key'), 
  3.   cert: fs.readFileSync('./server.crt'
  4.  
  5. http2 
  6.   .createServer(options, app) 
  7.   .listen(8080, ()=>{ 
  8.     console.log(`Server is listening on https://localhost:8080. 
  9.     You can open the URL in the browser.`) 
  10.   } 

該實現(xiàn)的關(guān)鍵就在于,圍繞著 streams(流)。不是樹林中的河流,而是指開發(fā)者使用的從源頭到客戶端的建立起的數(shù)據(jù)通道流。如果你幾乎不懂流以及 Node.js 和 Express.js 的 HTTP 的請求和返回信息

啟動和對比 HTTP/2 Server Push

使用命令 node index.js 或者 npm stat 運行服務(wù)端腳本,然后訪問 https://localhost:3000/pushy,就可以看到彈窗!而且我們在該路由不存在文件,你可以查看服務(wù)器終端的 logs ,只會有一個請求,而不是沒使用服務(wù)器推送的時候的兩個請求(一個 HTML、一個 JS)。

可以在瀏覽器中檢測收到服務(wù)器端推送的行為。Chrome 啟動開發(fā)者工具,打開 Network 標(biāo)簽,你可以看到 main.js 不存在綠色時間條,就是說明沒有等待時間 TTFB (Time to First Byte)詳細(xì)

再仔細(xì)看,可以看到請求是由 Push 開始發(fā)起的(Initiator列查看),沒有使用服務(wù)器推送的 HTTP/2 服務(wù)器或者 HTTP/1,這一列就會顯示文件名稱,如 index.html 發(fā)起的顯示就是 index.html。

實踐就結(jié)束了,使用了 Express 和 Spdy 簡單就實現(xiàn)了推送 JS 資源,而該資源可以用于后面 HTML 中 <script> 標(biāo)簽引入的。當(dāng)然你也可以在腳本中使用 fs 來讀取文件資源。

總結(jié)

HTTP/2 擁有很多很好的特性,服務(wù)器推送是最被看好的特性之一。它的好處就在于當(dāng)瀏覽器請求頁面的時候,同時發(fā)送必需的資源文件(圖片,CSS 樣式,JS 文件),而不需要等待客戶端瀏覽器請求這些資源,從而做到更快的第一次渲染時間

HTTP/2 庫 spdy 讓開發(fā)者在基于 Express 的應(yīng)用能更容易的實現(xiàn)服務(wù)器推送特性。

責(zé)任編輯:武曉燕 來源: segmentfault
相關(guān)推薦

2013-06-14 09:27:51

Express.jsJavaScript

2020-08-07 10:40:56

Node.jsexpress前端

2014-09-12 10:35:09

Node.jsHTTP 206

2021-01-14 10:48:34

Docker CompNode.js開發(fā)

2014-07-11 14:16:15

AbsurdJSExpress

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開發(fā)指南基礎(chǔ)介紹

2019-02-21 10:38:10

Web 開發(fā)代碼

2023-06-30 23:25:46

HTTP模塊內(nèi)存

2011-09-09 14:23:13

Node.js

2011-11-01 10:30:36

Node.js

2011-09-08 13:46:14

node.js

2011-09-02 14:47:48

Node

2016-09-18 16:04:24

HTTPNode應(yīng)用

2012-10-24 14:56:30

IBMdw

2011-11-10 08:55:00

Node.js

2022-04-02 06:04:03

Node.js代碼緩存V8

2022-04-01 08:02:32

Node.js快照加速hooks

2021-07-16 04:56:03

NodejsAddon

2021-07-09 00:24:10

No.jsNode.js原理
點贊
收藏

51CTO技術(shù)棧公眾號