استقرار
با text build --adapter static، bun، vercel یا cloudflare مستقر کنید، یا دستور text start را پشت پروکسی اجرا کنید.
دستور text build یک dist/ قابلانتقال تولید میکند. آداپتر آن را به خروجی مورد انتظار پلتفرم تبدیل میکند.
آداپترها
text build --adapter <name>| آداپتر | خروجی | اجرا |
|---|---|---|
| (هیچکدام) | dist/ + dist/.text/server | text start (Node) |
static | dist/ | هر میزبان ایستا |
bun | dist/server.js | bun dist/server.js |
vercel | .vercel/output | Vercel (Build Output API v3) |
cloudflare | dist/ + _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") و نشستهای زندهٔ آنها را نیز میزبانی میکند. از آن در کانتینر استفاده کنید:
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.func | middleware مسیریابی 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.js | middleware، بازنویسیها، کنترلگرهای مسیر و سند کنسول |
_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 تنظیم کنید.
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 قرار دهید:
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*) دقیق هستند.