前言
最近接一个需求,vue实现的前端,node服务写的中间层,生成前端应用,主要功能有:编译打包应用,压缩代码传到服务端。因在发布应用时,不知道node服务端发布的应用进程如何,应用编译发布是否成功,需要将日志打印输出到前端的页面中展示。
最近初学node,在网上找了一圈怎么实现前端后分离的node日志打印输出功能,找了一圈没找到合适的。现简单的实现了该功能,将大概的实现过程记录下来。
基础知识
我们先来了解一下基础知识:
websoket
WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例如 Chrome,Safrie,Firefox,Opera,IE等等,对该协议支持最早的应该是chrome,从chrome12就已经开始支持,随着协 议草案的不断变化,各个浏览器对协议的实现也在不停的更新。该协议还是草案,没有成为标准,不过成为标准应该只是时间问题了。
Socket.IO
Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5
Socket.IO支持4种协议:WebSocket、htmlfile、xhr-polling、jsonp-polling,它会自动根据浏览 器选择适合的通讯方式,从而让开发者可以聚焦到功能的实现而不是平台的兼容性,同时Socket.IO具有不错的稳定性和性能。
第一步:解决实时通信问题
express在前面的工作中已经配置完成,本文只讲述如何引入soket.io完成日志功能,配置Socket.IO之前请先配置好express。
一、Node服务端配置
- 服务端安装Socket.IO
$ npm install --save -dev socket.io
- 服务端Socket.IO注册
const express = require('express')
const app = express()
const http = require('http').createServer(app)
const io = require('socket.io')(http)
const port = 3000
// 原来没引入socket.io前是app.listen
// 这里要用server去监听端口,不然找不到socket.io.js文件
http.listen(port, () => {
console.log(`服务启动: http://localhost:${port}`)
})
io.on('connection', (soket) => {
console.log('已经连接上了', soket)
})
二、web客户端配置
1. 安装客户端socket.io-client
npm install socket.io-client
2. 在具体需要通信的js文件中引入如下语句
import { io } from "socket.io-client";
...
// http://localhost:3000 这里的端口号地址和服务端的一致
const socket = io("http://localhost:3000")
console.log('ws://localhost:3000', socket)
socket.on("connect", (socket) => {
console.log('socket', socket)
})
完成以上配置后,运行一下,报错
Access to XMLHttpRequest at 'http://localhost:3000/socket.io/?EIO=4&transport=polling&t=Nu518Zd' from origin 'http://localhost:9528' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这是提醒我们需要给后端服务配置跨域。
3. 跨域通信
我们将node服务端的代码改写如下:
const express = require('express')
const app = express()
const http = require('http').createServer(app)
// {cors: true} 解决跨域问题
const io = require('socket.io')(http, {cors: true})
const port = 3000
再次运行前后端服务 前端控制台打印如下:
后端控制台打印如下:
至此,我们已经打通socket通信连接。
接下来,我们需要控制台接收我们运行时的日志,传送到前端接收打印。
第二步:将node服务运行时的输出代码,输出到前端显示
在网上找的node日志实现,大部分都是把日志写到本地文件中,再读取出来,并不是实时打印。而且时间有限,暂时没有那么多时间研究,如何把日志文件写到本地中,再实时输出到前端。
想了个比较笨的方法,大概的思路是,在每次node需要查看运行情况的位置,手动通过Socket.IO的广播功能,将信息传送到前端,核心代码如下:
1. Node服务端:
socket.emit('send log', {
status: 'success',,
statusCode: 200,
data: `需要传送给前端的信息`
});
2. web客户端:
const socket = io("http://localhost:3000" , {path: '/socket.io/log/'})
socket.on("connect", (socket) => {
that.$emit('writeMsg', {
data: '已连接至应用生成器服务器...'
})
})
socket.on('send log', function(msg){
console.log('msg:', msg)
// 这里的msg就是后端传过的语句,你可以采用xterm插件在前端显示
})
socket.on('error', () => {
console.log('连接错误 ')
})
socket.on('disconect', (msg) => {
console.log('关闭链接')
})
如未写path,socket.io插件默认请求URL/socket.io/, 你可以根据你的实际情况写path部分。 然后我们刷新查看,可以看到连接成功后的通信截图:
日志显示部分,我们采用的插件是xterm,你可以这里与我们的主题核心无关,你可以百度到相关文档使用。
我们来看一下最终效果:
如果想将shell命令行中的错误输出到前端显示,可以采用try{}catch{}捕获错误,通过socket.on('send log', function(msg){})方法输出到前端显示。