xterm.jsが楽しそう
ブラウザにTerminalを設置できるxterm.jsというライブラリがある。VSCodeのTerminalやHyperなどに使われている。
xterm.jsが提供するのはざっくり言ってしまえばTerminalの形をしたテキストフィールドのみ。実際にTerminalに接続したりキーボードの入力を送信したりする処理は自分で書く必要がある。
xterm.jsを触ってみた
xterm.jsを組み込むフロントエンドにNext.js、xtermとやりとりするためのサーバーサイドをNestJSを使って書いてみた。
ブラウザから自分のTemrinalに接続
vimとtmuxの挙動が若干怪しいが、いちおう接続するところまではいけたので満足。
以下メモ
xterm.jsの流れ
ReferenceError: self is not definedが出る
nextjsのSSRを用いているから出るエラーだった。試しにcreate-react-appでやったらエラーは出なかった。
完璧な回答がここにあった。
dynamic importで解決。ReactHooksコンポーネントの場合、then(mod)が必要。
const Terminal = dynamic( () => import('@/components/terminal').then((mod) => mod.TerminalComponent), { ssr: false, } ) const Index: React.FC = () => { const classes = useStyles() return ( <Layout> <div className={classes.container}> <Terminal /> </div> </Layout> ) }
document.getElementByIdをReactHooksでする
デモだとindex.htmlに<div id="terminal"></div>
と書いてあって、tsファイル内でterm.open(document.getElementById('terminal'))
をする形がだったが、
ReactHooksだとindex.htmlがないからどうしたらいいのかわからなかった。
下記のような形でいける。
import React, { useEffect } from 'react' import { Terminal } from 'xterm' export const TerminalComponent = () => { const term = new Terminal() useEffect(() => { term.open(document.getElementById('terminal')) }) return <div id="terminal" /> }
useRefをつかってもできる
import React, { useEffect } from 'react' import { Terminal } from 'xterm' export const TerminalComponent = () => { const ref = React.useRef<HTMLDivElement>() const term = new Terminal() useEffect(() => { term.open(ref.current) }) return <div ref={ref}></div> }
複数のTerminalを置くとき、cssが効かない
Propsでidを渡すようにしたら解決した。document.getElementById("terminal")
でやっていたため、2つ目のTerminalが1つ目に奪われてしまっている状態であった。なのでPropsでidを渡すようにして、document.getElementById(id)
としたらいけた。
nestjsでサーバーを構築
$ yarn global add @nestjs/cli $ yarn global add @nestjs/schematics $ nest new server
Error: Collection "@nestjs/schematics" cannot be resolved.が出る。yarn global add @nestjs/schematics
が必要。
node-configでTypeError: Cannot read property 'get' of undefinedがでる
importの仕方を変えたら解決した。