You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js实现前端终端实时显示sass --watch输出的问题

问题:前端模拟终端实时展示sass --watch输出,res.render仅能调用一次如何实现多次返回数据

我希望在前端模拟终端,实时展示sass --watch的输出,但res.render仅能调用一次,请问有什么方法可以实现多次返回数据?

后端代码(server.js)

app.get('/sass', function (req, res) {
  path1 = req.query.chemin;
  path2 = req.query.chemin;
  
  const ls = spawn('sass', ['--watch path1 path2'], { shell: true });

  ls.stdout.on('data', (data) => {
    
    console.log(ls.pid);
    message = JSON.stringify(`stdout: ${data}`);

    res.render('index', { messagee: message, path: firstpath });

  });
  
});

前端代码(index.ejs)

<div id="terminal">  <%= messagee %> </div>

项目结构

server.js
- views
  -- index.ejs
- public
  -- css
  -- js
  -- img

解决方案

HTTP请求是一次性响应模型,res.render只能完成单次页面渲染,要实现实时数据推送,推荐使用Server-Sent Events(SSE)——它适合这种单向的日志/输出推送场景,实现步骤如下:

1. 后端改造:用SSE推送sass --watch输出

修改接口逻辑,不再调用res.render,而是返回持续的SSE数据流:

app.get('/sass-stream', function (req, res) {
  // 设置SSE响应头,保持连接存活
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  const path1 = req.query.chemin;
  const path2 = req.query.chemin; // 注意:此处path1和path2取值相同,若为笔误请修正实际路径

  // 启动sass监听进程(拆分参数避免shell解析问题)
  const ls = spawn('sass', [`--watch`, path1, path2], { shell: true });

  // 监听标准输出,推送给前端
  ls.stdout.on('data', (data) => {
    const msg = `stdout: ${data.toString().trim()}`;
    // 按SSE格式写入数据:data: 内容\n\n
    res.write(`data: ${JSON.stringify(msg)}\n\n`);
  });

  // 监听错误输出
  ls.stderr.on('data', (data) => {
    const errMsg = `stderr: ${data.toString().trim()}`;
    res.write(`data: ${JSON.stringify(errMsg)}\n\n`);
  });

  // 进程退出时关闭连接
  ls.on('close', (code) => {
    res.write(`data: ${JSON.stringify(`sass进程已退出,退出码:${code}`)}\n\n`);
    res.end();
  });

  // 前端断开连接时,杀死sass进程避免资源浪费
  req.on('close', () => {
    ls.kill();
  });
});

2. 前端改造:接收SSE并更新终端内容

修改index.ejs,添加JS代码监听SSE流,实时追加输出到终端:

<div id="terminal" style="background: #1e1e1e; color: #d4d4d4; padding: 12px; font-family: monospace; min-height: 240px; overflow-y: auto;"></div>

<script>
const terminal = document.getElementById('terminal');
// 替换成实际的路径参数,或从页面渲染数据中获取
const targetPath = '<%= path %>';
// 建立SSE连接
const eventSource = new EventSource(`/sass-stream?chemin=${encodeURIComponent(targetPath)}`);

// 接收推送的消息并更新终端
eventSource.onmessage = function(e) {
  const message = JSON.parse(e.data);
  terminal.innerHTML += message + '<br>';
  // 自动滚动到底部
  terminal.scrollTop = terminal.scrollHeight;
};

// 处理连接错误
eventSource.onerror = function(e) {
  terminal.innerHTML += '连接异常,已断开<br>';
  eventSource.close();
};
</script>

3. 补充初始页面路由

保留一个基础路由用于渲染初始页面:

app.get('/', function(req, res) {
  res.render('index', { path: req.query.chemin || '' });
});

用户访问页面后,前端会自动建立SSE连接,后端将sass --watch的实时输出持续推送到前端终端。

内容的提问来源于stack exchange,提问作者William Gaonarch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 02:05:20