提出问题
- 文件内容变更了,浏览器是怎么知道的呢?
- css 文件内容变更了,没有刷新页面 怎么加载最新的内容呢?
结论
websocket
浏览器和服务器先建立好链接,服务器就可以直接通知到客户端了。这个时候无论是 pc 上还是手机上都可以随时根据需要刷新或者加载资源。
实现思维
- 服务器和浏览器通过 websocket 建立链接。
- 服务器和浏览器规定好消息的规则,是刷新页面还是更新 css。
1.服务端使用 node 创建一个 websocket 服务。
2.浏览器使用 websocket 创建一个链接和服务器进行链接。
3.双方通过对应的 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 = '';
}
代码地址:https://github.com/bigerfe/hotUpdate-demo
原文链接: 简单聊聊前端开发中的热更新原理
网友评论