背景大家都知道前端项目开发过程中的热更新机制,但是不知道大家在开发的时候有没有配置这方面的。相信接触最多的就是webpack的热更新了。文件保存后自动刷新页面,或者自动更新css。页面的样式将在不刷新页面的情况下更新。存在热模块更换。热更新机制很有意思,可以提高很多开发效率,但是能用到这个阶段还不是我们的目标。我们要深入研究,看看背后的原理,一个有没有想过,另一个能不能自己去实现。.热更新原理下面说说如何自己实现一个热更新,即当文件发生变化时页面会自动刷新,PC端和移动端可以同步。如果更改了css,则无需刷新页面即可应用最新的css。其实热更新的原理并不复杂,或者说很简单。我们一步一步来分析。这篇文章不是告诉你如何使用一些API,而是用架构思维来分析和解决问题。[分析]浏览器如何知道文件内容发生了变化?css文件内容变了,但是页面没有刷新。如何加载最新内容?只要解决了以上两个问题,我们就大功告成了。因为剩下的就是编码,这个好说。[结果]如何通知浏览器文件已更改?浏览器和服务器保持连接。如果服务器有什么问题,直接通过当前链接告诉浏览器即可。连接必须是长连接,不然怎么实时通信。保持长连接的方法有哪些?轮询?事件源?两者都不够好。有更好的解决方案吗?即——websocket浏览器和服务器先建立连接,服务器可以直接通知客户端。此时无论是PC端还是手机端,都可以随时刷新或加载资源。css更新,css本身可以通过dom操作。只要浏览器知道css更新了,就可以直接重新加载当前的css文件。架构思维我们正在审查这个架构。服务器和浏览器通过websocket建立连接。服务器和浏览器规定了好消息的规则,是刷新页面还是更新css。基本结构有了,剩下的就是编码实现了。服务端使用node创建一个ws服务。浏览器使用websocket创建到服务器的连接。双方通过相应的API进行数据操作。代码实现本文只讲解思路,不实现文件监控,后面会介绍。暂且先确定两条消息规则:浏览器收到命令:htmlFileChange,此时浏览器刷新;浏览器收到命令:cssFileChange,此时不刷新页面,自动加载css文件;具体代码如下:serviceEnd://web-socket.js创建ws服务varws=require("nodejs-websocket");//需要安装这个包module.exports=function(){returnfunction(){console.log("重前端提醒,开始建立连接...")varsessions=[];//存储每个连接对象varserver=ws.createServer(function(conn){sessions.push(conn);//将新的连接对象存入数组中conn.on("text",function(str){console.log("收到的信息是:"+str)sessions.forEach(item=>{.sendText(str)//所有客户端都发送消息});});conn.on("close",function(code,reason){console.log("closeconnection")});conn.on("error",function(code,reason){console.log("异常关闭")});}).listen(6152)console.log("WebSocketestablished")}}//server.jshttp服务代码让http=要求('http');让fs=require('fs');letwebSocket=require('./node/web-socket');constBASEROOT=process.cwd();//获取当前执行路径//读取index.html的内容letgetPageHtml=function(){让data=fs.readFileSync(BASEROOT+'/html/index.html');returndata.toString();}//读取index.css内容letgetPageCss=function(){letdata=fs.readFileSync(BASEROOT+'/html/index.css');returndata.toString();}//节点端开启ws服务webSocket()();http.createServer(function(req,res){//创建http服务letbody='',url=req.url;req.on('data',function(chunk){body+=chunk;});req.on('end',function(){//简单路由处理根据不同路径输出不同内容给浏览器if(url.indexOf('/index.css')>-1){res.write(getPageCss());}else{res.write(getPageHtml());}res.end();});}).listen(6151);console.log('重度前端提醒...服务器启动');页面截图客户端//index.html布局代码省略constnick=['a','b','c','d','e','f','g','aa','cc'];让索引=0;//创建WebSocket连接action.constsocket=newWebSocket('ws://10.70.69.191:6152');//连接打开socket.addEventListener('open',function(event){socket.send(navigator.userAgent);});//监听服务器推送的消息socket.addEventListener('message',function(event){if(index>nick.length){index=0;//只是每次输出不同的昵称,无意义}varele=document.createElement('div');ele.innerHTML=nick[index]+':'+event.data;if(event.data==='htmlFileChange'){//html文件已更新Refresh当前页面位置.reload();}if(event.data==='cssFileChange'){//css文件更新刷新当前页面reloadCss();}document.getElementById('content').append(ele);指数+=1;});//重新加载css函数reloadCss(){varcssUrl=[],links=document.getElementsByTagName('link'),len=links.length;对于(vari=0;i
