wterm: محاكي الطرفية للويب من Vercel المدعوم بـ Ghostty

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

Transcript

00:00:00هذا Wterm، محاكي طرفية قائم على الويب من Vasell
00:00:03يقوم بالرسم مباشرة على DOM بدلاً من Canvas.
00:00:06لذا فإن اختيار النص، والبحث في المتصفح،
00:00:08وقارئات الشاشة تعمل جميعها معه ببساطة.
00:00:10إنه مكتوب بلغة Zig، ويتم تجميعه في ملف WASM ثنائي بحجم 12 كيلوبايت،
00:00:14وهناك أيضاً واجهة خلفية اختيارية مدعومة بـ LibGhosty،
00:00:17وهي نفس المحرك الذي يشغل Ghosty terminal،
00:00:19مما يمنحك توافقاً كاملاً مع الطرفية في المتصفح.
00:00:22ولكن هل ملف WASM ثنائي بحجم 12 كيلوبايت
00:00:24كافٍ حقاً لاستبدال محاكي طرفية أصلي؟
00:00:28على الأرجح لا، لكن اشترك ودعنا نكتشف ذلك.
00:00:33الطرفيات القائمة على الويب موجودة في كل مكان تقريباً.
00:00:36في بيئات التطوير السحابية مثل GitHub Codespaces،
00:00:39وأدوات البنية التحتية مثل Portainer أو Qualify،
00:00:41وحتى بيئات التطوير المكتبية مثل VS Code أو Cursor.
00:00:44لكنها جميعاً تستخدم Xterm.js للقيام بذلك
00:00:47لأنه موجود منذ فترة طويلة
00:00:49وهو الخيار الافتراضي بشكل أساسي.
00:00:51لكن Xterm لديه مشكلة كبيرة.
00:00:52إنه يرسم على عنصر canvas.
00:00:54لذا فإن القيام بأشياء مثل اختيار النص
00:00:56أو العثور على كلمات في صفحة
00:00:58يجب أن يعاد تنفيذها من الصفر،
00:01:00وهو ما لا ينجح دائماً بشكل جيد.
00:01:02يتخذ Wterm نهجاً مختلفاً تماماً
00:01:04من خلال الرسم على DOM،
00:01:05مما يعني أن مخرجات الطرفية هي مجرد HTML،
00:01:08والمتصفح يتعامل مع ذلك بشكل أساسي مجاناً.
00:01:10ولكن يمكن لـ Wterm أيضاً القيام ببعض الأشياء الرائعة
00:01:13من خلال الرسم باستخدام HTML،
00:01:14مثل إعادة رسم الصف الذي تم تحديثه فقط،
00:01:17بدلاً من إعادة رسم الطرفية بالكامل في كل إطار.
00:01:20كما يمكن كتابته في أطر عمل مختلفة
00:01:22مثل React أو Vue.
00:01:23يمكنك تغيير السمة.
00:01:24وهناك أيضاً حزمة Wterm ghosty منفصلة،
00:01:27والتي تستبدل كود zig بـ lib ghosty
00:01:29وتعمل بشكل أفضل بشكل مفاجئ
00:01:31من مشروع web ghosty الآخر،
00:01:33الذي سنتحدث عنه أكثر لاحقاً في الفيديو.
00:01:35لكن في الوقت الحالي، دعنا نجرب Wterm
00:01:37بمشروع تجريبي بسيط.
00:01:38بعد تثبيت Wterm مع React،
00:01:40قمت باستيراد المكون بالإضافة إلى CSS،
00:01:43وأنا أقوم برسم المكون هنا.
00:01:45لذا الآن إذا قمت بتشغيل التطبيق ثم انتقلت إلى المتصفح،
00:01:48يمكنني رؤية أن هناك طرفية.
00:01:49ولكن إذا ضغطت على أمر مثل ls،
00:01:51يمكننا أن نرى أنه لا يحدث شيء.
00:01:52وهذا لأنها ليست متصلة
00:01:53بكمبيوتر آخر لقراءة المعلومات منه.
00:01:56دعني أشرح.
00:01:57في الوقت الحالي، العميل غير متصل بواجهة خلفية،
00:01:59لذا لا يوجد مكان للحصول على المعلومات منه.
00:02:01لكن ما يجب علينا فعله هو توصيله بجهاز آخر.
00:02:04لذا يمكن أن يكون جهازي المحلي
00:02:06أو جهازاً على السحابة،
00:02:07ثم تشغيل طرفية وهمية أو طرفية زائفة
00:02:10داخل ذلك الجهاز بنفس أبعاد
00:02:13تلك الموجودة لدى العميل.
00:02:14لذا إذا قمنا ببعض ضغطات المفاتيح،
00:02:16يتم إرسال معلومات ضغط المفاتيح تلك
00:02:18إلى الجهاز الآخر،
00:02:20الذي يقوم بتنفيذ ضغطات المفاتيح تلك،
00:02:22ويرسم النتائج،
00:02:23ويرسل كل تلك المعلومات مرة أخرى إلى العميل.
00:02:25وهذا الأخذ والرد يجب أن يحدث
00:02:26بسرعة كبيرة مع حد أدنى من التأخير.
00:02:28لذا فإن أفضل طريقة لتوصيل العميل
00:02:30والجهاز الآخر معاً
00:02:31هي استخدام WebSockets.
00:02:32لذا دعنا نمضي قدماً ونفعل ذلك.
00:02:34لذا يمكننا استخدام HETS في الخادم
00:02:35مع Ubuntu الذي قمت بإعداده بالفعل
00:02:37مع تثبيت Node.
00:02:38ولدي أيضاً بالفعل خادم Wterm
00:02:40مع نص برمجي للخادم.
00:02:42لذا إذا نظرنا إلى ذلك،
00:02:43يمكننا أن نرى أننا ننشئ خادم WebSocket
00:02:45على مسار slash API terminal.
00:02:48سيكون لهذا معنى أكبر بعد قليل.
00:02:49وهنا في الأسفل،
00:02:49نقوم بإنشاء طرفية زائفة
00:02:51باسم يطابق نوع الطرفية لدينا.
00:02:53إليك كيف يمكنك العثور على خاصتك إذا كنت مهتماً.
00:02:55وهنا في الأسفل،
00:02:56نحصل على أي ضغطة مفتاح من العميل،
00:02:58ونعالجها على الخادم،
00:02:59لذا داخل طرفيتنا الوهمية،
00:03:01ثم نعيد تلك المعلومات
00:03:02إلى العميل هنا.
00:03:03لذا يقوم الخادم بإرجاع كل شيء
00:03:05وليس فقط الصف المحدد الذي تم تحديثه.
00:03:07الآن على جانب العميل في ملف app.tsx،
00:03:10نقوم بإنشاء اتصال WebSocket
00:03:11بخادمنا على منفذ slash API slash terminal.
00:03:14ثم نستخدم تحويل WebSocket
00:03:16من Wterm للاتصال بذلك الرابط
00:03:19مع إعادة اتصال تلقائي.
00:03:21ثم هذا هو ما يرسل معلومات ضغط المفاتيح
00:03:23من هنا إلى الخادم.
00:03:24نحن نتعامل مع تغيير حجم المتصفح هنا،
00:03:26ثم هنا في الأسفل،
00:03:27ودالة التعامل مع البيانات
00:03:28تتعامل مع كل المعلومات
00:03:30التي تأتي من الخادم.
00:03:31والشيء الرائع في نواة ZIG
00:03:33هو أنها ستمرر هذه المعلومات،
00:03:35وتكتشف ما تم تغييره،
00:03:36وتعيد رسم ذلك الجزء من HTML فقط.
00:03:39هنا في الأسفل، حجم العمود والصف
00:03:41يجب أن يطابق ما كان لدينا على الخادم،
00:03:42وكل شيء آخر مفهوم بذاته.
00:03:45لذا الآن مع تشغيل العميل والخادم،
00:03:47بالعودة إلى المتصفح، إذا ضغطت على LS،
00:03:49يمكننا أن نرى أنها تسرد الملفات المتاحة لدينا.
00:03:52لذا يمكنني الضغط على LS مع العلم L
00:03:53لرؤية المزيد من المعلومات حول الملفات.
00:03:55يمكنني الدخول إلى ملف،
00:03:57وإلقاء نظرة على المعلومات الموجودة بداخله،
00:03:59وأيضاً القيام بأشياء مثل رؤية قائمة
00:04:01الحاويات التي قمت بتشغيلها.
00:04:02يمكنني حتى فتح ملف باستخدام Vim
00:04:03والتنقل خلاله.
00:04:04ولكن على الرغم من أن كل ذلك يعمل،
00:04:06إنه لا يقوم بذلك بشكل جيد للغاية.
00:04:07أعني، إذا حاولنا تمييز بعض النصوص،
00:04:09يمكننا رؤية بعض الحروف
00:04:10غير مقروءة تماماً.
00:04:12لذا لإصلاح ذلك،
00:04:13يمكننا إعداد Wterm مع Ghosty
00:04:15عن طريق تحميل Ghosty core
00:04:16وإضافته كدعامة في React.
00:04:18يمكنك رؤية الآن أنه إذا فتحنا ملف الخادم
00:04:20وقمنا بتمييز بعض النصوص،
00:04:22يصبح كل شيء أكثر قابلية للقراءة.
00:04:23يمكنه حتى القيام بأشياء مثل
00:04:24رسم الكود المفتوح بشكل صحيح،
00:04:26مما يسمح لنا بتغيير النماذج،
00:04:27وإعطائها أمراً مع دعم الرموز التعبيرية.
00:04:29يمكننا حتى أن نرى أن Ghosty يرسم الألوان
00:04:31بشكل أفضل قليلاً
00:04:31مما هو عليه مع عارض Wterm الأساسي.
00:04:34لكن نواة Zig يبلغ حجمها 12 كيلوبايت فقط
00:04:36مقارنة بـ 400 كيلوبايت من Ghosty.
00:04:39لذا إذا كنت تهتم بالحجم،
00:04:40فربما التزم بنواة Zig.
00:04:43على أي حال، هذه نظرة عامة سريعة على Wterm من Vercel.
00:04:46بالطبع، هناك العديد من الميزات الأخرى
00:04:48التي لم أستعرضها،
00:04:49مثل القدرة على تحويل Markdown
00:04:51إلى مخرجات طرفية جميلة،
00:04:52واستخدام Bash فقط للتنقل عبر ملفات وهمية
00:04:55إذا لم يكن لديك وصول إلى واجهة خلفية.
00:04:57وهناك حتى أمثلة
00:04:58حول كيفية إعداد عميل SSH
00:05:00من خلال طرفية في المتصفح.
00:05:02لكنني لم أجد Wterm مثالياً.
00:05:05كانت هناك بعض مشكلات الرسم
00:05:06عند استخدام إصدار Ghosty،
00:05:08عند التنقل ذهاباً وإياباً بين NeoVim
00:05:10أو حتى OpenCode.
00:05:11ولجعل عارض Ghosty يعمل
00:05:13مع واجهة BUN الأمامية الخاصة بي،
00:05:15كان علي استيراد ملف WASM
00:05:17لأن BUN لن ينسخ أي ملفات غير JS
00:05:19من مجلد Node modules.
00:05:21لكنني أحب نهج الرسم على DOM،
00:05:23مما يعني أنك تحصل على إمكانية الوصول
00:05:25وميزات المتصفح الأصلية
00:05:27دون القيام بأي عمل إضافي،
00:05:29وهو ما كافح Xterm للقيام به،
00:05:31على الرغم من أنه موجود منذ أكثر من 10 سنوات.
00:05:33لكن Xterm.js لديه نظام بيئي ضخم
00:05:35وهو الحل الذي تم اختباره في المعارك،
00:05:38لذا لن تخطئ إذا انتهى بك الأمر باختياره.
00:05:40هناك أيضاً GhostyWeb من Coda،
00:05:42الذي يتخذ نهجاً مختلفاً.
00:05:43إنه يستخدم نفس محرك libGhosty
00:05:45المستخدم من قبل طرفية Ghosty الفعلية،
00:05:48لكنه بديل مباشر لـ Xterm،
00:05:50لذا فهو لا يزال يستخدم نهج الرسم canvas
00:05:52ويستخدم نفس API،
00:05:54لكنك تحصل على طرفية أفضل.

