Deployen

Deploye mit text build --adapter static, bun, vercel oder cloudflare, oder führe text start hinter einem Proxy aus.

text build erzeugt ein portables dist/. Ein Adapter wandelt es in die Ausgabe um, die eine Plattform erwartet.

Adapter

text build --adapter <name>
AdapterAusgabeAusführung
(keiner)dist/ + dist/.text/servertext start (Node)
staticdist/Jeder statische Host
bundist/server.jsbun dist/server.js
vercel.vercel/outputVercel (Build Output API v3)
cloudflaredist/ + _worker.jsCloudflare Pages

Der Adapter kann auch über TEXTJS_ADAPTER festgelegt werden. Wenn text build auf Vercel (VERCEL=1) oder Cloudflare Pages (CF_PAGES=1) läuft, wird automatisch der passende Adapter ausgewählt.

Die Server-Adapter (bun, vercel und cloudflare) führen dieselbe Pipeline wie text start aus: Middleware, rewrites, Route-Handler mit dem Route-Cache, statische Assets und dann das Konsolendokument für Seiten-URLs. Terminal-Clients wie curl erhalten stattdessen den ersten Frame der Seite als ANSI-Text. Auf vercel und cloudflare gilt das nur für statische Seiten (siehe curl und Terminal-Clients). Die Server-Adapter liefern Dateien mit Hash im Namen unter /assets/ mit Cache-Control: public, max-age=31536000, immutable aus.

Statisch

text build --adapter static

Verwende diesen Adapter für Hosts ohne Server, etwa GitHub Pages, S3 oder ein CDN. GET-Route-Handler mit dynamic = "force-static" oder revalidate werden per Prerendering in Dateien umgewandelt: Aus app/api/feed.json/route.ts wird dist/api/feed.json. Eine Kopie von index.html wird in 404.html geschrieben, damit Deep-Links die Konsolen-App öffnen. Statische Hosts können curl nicht von einem Browser unterscheiden, daher erhält curl die HTML-Seite.

Der Build schlägt fehl und listet alle Gründe auf, wenn die App einen Server benötigt: middleware.ts, serverseitig gerenderte Routen, dynamische Route-Handler, Route-Handler mit dynamischen Segmenten oder andere Methoden als GET. Konfiguriere rewrites stattdessen auf dem Host.

Bun

text build --adapter bunPORT=8080 bun dist/server.js

Der bun-Adapter schreibt einen einzelnen, eigenständigen Server, der zur Laufzeit keine node_modules benötigt. Er liest PORT (Standard 3000) und HOSTNAME (Standard 0.0.0.0) und liefert niemals server.js oder .text/ aus. Er läuft als langlebiger Prozess und hostet daher wie text start auch serverseitig gerenderte Routen (export const runtime = "server") und deren Live-Sitzungen. Verwende ihn in einem Container:

Dockerfiletext
FROM oven/bun:1COPY dist /appCMD ["bun", "/app/server.js"]

Vercel

text build --adapter vercelvercel deploy --prebuilt

Oder pushe in ein mit Vercel verbundenes Git-Repository: Der Build führt text build aus, erkennt Vercel und schreibt .vercel/output.

AusgabeInhalt
static/Der Client-Build (unter basePath)
functions/_textjs/server.funcEine Node.js 22-Funktion, die alle Route-Handler bedient, mit Streaming
functions/_middleware.funcEdge-Routing-Middleware: middleware.ts und kanonische Pfade für jede App
config.jsonAsset-Header, Middleware-Matcher, Rewrites, Handler-Routen und das Konsolendokument

