node 实现日志打印输出到前端显示

1,944 阅读4分钟

前言

最近接一个需求,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服务端配置

  1. 服务端安装Socket.IO

$ npm install --save -dev socket.io

  1. 服务端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.

image.png 这是提醒我们需要给后端服务配置跨域。

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

再次运行前后端服务 前端控制台打印如下:

image.png

后端控制台打印如下:

image.png

至此,我们已经打通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部分。 然后我们刷新查看,可以看到连接成功后的通信截图:

image.png

日志显示部分,我们采用的插件是xterm,你可以这里与我们的主题核心无关,你可以百度到相关文档使用。

我们来看一下最终效果:

image.png

如果想将shell命令行中的错误输出到前端显示,可以采用try{}catch{}捕获错误,通过socket.on('send log', function(msg){})方法输出到前端显示。