開發環境頁面熱更新早已經是主流,常見的需求如賽事網頁推送比賽結果、網頁實時展現投票或點贊數據、在線評論或彈幕、在線聊天室等,都須要藉助熱更新功能,才能達到實時的端對端的極致體驗。前端
在最新版本的webpack-dev-server中,熱更新機制已經從EventSource切換到了WebSocket。webpack
早期webpack的熱更新藉助於EventSource,這就不得不提到webpack-hot-middleware插件了nginx
webpack-hot-middleware
中間件是webpack的一個plugin,一般結合webpack-dev-middleware一塊兒使用。藉助它能夠實現瀏覽器的無刷新更新(熱更新),即webpack裏的HMR(Hot Module Replacement)。如何配置請參考 webpack-hot-middleware,如何理解其相關插件請參考 手把手深刻理解 webpack dev middleware 原理與相關 plugins。
webpack加入webpack-hot-middleware後,內存中的頁面將包含HMR相關js,加載頁面後,Network欄能夠看到以下請求:git
__webpack_hmr是一個type爲EventSource的請求, 從Time欄能夠看出:默認狀況下,服務器每十秒推送一條信息到瀏覽器。github
若是此時關閉開發服務器,瀏覽器因爲重連機制,將持續拋出相似GET http://www.test.com/__webpack_hmr 502 (Bad Gateway)
這樣的錯誤。從新啓動開發服務器後,重連將會成功,此時便會刷新頁面。以上這些即是咱們使用時感覺到的最初的印象。固然,停留在使用層面不是咱們的目標,接下來咱們將跳出該中間件,講解其所使用到的EventSource技術。web
EventSource 不是一個新鮮的技術,它早就隨着H5規範提出了,正式一點應該叫Server-sent events,即SSE。鑑於傳統的經過ajax輪訓獲取服務器信息的技術方案已通過時,咱們迫切須要一個高效的節省資源的方式去獲取服務器信息,一旦服務器資源有更新,可以及時地通知到客戶端,從而實時地反饋到用戶界面上。EventSource就是這樣的技術,它本質上仍是HTTP,經過response流實時推送服務器信息到客戶端。
客戶端新建一個EventSource對象很是簡單。ajax
const es = new EventSource('/message');// /message是服務端支持EventSource的接口
服務端實現/message接口,須要返回類型爲 text/event-stream的響應頭。segmentfault
var http = require('http'); http.createServer(function(req,res){ if(req.url === '/message'){ res.writeHead(200,{ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); setInterval(function(){ res.write('data: ' + +new Date() + '\n\n'); }, 1000); } }).listen(8888);
咱們注意到,爲了不緩存,Cache-Control 特別設置成了 no-cache,爲了可以發送多個response, Connection被設置成了keep-alive.。發送數據時,請務必保證服務器推送的數據以 data:開始,以\n\n結束,不然推送將會失敗(緣由就不說了,這是約定的)。
以上,服務器每隔1s主動向客戶端發送當前時間戳,爲了接受這個信息,客戶端須要監聽服務器。以下:跨域
es.onmessage = function(e){ console.log(e.data); // 打印服務器推送的信息 }
es能夠監放任何指定類型的事件。瀏覽器
es.addEventListener("####", function(e) {// 事件類型能夠隨你定義 console.log('####:', e.data); },false)
服務器發送不一樣類型的事件時,須要指定event字段。
res.write('event: ####\n'); res.write('data: 這是一個自定義的####類型事件\n'); res.write('data: 多個data字段將被解析成一個字段\n\n');
使用EventSource技術實時更新網頁信息十分高效。實際使用中,咱們幾乎不用擔憂兼容性問題,主流瀏覽器都了支持EventSource,固然,除了掉隊的IE系。對於不支持的瀏覽器,其PolyFill方案請參考HTML5 Cross Browser Polyfills
關於CORS配置能夠參考我另外一篇博文 前端跨域詳解
既然說到了EventSource,便有必要談談遇到的坑,接下來,就說說我遇到的webpack熱更新延遲問題。
如咱們所知,webpack藉助webpack-hot-middleware插件,實現了網頁熱更新機制,正常狀況下,瀏覽器打開 http://localhost:8080 這樣的網頁便可開始調試。然而實際開發中,因爲遠程服務器須要種cookie登陸態到特定的域名上等緣由,所以本地每每會用nginx作一層反向代理。即把 http://www.test.com 的請求轉發到 http://localhost:8080 上轉發事後,發現熱更新便延遲了。
緣由是nginx默認開啓的buffer機制緩存了服務器推送的片斷信息,緩存達到必定的量纔會返回響應內容。只要關閉proxy_buffering便可。配置以下所示:
server { listen 80; server_name www.test.company.com; location / { proxy_pass http://localhost:8080; proxy_buffering off; } }
WebSocket
WebSocket是基於TCP的全雙工通信的協議,它與EventSource有着本質上的不一樣.(前者基於TCP,後者依然基於HTTP)。關於WebSocket能夠參考這裏WebSocket