curl and Terminal Clients

curl, Wget, HTTPie and xh get a page's first frame as truecolor ANSI text. Configure its size or turn it off.

终端 HTTP 客户端获取页面的第一帧,格式为真彩色 ANSI 文本,而非 HTML 文档。无需任何配置。

curl https://my-app.example.com/about

哪些请求会获取帧

请求满足以下所有条件时会获取帧:

  • 方法为 GET 或 HEAD;
  • User-Agent 以 curl/、Wget/、wget2/、HTTPie/ 或 xh/ 开头;
  • 缺少 Accept 标头,或该标头不包含 text/html。

浏览器、爬虫和链接预览会获取 HTML 页面。要用 curl 获取 HTML,请显式请求:

curl -H 'Accept: text/html' https://my-app.example.com/about

是否返回帧在即将提供页面时决定:即在中间件、rewrites 和路由处理程序之后,且文件或最后一段包含点号的路径绝不会返回帧。中间件重定向、401 状态码、标头和重写对 curl 和浏览器同样生效。/api/health 仍会运行其处理程序,/robots.txt 仍会提供该文件。

帧的内容

帧是页面的首次渲染,与预渲染外壳一样:所有仍在等待的 <Suspense> 边界都会显示其回退内容。异步服务端组件不会运行,fetch() 也永远不会完成,因此在 effects 中加载的数据会保持加载状态。

  • 尺寸:80 × 24 个单元格。使用固定视口(viewport.responsive: false)的应用则采用 viewport.width × viewport.height。
  • 颜色:使用应用的 viewport.theme 中的 24 位 SGR 转义码。每行以重置码结尾,帧以换行符结尾。
  • 状态:200,或在没有匹配页面或页面调用 notFound() 时返回 404 及应用的未找到页面。渲染时调用 redirect() 的页面会提供 HTML。

响应的类型为 text/plain; charset=utf-8,并带有 Vary: User-Agent, Accept 和 Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate,因此共享缓存不会存储帧并将其提供给浏览器。对于 curl 获取帧的路径,其 HTML 页面也带有相同的 Vary 标头。

支持的运行环境

托管环境静态页面动态页面、未知路径
text dev按请求渲染按请求渲染
text start, bun由 text build 预渲染按请求渲染
vercel, cloudflare由 text build 预渲染HTML 页面
staticHTML 页面HTML 页面

服务端渲染的页面需要 text start 或 bun(参见部署)。

静态托管环境无法为不同客户端提供不同响应,因此 static 适配器不支持帧。在 Vercel 和 Cloudflare 上,静态页面的帧随构建产物一起发布。动态页面([id]、force-dynamic)在那里提供 HTML,因为 vercel 和 cloudflare 适配器不部署渲染器。

text start 和 bun dist/server.js 使用 .text/server/live.mjs 按请求渲染其余页面,并将最近 128 帧保留 10 秒。每台服务器每 10 秒最多渲染 20 个未缓存的页面。超过此限额后,curl 会获取 HTML 页面,直到额度恢复。如果服务器无法加载 live.mjs,例如某个页面模块在顶层读取 window,这些页面就会提供 HTML。

text build 会报告预渲染的帧:

 ✓ Prerendering curl frames (5/5)

配置

更改整个应用的尺寸,或关闭帧:

text.config.tsts
import { defineConfig } from "@textjs/app";export default defineConfig({  ansi: { cols: 100, rows: 30 },  // ansi: false,});

页面可以更改自身尺寸,也可以向终端提供 HTML:

app/dashboard/page.tsxtsx
export const ansi = { cols: 120, rows: 40 };// export const ansi = false;

尺寸限制在 1~500 个单元格之间。在 text.config.ts 中设置 ansi: false 后,页面导出项会被忽略。

明文 HTTP

除非传入 -L,否则 curl 不会跟随重定向。Vercel 会将 http:// 请求重定向到 https://,启用 始终使用 HTTPS 的 Cloudflare 也会如此,因此 curl http://… 会输出重定向响应而非帧。分享 https:// URL。

自定义服务器

@textjs/app/ansi 导出检测和响应辅助函数,供不运行 text start 或适配器的服务器和函数使用:

import { ansiResponse, wantsAnsi } from "@textjs/app/ansi";import { frameToAnsi } from "@textjs/react";if (wantsAnsi(request)) return ansiResponse(frameToAnsi(buffer, { theme: "geistDark" }), request.method);

wantsAnsi(request) 也接受 (method, headers),其中标头可使用 Web Headers 或 Node 的 IncomingHttpHeaders。frameToAnsi(buffer, { theme }) 以与框架相同的方式编码已渲染的 CellBuffer。

在 GitHub 上编辑此页