استقرار

با ⁦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.js⁦Cloudflare 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.funcmiddleware مسیریابی Edge: فایل middleware.ts و مسیرهای کانونی برای هر برنامه
config.jsonهدرهای منابع، تطبیق‌دهنده‌های middleware، بازنویسی‌ها، مسیرهای کنترل‌گر و سند کنسول

⁦edge middleware⁩ از پروتکل x-middleware-next / x-middleware-rewrite استفاده می‌کند، بنابراین جایگزینی هدرها و بازنویسی‌ها پیش از رسیدن به تابع یا CDN در مسیریاب Vercel انجام می‌شوند. تمام تطبیق‌دهنده‌ها از یک الگوی مسیر 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/* پیش و پس از middleware و بازنویسی‌ها، بدون اجرای تابع پاسخ 404 برمی‌گردانند. مسیرهای تولیدشده مانند تطبیق‌دهنده‌ها و بازنویسی‌ها در تمام میزبان‌های دیگر، با حساسیت به بزرگی و کوچکی حروف تطبیق داده می‌شوند.

آزمون‌های آداپتر این خروجی را در برابر شبیه‌سازی محلی مسیریاب 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هر درخواست را به worker می‌فرستد. بدون middleware یا basePath، مسیر /assets/* روی CDN ایستای Pages باقی می‌ماند
_headersکش تغییرناپذیر برای /assets/* (به انتهای فایل شما افزوده می‌شود)
404.htmlباعث می‌شود Pages برای فایل‌های ناموجود به‌جای برنامه، پاسخ 404 بدهد (اگر چنین فایلی دارید، حفظ می‌شود)

دایرکتوری .text/ (باندل‌های سرور و مانیفست‌های ساخت) از dist/ حذف می‌شود، چون Pages دایرکتوری را بدون تغییر منتشر می‌کند.

پرچم سازگاری nodejs_compat را در پروژهٔ Pages (تنظیمات → محیط اجرا) یا در wrangler.toml فعال کنید؛ کش داده از AsyncLocalStorage استفاده می‌کند. فایل‌های ایستا از طریق اتصال ASSETS ارائه می‌شوند و اعتبارسنجی مجدد در پس‌زمینه از ctx.waitUntil() استفاده می‌کند.

با وجود middleware، هر درخواست، از جمله درخواست منابع هش‌دار، worker را اجرا می‌کند تا middleware تمام مسیرهای دسترسی به یک فایل را ببیند. هر درخواستی که worker را اجرا می‌کند یک فراخوانی Functions است و از سهمیهٔ درخواست‌های Workers شما کم می‌کند. برای بارگذاری یک صفحه، این شامل سند و هر فایلی است که دریافت می‌کند (2 برای یک برنامهٔ آزمایشی کوچک با یک باندل JavaScript؛ بیشتر برای برنامه‌هایی با فایل‌های بیشتر). در طرح ⁦Workers Free⁩، پس از اتمام سهمیهٔ روزانه، Pages فایل‌های ایستا را بدون worker ارائه می‌کند و در نتیجه middleware اجرا نمی‌شود. اگر middleware از چیزی در dist/ محافظت می‌کند، گزینهٔ تنظیمات → محیط اجرا → ⁦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. وقتی صفحه‌ای runtime = "server" را صادر کند، آداپترهای static، vercel و cloudflare ساخت را با خطای TX030 متوقف می‌کنند.

پشت پروکسی

دستور 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 استفاده کنید که تمام آداپترهای سرور از آن پشتیبانی می‌کنند.
  • نمونه‌های بدون سرور هرکدام کش درون‌حافظه‌ای خود را دارند. بخش کش را ببینید.
  • موارد rewrites که از گروه‌های خام عبارت منظم استفاده می‌کنند، تا حد امکان به مسیرهای Vercel تبدیل می‌شوند؛ پارامترهای نام‌دار (:slug، :path*) دقیق هستند.
ویرایش این صفحه در GitHub