Key Takeaway

يوفر Wterm بديلاً حديثاً لـ Xterm.js من خلال الرسم المباشر على DOM، مما يسهل الوصول إلى ميزات المتصفح الأصلية مع الحفاظ على خفة الحجم باستخدام نواة Zig بحجم 12 كيلوبايت.

Highlights

  • Wterm يرسم مخرجات الطرفية مباشرة على DOM مما يتيح ميزات المتصفح الأصلية مثل اختيار النص والبحث دون إعادة تنفيذها من الصفر.

  • تعتمد نواة Zig في Wterm على ملف ثنائي بحجم 12 كيلوبايت، مما يجعلها خفيفة جداً مقارنة بـ 400 كيلوبايت لمحرك Ghostty.

  • يتيح Wterm تحسين الأداء عبر إعادة رسم الصف المحدث فقط بدلاً من إعادة رسم كامل الطرفية في كل إطار.

  • يعمل Wterm عبر WebSockets لتبادل ضغطات المفاتيح ومخرجات الطرفية بين المتصفح والخادم مع تأخير أدنى.

  • يؤدي دمج libGhosty كواجهة خلفية اختيارية إلى تحسين دعم الألوان والرموز التعبيرية مقارنة بنواة Zig الأساسية.

Timeline

مفهوم Wterm وميزاته التقنية

  • يستخدم Wterm نموذج DOM للرسم بدلاً من عنصر canvas التقليدي.
  • تتكامل واجهات المتصفح الأصلية مثل البحث وقارئات الشاشة بشكل تلقائي مع مخرجات الطرفية.
  • يتم تجميع النواة الأساسية في ملف WASM بحجم 12 كيلوبايت مكتوب بلغة Zig.

