Развёртывание

Разверните приложение с text build --adapter static, bun, vercel или cloudflare либо запустите text start за прокси.

text build создаёт переносимый каталог dist/. Адаптер преобразует его в формат, который ожидает платформа.

Адаптеры

text build --adapter <name>
АдаптерРезультатСреда запуска
(нет)dist/ + dist/.text/servertext start (Node)
staticdist/Любой статический хостинг
bundist/server.jsbun dist/server.js
vercel.vercel/outputVercel (Build Output API v3)
cloudflaredist/ + _worker.jsCloudflare Pages

Адаптер можно задать и через TEXTJS_ADAPTER. Когда text build запускается на Vercel (VERCEL=1) или Cloudflare Pages (CF_PAGES=1), соответствующий адаптер выбирается автоматически.

Серверные адаптеры (bun, vercel и cloudflare) выполняют ту же цепочку обработки, что и text start: middleware, rewrites, обработчики маршрутов с кешем маршрутов, статические ресурсы, затем документ консоли для URL страниц. Терминальные клиенты, такие как curl, вместо этого получают первый кадр страницы в виде текста ANSI. На vercel и cloudflare это работает только для статических страниц (см. curl и терминальные клиенты). Серверные адаптеры отдают файлы с хешами в /assets/ с заголовком Cache-Control: public, max-age=31536000, immutable.

Статический хостинг

text build --adapter static

Используйте его для хостингов без сервера, таких как GitHub Pages, S3 или CDN. Для обработчиков маршрутов GET с dynamic = "force-static" или revalidate выполняется пререндеринг в файлы: app/api/feed.json/route.ts превращается в dist/api/feed.json. Копия index.html записывается в 404.html, чтобы прямые ссылки открывали консольное приложение. Статические хостинги не могут отличить curl от браузера, поэтому curl получает HTML-страницу.

Сборка завершается ошибкой с перечислением всех причин, если приложению нужен сервер: middleware.ts, отрендеренные на сервере маршруты, динамические обработчики маршрутов, обработчики маршрутов с динамическими сегментами или методы, отличные от GET. Вместо этого настройте rewrites на хостинге.

Bun

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

Адаптер bun записывает единый автономный сервер, которому не нужен node_modules во время выполнения. Он читает PORT (по умолчанию 3000) и HOSTNAME (по умолчанию 0.0.0.0) и никогда не отдаёт server.js или .text/. Это долгоживущий процесс, поэтому он, как и text start, обслуживает отрендеренные на сервере маршруты (export const runtime = "server") и их активные сессии. Используйте его в контейнере:

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

Vercel

text build --adapter vercelvercel deploy --prebuilt

Или отправьте изменения в Git-репозиторий, подключённый к Vercel: сборка запускает text build, обнаруживает Vercel и записывает .vercel/output.

РезультатСодержимое
static/Клиентская сборка (в basePath)
functions/_textjs/server.funcОдна функция Node.js 22, обслуживающая все обработчики маршрутов, с потоковой передачей
functions/_middleware.funcEdge Routing Middleware: middleware.ts и канонические пути для каждого приложения
config.jsonЗаголовки ресурсов, правила сопоставления middleware, перезаписи, маршруты обработчиков и документ консоли

