背景前端项目开发过程中热更新的机制大家都知道,不知道你在开发的时候是否做了这方面的配置。相信接触最多的就是 webpack 的热更新,文件保存后页面自动刷新,或者 css 自动更新,页面的样式在不刷新页面的情况下就会更新。还有就是模块热替换。热更新机制很好玩,能提升不少开发效率,但是只是处于会用的阶段不是我们的目的,我们应该适当的深入学习下,看看他背后的原理,一个是否思考过,一个是否能自己实现。热更新原理咱们这里主要说下怎样自己实现一个热更新,也就是文件更改了会自动刷新页面,可以同步 pc 和 移动端,css 更改了可以不刷新页面就应用最新的 css。其实热更新的原理并不复杂,或者说很简单。咱们一步一步的分析下。本文不是要告诉你一些 api如何使用,而是利用架构的思维去分析和解决问题。【分析】文件内容变更了,浏览器是怎么知道的呢?css 文件内容变更了,没有刷新页面 怎么加载最新的内容呢?只要解决了上面两个问题,我们就算是完成了。因为剩下得就是编码了,这都好说。【结果】文件变更了,我怎样通知浏览器?浏览器和服务器保持着连接。 服务器有什么事儿直接通过当前的链接告诉浏览器就可以了。连接肯定是长连接,不然怎么实时通信。保持长连接有哪些方法呢? 轮询?eventSorce? 都不够好。 有么有更好的方案呢?那就是 - websocket浏览器和服务器先建立好链接,服务器就可以直接通知到客户端了。这个时候无论是 pc 上还是手机上都可以随时根据需要刷新或者加载资源。css 更新,css 本身是可以通过 dom 去操作的。浏览器只要知道是 css更新了,直接重新加载当前的 css 文件就可以了。架构思维咱们在重新捋捋这个架构。服务器和浏览器通过 websocket 建立链接。服务器和浏览器规定好消息的规则,是刷新页面还是更新 css。基本架构有了,其他的就是编码实现了。服务端使用 node 创建一个 ws 服务。浏览器使用 websocket 创建一个链接和服务器进行链接。双方通过对应的 api 进行数据的操作。代码实现本文只是讲解下思路,并没有实现文件的监听,文件监听后面会介绍。咱暂时先确定好两个消息规则:浏览器收到 命令为:htmlFileChange ,此时浏览器刷新;浏览器收到命令为:cssFileChange,此时不刷新页面,自动加载 css 文件;具体代码如下:服务端://web-socket.js 创建 ws 服务var ws = require(“nodejs-websocket”);//需要安装这个包module.exports = function(){ return function () { console.log(“重度前端提醒,开始建立连接…”) var sessions = [];//存放每一个链接对象 var server = ws.createServer(function (conn) { sessions.push(conn);//将新的链接对象存放在数组中 conn.on(“text”, function (str) { console.log(“收到的信息为:” + str) sessions.forEach(item=>{ item.sendText(str) //所有客户端都发送消息 }); }); conn.on(“close”, function (code, reason) { console.log(“关闭连接”) }); conn.on(“error”, function (code, reason) { console.log(“异常关闭”) }); }).listen(6152) console.log(“WebSocket建立完毕”) }}//server.js http 服务代码let http = require(‘http’);let fs = require(‘fs’);let webSocket = require(’./node/web-socket’);const BASEROOT = process.cwd();//获得当前的执行路径//读取 index.html内容let getPageHtml = function () { let data = fs.readFileSync(BASEROOT+’/html/index.html’); return data.toString();}//读取 index.css内容let getPageCss = function () { let data = fs.readFileSync(BASEROOT + ‘/html/index.css’); return data.toString();}//node 端 开启 ws 服务webSocket()();http.createServer(function (req, res) {//创建 http 服务 let body = ‘’,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(‘重度前端提醒…… server start’);页面截图客户端//index.html 布局代码省略 const nick = [‘a’, ‘b’, ‘c’, ’d’, ’e’, ‘f’, ‘g’, ‘aa’, ‘cc’]; let index = 0; // Create WebSocket connection. const socket = new WebSocket(‘ws://10.70.69.191:6152’); // Connection opened socket.addEventListener(‘open’, function (event) { socket.send(navigator.userAgent); }); // 监听服务器推送的消息 socket.addEventListener(‘message’, function (event) { if (index > nick.length) { index = 0;//只是为了每次输出不同的昵称,没实际意义 } var ele = document.createElement(‘div’); ele.innerHTML = nick[index] + ‘:’ + event.data; if (event.data === ‘htmlFileChange’) { //html 文件更新了 刷新当前页面 location.reload(); } if (event.data === ‘cssFileChange’) { //css 文件更新了 刷新当前页面 reloadCss(); } document.getElementById(‘content’).append(ele); index += 1; }); //重新加载 css function reloadCss() { var cssUrl = [], links = document.getElementsByTagName(’link’), len = links.length; for (var i = 0; i < len; i++) { var url = links[i].href; document.getElementsByTagName(‘head’)[0].appendChild(getLinkNode(url)); //创建新的 css 标签 document.getElementsByTagName(‘head’)[0].removeChild(links[i]); //移除原有 css } console.log(document.getElementsByTagName(‘head’)[0]) function getLinkNode(cssUrl) { var node = document.createElement(’link’); node.href = cssUrl; node.rel = ‘stylesheet’; return node; } } document.getElementById(‘btn1’).onclick = function () { socket.send(document.getElementById(‘message’).value); document.getElementById(‘message’).value = ‘’; }index.css 内容 input { outline: none; } #content { height: 400px; width: 400px; border: solid 1px #ccc; color: red; }代码倒是次要的。解决问题的思路才重要。有了解决问题的架构思维,代码实现都好说。写到这里咱们还能顺便实现一个群聊。本质就是服务器和浏览器怎样实时通信,解决了这个问题,其他的都是小事儿。这个技术实现还是比较简单的。另外对模块热更新和 websocket 原理有兴趣的可以研究下,后面可能也会介绍。总结本文主要介绍简易版热更新的原理;热更新实现思路和代码实现;架构思维:简单的带出架构思维的作用;希望本文对你有用。原创不易、请多鼓励自家观点、欢迎打脸代码示例下载https://github.com/bigerfe/ho…作者:微信公众号 - 重度前端 主笔:八门欢迎关注 重度前端-每周5原创全栈干货+每周三深度技术文章