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クライアントには、HTMLドキュメントの代わりに、ページの最初のフレームがトゥルーカラーのANSIテキストとして返されます。設定は不要です。

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() も解決されないため、エフェクトで読み込むデータは読み込み中の状態のままです。

  • サイズ:80 × 24セルです。ビューポートが固定のアプリ(viewport.responsive: false)では、代わりに viewport.width × viewport.height を使用します。
  • 色:アプリの viewport.theme に基づく24ビットSGRエスケープコードを使用します。各行はリセットで終わり、フレームは改行で終わります。
  • ステータス:200、または一致するページがない場合やページが notFound() を呼び出した場合は、アプリのnot-foundページとともに 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, buntext build でプリレンダリングリクエスト時にレンダリング
vercel, cloudflaretext build でプリレンダリングHTMLページ
staticHTMLページHTMLページ

サーバーレンダリングされるページには text start または bun が必要です(デプロイを参照)。

静的ホストはクライアントごとに異なるレスポンスを返せないため、static アダプターはフレームに対応していません。VercelとCloudflareでは、静的ページのフレームがビルドに含まれます。vercel アダプターと cloudflare アダプターはレンダラーをデプロイしないため、これらの環境では動的ページ([id]、force-dynamic)はHTMLを返します。

text start と bun dist/server.js は、残りのページを .text/server/live.mjs でリクエスト時にレンダリングし、直近の128フレームを10秒間保持します。各サーバーが10秒間にレンダリングする未キャッシュのページは、最大20ページです。この上限を超えると、処理枠が回復するまでcurlにはHTMLページが返されます。ページモジュールがトップレベルで window を読み取るなどの理由で、サーバー上で live.mjs を読み込めない場合、それらのページは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

curlは -L を指定しない限り、リダイレクトを追跡しません。Vercelは http:// リクエストを https:// にリダイレクトし、Cloudflareも常にHTTPSを使用が有効な場合は同様に動作するため、curl http://… はフレームの代わりにリダイレクトを出力します。共有するURLには https:// を使用してください。

カスタムサーバー

@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) は、Webの Headers またはNodeの IncomingHttpHeaders を使った (method, headers) も受け付けます。frameToAnsi(buffer, { theme }) は、レンダリング済みの CellBuffer をフレームワークと同じ方法でエンコードします。

GitHubでこのページを編集