تعتمد معظم الطرفيات المستندة إلى الويب حالياً على Xterm.js الذي يستخدم canvas، مما يضطر المطورين لإعادة تنفيذ ميزات المتصفح الأساسية كاختيار النص. يقدم Wterm حلاً جذرياً عبر التعامل مع مخرجات الطرفية كعناصر HTML عادية. يتيح هذا النهج أيضاً تحسينات في الكفاءة مثل تحديث الصفوف المتغيرة فقط بدلاً من إعادة رسم الشاشة بالكامل.

إعداد وتوصيل الطرفية عبر WebSockets

  • يتطلب Wterm اتصال WebSocket بخادم بعيد لتنفيذ الأوامر في طرفية زائفة (pseudoterminal).
  • يعالج الخادم ضغطات المفاتيح المرسلة من العميل ويعيد المخرجات الناتجة ليعرضها المتصفح.
  • تضمن مزامنة أبعاد الصفوف والأعمدة بين العميل والخادم عرضاً صحيحاً للمحتوى.

لا يعمل Wterm بمفرده كعميل محلي فقط، بل يحتاج إلى واجهة خلفية تتفاعل مع نظام التشغيل عبر طرفية زائفة. يتم إرسال بيانات ضغط المفاتيح من المتصفح إلى خادم (مثل خادم Node.js) عبر WebSockets، حيث يتم معالجتها وإعادة النتائج إلى العميل لعرضها باستخدام نواة Zig التي تكتشف التغييرات في HTML وتعيد رسم الأجزاء المطلوبة فقط.

مقارنة الأداء والخيارات المتاحة

  • يؤدي دمج libGhosty إلى تحسين عرض الألوان ودعم الرموز التعبيرية مقارنة بالنواة الأساسية.
  • تظل نواة Zig أكثر كفاءة من حيث الحجم (12 كيلوبايت) مقابل محرك Ghostty (400 كيلوبايت).
  • يواجه Wterm تحديات في استقرار الرسم مقارنة بـ Xterm.js الذي يمتلك نظاماً بيئياً ناضجاً.

رغم تفوق Wterm في إمكانية الوصول بفضل DOM، إلا أن Xterm.js لا يزال الحل الأكثر استقراراً والمختبر ميدانياً. توجد خيارات أخرى مثل GhosttyWeb التي تستخدم نفس محرك libGhosty ولكنها تلتزم بنموذج canvas وواجهة برمجة تطبيقات مشابهة لـ Xterm، مما يوفر توازناً بين الجودة والألفة في الاستخدام.

Community Posts

No posts yet. Be the first to write about this video!

Write about this video