Die Edge-Middleware verwendet das Protokoll x-middleware-next / x-middleware-rewrite, sodass Header-Überschreibungen und Rewrites im Router von Vercel stattfinden, bevor die Funktion oder das CDN erreicht wird. Alle Matcher teilen sich ein src-Muster für Routen. Anfragen, die kein Matcher abdeckt, überspringen die Middleware, es sei denn, ihr Pfad liegt möglicherweise nicht in kanonischer Form vor (Prozentkodierungen, Zeichen, die ein URL-Parser kodiert, //, .- oder ..-Segmente, ein abschließender Schrägstrich). Die Middleware gleicht dann den kanonischen Pfad ab, prüft has / missing und schreibt die Anfrage auf diesen Pfad um, damit Vercel sie genauso routet. Apps ohne middleware.ts erhalten dieselbe Edge-Funktion, die nur das Rewrite ausführt. Da jeder Build eine Edge-Funktion enthält, deploye über ein angemeldetes Vercel-Konto: Anonyme Deployments (vercel deploy --temporary) akzeptieren keine Edge-Funktionen.

Die Handler-Funktion ist intern. Jede Handler-Route übergibt ihr den übereinstimmenden Pfad im Anfrage-Header x-textjs-path. Dieser Header wird vor und nach der Middleware aus jeder Anfrage entfernt, und die Edge-Middleware leitet ihn niemals weiter (weder vom Client noch aus middleware.ts), sodass ihn nur die Handler-Routen setzen können. Anfragen an /_textjs/* geben vor und nach Middleware und Rewrites 404 zurück, ohne die Funktion auszuführen. Generierte Routen beachten die Groß- und Kleinschreibung, ebenso wie die Matcher und Rewrites auf jedem anderen Host.

Die Tests des Adapters prüfen diese Ausgabe gegen eine lokale Emulation des Vercel-Routers. Dessen Verhalten beim src-Abgleich, bei dest-Erfassungsgruppen, Header-Transformationen und status-Routen wurde anhand echter Deployments geprüft; die Edge-Middleware nicht, da sie sich nicht anonym deployen lässt.

Cloudflare Pages

text build --adapter cloudflarebunx wrangler pages dev dist --compatibility-flags=nodejs_compatbunx wrangler pages deploy dist

Die Ausgabe verwendet den erweiterten Modus von Pages:

DateiZweck
_worker.jsMiddleware, Rewrites, Route-Handler und das Konsolendokument
_routes.jsonSendet jede Anfrage an den Worker. Ohne Middleware oder basePath bleibt /assets/* auf dem statischen CDN von Pages
_headersUnveränderliches Caching für /assets/* (an deine Datei angehängt)
404.htmlLässt Pages bei fehlenden Dateien mit 404 statt mit der App antworten (bleibt erhalten, falls bereits vorhanden)

.text/ (Server-Bundles und Build-Manifeste) wird aus dist/ entfernt, da Pages das Verzeichnis unverändert veröffentlicht.

Aktiviere das Kompatibilitätsflag nodejs_compat im Pages-Projekt (Settings → Runtime) oder in wrangler.toml; der Datencache verwendet AsyncLocalStorage. Statische Dateien werden über das ASSETS-Binding ausgeliefert, und die Revalidierung im Hintergrund verwendet ctx.waitUntil().

Mit Middleware führt jede Anfrage den Worker aus, auch bei Assets mit Hash im Namen, damit die Middleware jeden Pfad sieht, über den eine Datei erreichbar ist. Jede Anfrage, die den Worker ausführt, ist ein Functions-Aufruf und zählt zu deinem Workers-Anfragekontingent. Beim Laden einer Seite sind das das Dokument und jede Datei, die es abruft (2 für eine kleine Test-App mit einem JavaScript-Bundle; mehr bei Apps mit mehr Dateien). Im Workers-Free-Tarif liefert Pages statische Dateien ohne den Worker aus, sobald das tägliche Kontingent aufgebraucht ist, und überspringt damit die Middleware. Wenn Middleware etwas in dist/ schützt, setze Settings → Runtime → Fail open / closed auf Fail closed.

wrangler.tomltoml
name = "my-console"pages_build_output_dir = "dist"compatibility_date = "2025-01-01"compatibility_flags = ["nodejs_compat"]

Aktualisieren

Sicherheitskorrekturen in @textjs/app erreichen ein Deployment erst, nachdem du es neu gebaut und erneut deployt hast:

  • Vercel: Deploye das neue .vercel/output.
  • Cloudflare Pages: Deploye das neue dist/ mit _worker.js und _routes.json.
  • Bun: Deploye das gesamte neue dist/ (server.js, Assets und Live-Bundles) und starte den Server neu.
  • text start: Führe text build aus und starte neu.

Ältere Deployments bleiben unter ihren eigenen URLs erreichbar (zum Beispiel Vorschau-URLs von Vercel und Cloudflare Pages). Lösche sie oder sichere sie mit dem Zugriffsschutz der Plattform ab.

Serverseitig gerenderte Routen

Serverseitig gerenderte Routen halten für jeden offenen Tab eine Sitzung vor und benötigen daher einen langlebigen Server: text start oder den bun-Adapter. Die Adapter static, vercel und cloudflare brechen den Build mit TX030 ab, wenn eine Seite runtime = "server" exportiert.

Hinter einem Proxy

text start bindet sich an 127.0.0.1 und beantwortet bei dieser Loopback-Bindung nur Anfragen an localhost, *.localhost und Hosts mit IP-Adressen (Schutz vor DNS-Rebinding). Andere Hosts erhalten 403 mit TX028. Trage die öffentlichen Einstellungen in text.config.ts ein:

text.config.tsts
import { defineConfig } from "@textjs/app";export default defineConfig({  server: {    origin: "https://console.example.com", // request.url always uses it (or TEXTJS_ORIGIN)    trustProxy: true, // read X-Forwarded-Host / -Proto from your proxy (or TRUST_PROXY=1)    allowedHosts: [".example.com"],  },});

Ohne origin oder trustProxy wird request.url aus dem validierten Host-Header mit http gebildet.

Einschränkungen

  • proxy in text.config.ts läuft nur in text dev und text start; Adapter enthalten es nicht. Verwende rewrites, das jeder Server-Adapter unterstützt.
  • Serverless-Instanzen haben jeweils ihren eigenen In-Memory-Cache. Siehe Caching.
  • rewrites, die rohe Gruppen regulärer Ausdrücke verwenden, werden nach bestem Bemühen in Vercel-Routen übersetzt; benannte Parameter (:slug, :path*) sind exakt.
Diese Seite auf GitHub bearbeiten