العرض على الخادم في وحدة التحكم
يمكن لإصدار Text.js 0.4 عرض صفحة على الخادم وبث إطاراتها إلى وحدة التحكم كتغييرات في الخلايا. وتعرض المسارات الثابتة إطارها الأول مسبقًا داخل HTML.
أضاف Text.js 0.4 مكانًا ثانيًا لعرض الصفحة. تعمل شجرة React للصفحة في علامة تبويب المتصفح افتراضيًا. تعمل الصفحة التي تصدّر runtime = "server" على الخادم بدلًا من ذلك، ويتلقى المتصفح إطاراتها.
import { Suspense, type ReactNode } from "react";import os from "node:os";import { Box, Text } from "textjs";export const runtime = "server";async function Load(): Promise<ReactNode> { const [one, five] = os.loadavg(); return <Text>{`load ${one.toFixed(2)} ${five.toFixed(2)}`}</Text>;}export default function StatusPage(): ReactNode { return ( <Box flexDirection="column"> <Text bold>Status</Text> <Suspense fallback={<Text color="gray">Reading host…</Text>}> <Load /> </Suspense> </Box> );}المكوّن Load هو مكوّن من نوع async function. على الخادم، يعلّق تنفيذه عند أقرب <Suspense> أو loading.tsx حتى يُحسم الوعد الخاص به، ويمكنه قراءة الملفات وقواعد البيانات ووحدات node:* مباشرة. تحمّل المكوّنات غير المتزامنة البيانات ولا يمكنها استخدام الخطافات. تحتفظ المكوّنات العادية المحيطة بها بالخطافات والتركيز و useInput و <Link> و useRouter()، وتعمل هذه جميعًا بالطريقة نفسها في بيئتَي التشغيل.
ما ينزّله المتصفح
لا تُرسل الصفحة المعروضة على الخادم مكتبة React أو Yoga أو مساراتك. يحمّل المتصفح مشغّل إطارات بحجم يقارب 21 kB بضغط gzip، ويحتوي على CellBuffer وعلى CssConsoleDriver نفسه الذي يستخدمه عارض العميل. يضبط المشغّل وتيرة الإطارات على المعدل نفسه، 15 إطارًا في الثانية، لذا ينتج الإطار المعروض على الخادم استدعاء console.log نفسه الذي ينتجه العميل.
البروتوكول
تفتح كل علامة تبويب جلسة خاصة بها على الخادم: جذر React، وسجلّ موجّه مسارات في الذاكرة، ومخزن خلايا مؤقت. تنقل نقطة نهاية واحدة البيانات في الاتجاهين:
browser tab ──(GET /__textjs/live, server-sent events)──▶ frame deltasbrowser tab ──(POST /__textjs/live, JSON)──────────────▶ keys, paste, wheel, resize, focus, Back/Forwardيرسل الخادم الصفوف التي تغيّرت قيمة التجزئة الخاصة بها فقط منذ آخر إطار تلقاه ذلك الاتصال. يُرسل كل صف على هيئة مقاطع نصية تستند إلى جدول أنماط لا يقبل إلا الإلحاق. تصل العناقيد الكتابية العريضة ومجموعات الرموز التعبيرية والألوان شبه الشفافة دون تغيير.
يفصل بين الإطارات 66 ms على الأقل، وتُحسب فروق كل إطار مقارنةً بآخر ما قبله المقبس. عندما يتوقف اتصال بطيء عن تصريف البيانات، تُتخطى الحالات الوسيطة، وينتقل الإطار التالي إلى أحدث حالة.
إذا انقطع البث، يعيد المشغّل الاتصال مستخدمًا معرّف جلسته في الترويسة x-textjs-live، ويستأنف الجلسة نفسها من إطار مفتاحي جديد، مع الحفاظ على حالتها. معرّفات الجلسات قيم عشوائية بطول 192 بت تُحفظ في الذاكرة، ولا توضع أبدًا في عنوان URL. تتوقف الجلسة التي لا اتصال لها عن العرض، وتُزال من شجرة المكوّنات بعد 30 ثانية.
ترفض نقطتا النهاية الطلبات الواردة من مواقع أخرى، ويُتحقق من كل حدث إدخال وفق مخطط ثابت. تقبل الجلسة 64 حدثًا على الأكثر لكل طلب POST، ونحو 240 حدثًا في الثانية.
المكوّنات غير المتزامنة والبيانات
يُخزّن الوعد الخاص بكل مكوّن غير متزامن مؤقتًا لكل جلسة، بمفتاح يستند إلى المكوّن وخصائصه، لذا تعيد محاولة العرض استخدام الطلب الجاري بالفعل. تُمسح الذاكرة المؤقتة عند تغيّر المسار وعند استدعاء router.refresh():
const router = useRouter();useInput((e) => e.input === "r" && router.refresh());تُسمّى الوحدات المخصّصة للخادم فقط بالنمط *.server.ts. يفشل البناء إذا استوردت الشيفرة المرسلة إلى المتصفح إحدى هذه الوحدات، أو وحدة مدمجة من node:*، ويذكر اسم الجهة المستوردة.
العرض المسبق الجزئي
يعمل العرض المسبق الجزئي دون خادم. يعرض الأمر text build الآن كل مسار ثابت مرة واحدة، ويضمّن إطاره الأول في HTML الخاص بالمسار على هيئة <script> كلاسيكي صغير، فتظهر وحدة التحكم محتواها قبل تحميل أي وحدة.
الهيكل هو كل ما يُعرض بشكل متزامن. يعرض حدّ <Suspense> الذي لا يزال ينتظر محتواه البديل، بما في ذلك المكوّنات غير المتزامنة، ولا يُحسم fetch() أبدًا أثناء عرض الهيكل.
عند بدء تشغيل JavaScript، يبث عارض العميل أو مشغّل الإطارات الإطار الفعلي. ولأن الإصدار 0.4 يُلحق الإطارات أيضًا بدلًا من المسح، يبدأ العارض الذي ينفّذ التهيئة التفاعلية بالقيمة initialClear: false ويسجّل أسفل الهيكل، وتُخرج ستارته الهيكل من مجال الرؤية ضمن عملية الرسم نفسها في DevTools. يمسح الهيكل وحدة التحكم مرة واحدة بالضبط.
✓ Prerendering console shells (5/5) · 1 server-rendered, frame player 56.5 kB (21.3 kB gzip)يُعرض الهيكل بالحجم المضبوط في viewport، وهو 120 × 36 افتراضيًا، لأن عملية البناء لا تستطيع معرفة حجم وحدة التحكم لدى الزائر. عند تفعيل viewport.responsive، يتكيف حجم أول إطار مباشر مع وحدة التحكم المثبّتة. لا تعرض المسارات الديناميكية هيكلًا، ويوقف الإعداد ppr: false في text.config.ts العرض المسبق.
اختيار بيئة التشغيل
تبقى بيئة تشغيل العميل هي الافتراضية. تُعرض نتائج ضغطات المفاتيح ضمن المهمة نفسها، ويمكن نشر التطبيق على أي مضيف ثابت. تناسب بيئة تشغيل الخادم لوحات المعلومات وواجهات الإدارة التي تقرأ بيانات خاصة، والمسارات التي لا تريد تضمين اعتمادياتها في حزمة المتصفح. يمكن للتطبيق الواحد الجمع بين البيئتين، ويؤدي التنقل بينهما إلى تحميل عنوان URL المستهدف كمستند جديد.
يتوفر المرجع الكامل في العرض على الخادم.