返回

不仅仅是shell组件:在React中使用Xterm+Websocket的多样化应用场景

前端

跨越Shell组件的局限:React中Xterm+Websocket的多维应用

过去的一段时间里,我们在React中使用Xterm和Websocket实现了前端输入shell命令到K8s流式处理的功能。在这一过程中,我们遇到了很多问题和特殊情况,但网上并没有相关的可以借鉴的资源。通过一点一滴的定位和解决问题,我们最终完成了这一目标。因此,我们决定在此做一个小结,希望能帮助其他遇到类似问题的开发者。

丰富的应用场景

最初,我们只是想使用Xterm和Websocket来创建一个shell组件,但在开发过程中,我们意识到它们的应用场景远远不止于此。我们发现了更多激动人心的可能性,例如:

K8s流式处理

我们可以在React中使用Xterm和Websocket来实现K8s的流式处理。通过这种方式,我们可以直接在前端查看K8s的日志流,而无需打开单独的终端窗口或使用kubectl命令行工具。这在对K8s进行故障排除或调试时非常有用。

Web终端

我们可以使用Xterm和Websocket来创建一个功能齐全的Web终端。这将允许用户直接在浏览器中访问远程服务器或容器的shell。这对于系统管理员或开发人员来说非常有用,因为他们可以随时随地访问他们的服务器或容器。

Websocket通信

我们可以使用Xterm和Websocket来建立Websocket通信。这将允许我们创建实时聊天应用程序或其他需要双向通信的应用程序。这对于构建协作工具或游戏非常有用。

K8s Web终端

我们可以使用Xterm和Websocket来创建一个K8s Web终端。这将允许用户直接在浏览器中访问K8s集群中的pod或容器的shell。这对于管理和维护K8s集群非常有用。

远程终端

我们可以使用Xterm和Websocket来创建一个远程终端。这将允许用户从任何地方访问他们的计算机或服务器的shell。这对于远程工作或故障排除非常有用。

更进一步

这些只是Xterm和Websocket在React中的一些应用场景。随着技术的发展,我们相信还有更多有趣的应用场景等待我们去发现。

实际示例和代码片段

为了帮助您更好地理解这些应用场景,我们将提供一些实际示例和代码片段。

K8s流式处理

import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { WebSocketsTerminal } from 'xterm-terminal';
import { useEffect, useRef } from 'react';

const K8sStreamingTerminal = () => {
  const terminalRef = useRef(null);
  const term = new WebSocketsTerminal('ws://localhost:8080/websocket');

  useEffect(() => {
    const xterm = new Terminal({
      cursorBlink: true,
    });
    const attachAddon = new AttachAddon(term);
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    xterm.loadAddon(attachAddon);
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(webLinksAddon);
    xterm.open(terminalRef.current);
    attachAddon.attach(xterm, term);
    fitAddon.fit();
  }, []);

  return <div ref={terminalRef} />;
};

export default K8sStreamingTerminal;

Web终端

import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { WebSocketsTerminal } from 'xterm-terminal';
import { useEffect, useRef } from 'react';

const WebTerminal = () => {
  const terminalRef = useRef(null);
  const term = new WebSocketsTerminal('ws://localhost:8080/websocket');

  useEffect(() => {
    const xterm = new Terminal({
      cursorBlink: true,
    });
    const attachAddon = new AttachAddon(term);
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    xterm.loadAddon(attachAddon);
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(webLinksAddon);
    xterm.open(terminalRef.current);
    attachAddon.attach(xterm, term);
    fitAddon.fit();
  }, []);

  return <div ref={terminalRef} />;
};

export default WebTerminal;

Websocket通信

import { WebSocket } from 'ws';
import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { useEffect, useRef } from 'react';

const WebsocketCommunication = () => {
  const terminalRef = useRef(null);
  const ws = new WebSocket('ws://localhost:8080/websocket');

  useEffect(() => {
    const xterm = new Terminal({
      cursorBlink: true,
    });
    const attachAddon = new AttachAddon(ws);
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    xterm.loadAddon(attachAddon);
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(webLinksAddon);
    xterm.open(terminalRef.current);
    attachAddon.attach(xterm, ws);
    fitAddon.fit();
  }, []);

  return <div ref={terminalRef} />;
};

export default WebsocketCommunication;

K8s Web终端

import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { WebSocketsTerminal } from 'xterm-terminal';
import { useEffect, useRef } from 'react';

const K8sWebTerminal = () => {
  const terminalRef = useRef(null);
  const term = new WebSocketsTerminal('ws://localhost:8080/websocket');

  useEffect(() => {
    const xterm = new Terminal({
      cursorBlink: true,
    });
    const attachAddon = new AttachAddon(term);
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    xterm.loadAddon(attachAddon);
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(webLinksAddon);
    xterm.open(terminalRef.current);
    attachAddon.attach(xterm, term);
    fitAddon.fit();
  }, []);

  return <div ref={terminalRef} />;
};

export default K8sWebTerminal;

远程终端

import { Terminal } from 'xterm';
import { AttachAddon } from 'xterm-addon-attach';
import { FitAddon } from 'xterm-addon-fit';
import { WebLinksAddon } from 'xterm-addon-web-links';
import { WebSocketsTerminal } from 'xterm-terminal';
import { useEffect, useRef } from 'react';

const RemoteTerminal = () => {
  const terminalRef = useRef(null);
  const term = new WebSocketsTerminal('ws://localhost:8080/websocket');

  useEffect(() => {
    const xterm = new Terminal({
      cursorBlink: true,
    });
    const attachAddon = new AttachAddon(term);
    const fitAddon = new FitAddon();
    const webLinksAddon = new WebLinksAddon();
    xterm.loadAddon(attachAddon);
    xterm.loadAddon(fitAddon);
    xterm.loadAddon(webLinksAddon);
    xterm.open(terminalRef.current);
    attachAddon.attach(xterm, term);
    fitAddon.fit();
  }, []);

  return <div ref={terminalRef} />;
};

export default Remote