FlowingDev

مغامرة روبي على الويب: من غرف السيرفرات إلى متصفحك

اكتشف كيف يمكن لروبي، لغة كلاسيكية للخوادم، أن تعمل مباشرة في متصفحك بفضل سحر WebAssembly (Wasm) ومُفسِّر CRuby.

جرّب الأداة: ملعب Ruby

في جملة واحدة

ملعب روبي (Ruby playground) ينفذ كود روبي فوراً داخل متصفح الويب، بدون الحاجة لأي تثبيت، عن طريق تشغيل مُفسِّر روبي بأكمله على تقنية مذهلة اسمها WebAssembly.

المشكلة التي يحلها

روبي، التي وُلدت في منتصف التسعينيات بفضل يوكييرو "ماتز" ماتسوموتو، صُممت بفلسفة أساسية: سعادة المطور. صياغتها الأنيقة وسهلة القراءة جعلت كتابتها ممتعة، ولعقود، كان مكانها الأساسي على الخادم. شغّلت روبي عمالقة مثل GitHub و Shopify و Airbnb (في أيامه الأولى)، وأصبحت نجمة في عالم تطوير الواجهات الخلفية (backend)، خاصة مع إطار العمل Rails.

لكن هذه النجومية جاءت مع بعض العوائق. لتشغيل سطر واحد من كود روبي، كنت تحتاج إلى إعداد بيئة كاملة على جهازك. هذا كان يعني:

  1. تثبيت مفسر روبي نفسه.
  2. التعامل مع إصدارات المشاريع المختلفة باستخدام أدوات مثل RVM أو rbenv (هل سمعت من قبل بمصطلح "جحيم الاعتماديات"؟).
  3. تثبيت المكتبات، المسماة "gems"، والتي قد يكون لها اعتمادياتها المعقدة الخاصة.

هذا الإعداد يخلق حاجزًا كبيرًا. لمطور يريد فقط اختبار خوارزمية سريعة، أو طالب يتعلم الأساسيات، أو مطور واجهات أمامية لديه فضول حول دوال المصفوفات الشهيرة في روبي، فإن تثبيت بيئة محلية كاملة يشبه الحاجة إلى رخصة طيار لمجرد الجلوس في قمرة القيادة.

ملعب روبي يزيل كل هذا العناء. إنه يوفر بيئة تجريبية (sandbox) فورية بدون أي التزامات. إنه بمثابة "جرّب قبل أن تشتري"، مما يسمح لأي شخص، في أي مكان، بتجربة متعة روبي باستخدام متصفح الويب فقط. إنه للاختبارات السريعة، والعروض التوضيحية القابلة للمشاركة، والتعلم بدون الصداع اللوجستي.

كيف يعمل تحت الغطاء

إذًا، كيف نتمكن من حشر لغة خاصة بالخوادم، تتوقع أن تتحدث مع نظام ملفات ونظام تشغيل، في صندوق الرمل الأمني المشدد لمتصفح الويب؟ المكون السري هو تقنية أحدثت ثورة بهدوء في عالم الويب: WebAssembly.

### ما هو WebAssembly (Wasm)؟

فكر في WebAssembly (أو Wasm اختصارًا) كلغة جديدة للويب، ولكنها ليست لغة مصممة لتكتبها بنفسك. إنها صيغة تعليمات ثنائية منخفضة المستوى تعمل في المتصفح جنبًا إلى جنب مع JavaScript. تخيلها كمعالج افتراضي صغير وفائق الكفاءة يعيش داخل نافذة متصفحك.

لغات مثل C و C++ و Rust يمكن ترجمتها إلى Wasm. بدلاً من إنشاء ملف .exe لنظام Windows أو ملف ثنائي لنظام Linux، يقوم المترجم (compiler) بإنتاج ملف .wasm. يمكن للمتصفح بعد ذلك تحميل هذا الملف وتنفيذه بسرعة شبه أصلية، أسرع بكثير من JavaScript التقليدية. إنه المفتاح الذي يفتح الباب لتشغيل أكواد عالية الأداء وغير مكتوبة بـ JavaScript على الويب.

  Your C/C++/Rust Code
          |
          v
[ Wasm Compiler (e.g., Emscripten) ]
          |
          v
  your_program.wasm  <-- Runs in the Browser's Wasm VM

### ترجمة CRuby إلى Wasm

هنا يحدث السحر. النسخة الرسمية والقياسية من روبي تسمى CRuby لأنها مكتوبة بلغة البرمجة C. وبما أن لغة C يمكن ترجمتها إلى WebAssembly... أظن أنك فهمت الفكرة.

باستخدام مجموعة أدوات ترجمة خاصة (مثل Emscripten)، يمكن للمطورين أخذ الكود المصدري الكامل لمفسر CRuby وترجمته إلى ملف ruby.wasm. هذا الملف هو مفسر روبي نفسه، ولكنه مترجم إلى لغة يمكن لمحرك Wasm في المتصفح فهمها.