Edge-middleware использует протокол x-middleware-next / x-middleware-rewrite, поэтому переопределение заголовков и перезапись происходят в маршрутизаторе Vercel до обращения к функции или CDN. Все правила сопоставления используют один шаблон маршрута src. Запросы, не подходящие ни под одно правило, пропускают middleware, кроме случаев, когда их путь может быть не в канонической форме (процентное кодирование, символы, кодируемые парсером URL, //, сегменты . или .., завершающая косая черта). Тогда middleware сопоставляет канонический путь, проверяет has / missing и перезаписывает запрос на этот путь, чтобы Vercel маршрутизировал его так же. Приложения без middleware.ts получают ту же edge-функцию, которая выполняет только перезапись. Поскольку каждая сборка включает функцию Edge, выполняйте развёртывание из учётной записи Vercel, в которую вы вошли: анонимные развёртывания (vercel deploy --temporary) не поддерживают функции Edge.

Функция обработчика внутренняя. Каждый маршрут обработчика передаёт ей совпавший путь в заголовке запроса x-textjs-path. Этот заголовок удаляется из каждого запроса до и после middleware, а edge-middleware никогда не пересылает его (ни от клиента, ни из middleware.ts), поэтому задать его могут только маршруты обработчиков. Запросы к /_textjs/* возвращают 404 без запуска функции, до и после middleware и перезаписей. Сгенерированные маршруты сопоставляются с учётом регистра, как и правила сопоставления и перезаписи на всех остальных хостингах.

Тесты адаптера проверяют этот результат сборки с локальной эмуляцией маршрутизатора Vercel. Его поведение при сопоставлении src, захватах dest, преобразовании заголовков и маршрутах status проверено на реальных развёртываниях; Edge-middleware не проверялось, поскольку его нельзя развернуть анонимно.

Cloudflare Pages

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

Результат сборки использует расширенный режим Pages:

ФайлНазначение
_worker.jsMiddleware, перезаписи, обработчики маршрутов и документ консоли
_routes.jsonОтправляет каждый запрос воркеру. Без middleware или basePath путь /assets/* остаётся на статическом CDN Pages
_headersНеизменяемое кеширование для /assets/* (дописывается к вашим настройкам)
404.htmlЗаставляет Pages отвечать 404 для отсутствующих файлов вместо приложения (сохраняется, если уже есть)

.text/ (серверные бандлы и манифесты сборки) удаляется из dist/, поскольку Pages публикует каталог как есть.

Включите флаг совместимости nodejs_compat в проекте Pages (Settings → Runtime) или в wrangler.toml; кеш данных использует AsyncLocalStorage. Статические файлы отдаются через привязку ASSETS, а фоновая ревалидация использует ctx.waitUntil().

При наличии middleware каждый запрос запускает воркер, включая запросы ресурсов с хешами, чтобы middleware видел каждый путь, по которому можно получить файл. Каждый запрос, запускающий воркер, считается одним вызовом Functions и расходует вашу квоту запросов Workers. При загрузке страницы это документ и каждый запрашиваемый им файл (2 для небольшого тестового приложения с одним JavaScript-бандлом; больше для приложений с большим числом файлов). На тарифе Workers Free после исчерпания суточной квоты Pages отдаёт статические файлы без воркера, пропуская middleware. Если middleware защищает что-либо в dist/, установите Settings → Runtime → Fail open / closed в значение Fail closed.

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

Обновление

Исправления безопасности в @textjs/app попадают в развёрнутое приложение только после повторной сборки и развёртывания:

  • Vercel: разверните новый .vercel/output.
  • Cloudflare Pages: разверните новый dist/ с _worker.js и _routes.json.
  • Bun: разверните весь новый dist/ (server.js, ресурсы и бандлы активных сессий) и перезапустите сервер.
  • text start: запустите text build и перезапустите сервер.

Старые развёртывания остаются доступны по собственным URL (например, URL предварительного просмотра Vercel и Cloudflare Pages). Удалите их или ограничьте доступ к ним средствами защиты платформы.

Отрендеренные на сервере маршруты

Отрендеренные на сервере маршруты хранят сессию для каждой открытой вкладки, поэтому им нужен долгоживущий сервер: text start или адаптер bun. Адаптеры static, vercel и cloudflare завершают сборку ошибкой TX030, когда страница экспортирует runtime = "server".

Работа за прокси

text start привязывается к 127.0.0.1 и при привязке к loopback отвечает только хостам localhost, *.localhost и хостам с IP-адресами (защита от DNS-rebinding). Остальные хосты получают 403 с TX028. Поместите настройки публичного доступа в text.config.ts:

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"],  },});

Без origin или trustProxy значение request.url строится из проверенного заголовка Host с протоколом http.

Ограничения

  • proxy в text.config.ts работает только в text dev и text start; адаптеры его не включают. Используйте rewrites, которые поддерживает каждый серверный адаптер.
  • Каждый serverless-экземпляр имеет собственный кеш в памяти. См. Кеширование.
  • rewrites, использующие группы регулярных выражений напрямую, преобразуются в маршруты Vercel по мере возможности; именованные параметры (:slug, :path*) преобразуются точно.
Изменить эту страницу на GitHub