ターミナルでの実行
text runで同じダッシュボードをターミナルの全画面で実行します。
この章の内容
- `text run`
- `q` で終了
- 独自のCLI
- 相違点
text run は同じアプリをターミナルで実行します。レイアウト、コンポーネント、キーマップ、ルートハンドラーを共有し、出力には %c CSSスパンの代わりにトゥルーカラーANSIを使います。
text run
スクリプトを追加して実行します。
"scripts": { "dev": "text dev", "build": "text build",削除: "start": "text start"追加: "start": "text start",追加: "tui": "text run" },bun run tui # render ./app at /bun run tui -- --path /deployments # start on another routetext run は app/ 内のすべてのファイルをインポートし、インメモリーの履歴でApp Routerをマウントして全画面に描画します。<Link>、useRouter()、notFound()、redirect() はそのまま動作し、同一オリジンの fetch("/api/…") 呼び出しはプロセス内でルートハンドラーを実行します。Ctrl+C で終了し、スクロールバックを復元します。Bunが必要です。
q で終了
ターミナルユーザーは q での終了を想定しています。useApp().exit() はアプリをアンマウントしてターミナルを復元します。ブラウザーではコンソールアプリをアンマウントします。
追加:import { useApp } from "@textjs/app";export default function RootLayout({ children }: { children?: ReactNode }) {追加: const app = useApp(); useInput((e) => { if (e.key === "backspace") router.back();追加: if (e.input === "q") app.exit(); });独自のCLI
単一のコンポーネントには renderToTerminal を使います。App Routerを使わずに1つの要素をマウントし、fetch("/api/…") がルートハンドラーに届くのは text run での実行時のみなので、コンポーネントにデータを渡します。
import { renderToTerminal } from "@textjs/app/terminal";import { Table } from "@textjs/app";import { DEPLOYMENTS } from "./lib/deployments";const columns = [{ key: "commit", header: "Commit" }, { key: "project", header: "Project", width: 10 }];const app = await renderToTerminal(<Table columns={columns} rows={DEPLOYMENTS} autoFocus />);await app.waitUntilExit();bun cli.tsx で実行します。DeploymentsPage は行データを取得するため、text run が必要です。
相違点
ターミナルは再描画が速く(約15fpsに対して最大60fps)、ドッキングされたコンソールではなくウィンドウに合わせてグリッドのサイズを調整します。画像にはURLではなくピクセルデータが必要です。このダッシュボードを含め、それ以外はすべて同じコードです。
試す
これは章の終わりに完成するAcme Deploysで、DevToolsで動作しています。パッドをクリックして、以下のキーを使います。
コンソールを開く
アプリはDevToolsに描画されます。まずSafariの「設定」→「詳細」で「Webデベロッパ用の機能を表示」をオンにします。 次にここをクリックして、Enterを押します。
デスクトップで開く
このアプリはDevToolsのコンソールに描画されるため、デスクトップブラウザーが必要です。
クイズ
2問すべての問題に回答すると章を完了できます。