عندما يتم تحميل ملعب روبي، يقوم بتنزيل ملف ruby.wasm هذا. الآن لديك القوة الكاملة لمحرك لغة روبي في ذاكرة متصفحك، جاهز للانطلاق.

### الصمغ الذي يربط كل شيء: JavaScript

ملف .wasm قوي، لكنه معزول أيضًا. لا يمكنه لمس صفحة الويب مباشرة، أو طباعة نص على شاشتك، أو قراءة الكود الذي كتبته في مربع النص. إنه يحتاج إلى وسيط للتعامل معه، وهذا الوسيط هو JavaScript.

طبقة رقيقة من "الكود اللاصق" المكتوب بـ JavaScript هي المسؤولة عن إدارة وحدة Wasm. إليك ما يحدث خطوة بخطوة:

  1. التحميل: تقوم JavaScript بجلب ملف ruby.wasm وتهيئة وحدة Wasm. هذا يشبه تشغيل الطاقة لآلة روبي الافتراضية.
  2. الإدخال: عندما تكتب كودًا مثل puts "Hello, Matz!"، يأخذ كود JavaScript هذا النص.
  3. التنفيذ: يستدعي كود JS دالة معينة تم تصديرها من وحدة Wasm، شيء مثل run_ruby_code()، ويمرر سلسلة الكود الخاصة بك إليها.
  4. المعالجة: داخل آلة Wasm الافتراضية، يعمل مفسر CRuby، ويحلل الكود الخاص بك وينفذه. عندما يستدعي الكود الخاص بك puts، يكتب المفسر "Hello, Matz!" إلى مخرجاته القياسية (stdout).
  5. الإخراج: يتم تكوين وحدة Wasm لإعادة توجيه مخرجاتها (stdout) مرة أخرى إلى بيئة JavaScript. يلتقط كود JS اللاصق هذا الإخراج.
  6. العرض: أخيرًا، يأخذ كود JavaScript النص الملتقط ويعرضه في منطقة المخرجات على صفحة الويب.
// A simplified view of the JS glue logic
import initRuby from './ruby.wasm';

async function runPlayground() {
  // 1. Load the Wasm module and its exported functions
  const ruby = await initRuby({
    // 5. Capture anything the Wasm module tries to print
    print: (text) => {
      document.getElementById('output').textContent += text + '\n';
    }
  });

  // 2. Get user input
  const userInput = '3.times { |i| puts "Loop ##{i + 1}" }';

  // 3 & 4. Execute the Ruby code inside the Wasm VM
  ruby.eval(userInput);
}

كل هذا يحدث في جزء من الثانية، مما يخلق الوهم بأنك تشغل روبي أصليًا بينما أنت في الواقع تدير رقصة معقدة بين JavaScript وبرنامج C مترجم إلى WebAssembly.

قصص من الواقع

### المرشحة المستعجلة للمقابلة

كانت سارة في الجولة النهائية من مقابلة تقنية. المهمة: "اكتبي دالة روبي لإيجاد الحرف الأكثر تكرارًا في سلسلة نصية". كان حاسوبها المحمول في فوضى من المشاريع. أحدها يستخدم Ruby 2.7، والآخر Ruby 3.1. كانت تخشى الدقيقة التي ستقضيها في المصارعة مع rbenv لتبديل الإصدارات، وتصلي ألا تكون إحدى الاعتماديات قد تعطلت. بدلاً من ذلك، أعلنت: "هل تمانعون إذا استخدمت ملعبًا على الويب؟" فتحت نافذة في المتصفح، وكتبت حلها الأنيق باستخدام دوال روبي group_by و max_by، واختبرته بثلاثة مدخلات مختلفة في أقل من دقيقتين. لم ينبهر القائمون على المقابلة بالكود فقط، بل بكفاءتها أيضًا.

الدرس المستفاد: الملعب هو بيئة فورية ونقية. إنه يتجاوز فوضى الإعداد المحلي، مما يتيح لك التركيز بشكل كامل على الكود، وهو أمر لا يقدر بثمن تحت الضغط.

### مطور الواجهات الأمامية الفضولي

أليكس، مطور React، كان يقرأ تدوينة تشيد بصياغة روبي "الجميلة" لمعالجة البيانات. أظهرت التدوينة مثالاً لتحويل مصفوفة من الكائنات بسطر واحد. لم يرغب أليكس في المرور بمشقة تثبيت روبي فقط لتجربتها. فتح ملعب روبي، ولصق المصفوفة، وكتب سلسلة map و select بنفسه. قام بتعديلها، ولعب بها، وفي غضون خمس دقائق، "فهم الفكرة". في اليوم التالي، استخدم نمطًا مشابهًا من السلاسل الوظيفية في كود JavaScript الخاص به، مستلهمًا من رحلته القصيرة إلى عالم روبي.

الدرس المستفاد: الملاعب هي بيئات تجريبية خالية من العوائق للاستكشاف. تتيح لك غمس أصابع قدميك في أنظمة برمجية أخرى، وتعلم أنماط جديدة، وجلب تلك الأفكار إلى لغتك الأساسية.

