在终端中运行

使用 text run 在终端中全屏运行同一仪表盘。

本章应用正在你的控制台中运行。按 ⌘⌥JCtrl+Shift+J⌘⌥KCtrl+Shift+K⌘⌥C 打开控制台(先开启开发者功能),然后试用。
观看本章3:31

本章内容

  • `text run`
  • 按 `q` 退出
  • 自己的 CLI
  • 差异

text run 在终端中运行同一个应用。布局、组件、按键映射和路由处理程序共用,输出为真彩色 ANSI,而非 %c CSS span。

text run

添加一个脚本并运行:

package.json+2-1json
  "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 route

text run 导入 app/ 中的所有文件,使用内存中的历史记录挂载 App Router,并全屏绘制。<Link>、useRouter()、notFound() 和 redirect() 的用法不变,同源 fetch("/api/…") 调用会在进程内运行你的路由处理程序。Ctrl+C 退出并恢复终端的回滚缓冲区。此命令需要 Bun。

按 q 退出

终端用户习惯按 q 退出。useApp().exit() 卸载应用并恢复终端;在浏览器中则卸载控制台应用。

app/layout.tsx+3tsx
新增: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 即可挂载一个元素,而 fetch("/api/…") 只有在 text run 下才能调用路由处理程序,因此要将数据传给组件:

cli.tsxtsx
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。

差异

终端重绘更快(最高 60 fps,而非约 15 fps),网格尺寸随窗口调整,而非随停靠的控制台调整。图像需要像素数据,而非 URL。其余部分,包括这个仪表盘,都使用相同的代码。

试用

这是本章结束时的 Acme Deploys,正在 DevTools 中运行。点击输入区,然后使用下列按键。

▼ 09 · 在终端中运行

打开控制台

⌘⌥J
CtrlShiftJ
⌘⌥K
CtrlShiftK
⌘⌥C

应用在 DevTools 中渲染。先在 Safari 设置 → 高级中开启“显示网页开发者功能”。 然后点击这里并按 Enter。

在桌面端打开

此应用在 DevTools 控制台中渲染,需要桌面浏览器。

测验

2 个问题

回答所有问题以完成本章。

应用在终端中运行时有什么变化?

 

应用如何自行退出?