开发环境页面热更新早已经是主流,常见的需求如赛事网页推送比赛结果、网页实时展现投票或点赞数据、在线评论或弹幕、在线聊天室等,都须要借助热更新功能,才能达到实时的端对端的极致体验。前端
在最新版本的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