### تقرير الخطأ الذي ساعد حقًا

كان أحد المطورين يعاني من حالة غريبة في مكتبة "gem" مفتوحة المصدر لروبي. قدم تقرير خطأ يقول: "دالة process تفشل عندما تحتوي السلسلة المدخلة على رموز تعبيرية (emojis)". لم يتمكن المشرف على المشروع من إعادة إنتاج الخطأ. استمر النقاش ذهابًا وإيابًا لأيام. أخيرًا، تدخل مساهم آخر، وأنشأ مثالًا بسيطًا للخطأ في ملعب روبي، وشارك الرابط. نقر المشرف على الرابط، وشغل الكود، ورأى الخطأ على الفور. تم إصلاح الخطأ في غضون ساعة.

الدرس المستفاد: يوفر الملعب "مثالًا صغيرًا وكاملاً وقابلاً للتحقق" على طبق من ذهب. إنه يجعل تقارير الأخطاء لا يمكن إنكارها والتعاون فعالاً بشكل لا يصدق.

الأخطاء والفخاخ الشائعة

  • الاعتقاد بأنه خادم كامل. أنت داخل صندوق الرمل الأمني للمتصفح (sandbox). لا يمكنك الوصول إلى نظام الملفات المحلي (لن تعمل File.open على /etc/hosts)، أو فتح اتصالات شبكة عشوائية، أو الاتصال مباشرة بقاعدة بيانات. البيئة مقيدة بشدة لأسباب أمنية.
  • الاعتماد على مكتبات "gems" خارجية. يحتوي ملعبك على مكتبة روبي القياسية، ولكن هذا كل شيء عادةً. لا يمكنك فقط كتابة require 'rails' أو require 'nokogiri'. يتطلب تثبيت الـ "gems" غالبًا نظام ملفات وأحيانًا ترجمة إضافات C أصلية، وكلاهما غير متوفر في هذا السياق البسيط والمعزول.
  • تجاهل حدود أداء المتصفح. WebAssembly سريع، لكنه ليس سحرًا. حلقة لا نهائية (loop { puts 'oops' }) أو حساب مضروب عدد ضخم سيظل يجمد نافذة المتصفح، لأنه على الأرجح يعمل على نفس الخيط الرئيسي لواجهة المستخدم. استخدمه للسكربتات السريعة، وليس للحسابات العلمية الثقيلة.
  • نسيان الحالة (state). في كل مرة تضغط فيها على "تشغيل"، فإنك تبدأ من جديد بصفحة بيضاء ونظيفة. يتم إعادة تهيئة المفسر، وتختفي جميع المتغيرات من التشغيل السابق. هذه ميزة (لإمكانية إعادة الإنتاج!)، وليست خطأ، لكنها يمكن أن تربكك إذا كنت تتوقع استمرارية الحالة.

لماذا يجب أن تضعه في اعتبارك

يجب أن تفكر في استخدام ملعب روبي كلما احتجت إلى "جرعة روبي سريعة".

  • النماذج الأولية: اختبار فكرة خوارزمية أو تحويل بيانات بسرعة.
  • التعلم: تجربة صياغة روبي أو ميزة في المكتبة القياسية دون أي إعداد.
  • المشاركة: إنشاء قصاصة كود حية وقابلة للتشغيل لتضمينها في التوثيق، أو تدوينة، أو إجابة على Stack Overflow، أو تقرير خطأ.
  • المقابلات: استخدامه كأرضية نظيفة ومحايدة لتحديات البرمجة.
  • فهم Wasm: مجرد اللعب به هو وسيلة رائعة لتقدير قوة WebAssembly ومستقبل تطوير الويب، حيث يصبح المتصفح بيئة تشغيل عالمية للعديد من اللغات.

تعمق أكثر

كيف يفهم المحرر الشيفرة

ألوان الصياغة تأتي من محلل اللغة، لا من تشغيل البرنامج. يتعرف CodeMirror وLezer على الرموز والبنية محليًا في المتصفح. تجمع الاقتراحات الكلمات المحجوزة والأسماء المحلية عند دعمها والمقاطع الجاهزة ومرجعًا مدمجًا صغيرًا؛ ويكشف المرور فوق رمز موثق عن توقيعه. الاقتراح لا يضمن وجود الواجهة في بيئة التنفيذ. يكتشف المحلل أخطاء الصياغة عند دعمها، لكنه لا يحل محل فحص الأنواع أو التشغيل: قد تفشل شيفرة سليمة نحويًا. يستخدم Ruby وLua أوضاعًا قائمة على الرموز وتشخيصات أكثر محدودية. لا يوجد خادم لغة بعيد، ولا تحتاج الشيفرة إلى مغادرة الجهاز.

CodeMirror & Lezer: MIT.

انتهينا من النظرية. حان وقت التطبيق — 100% في متصفحك.

جرّب الأداة: ملعب Ruby