مقدمة إلى WebAssembly و Rust
تتطلب تطبيقات الويب الحديثة أداءً متزايدًا باستمرار. JavaScript، على الرغم من مزاياه، لا يتعامل دائمًا مع المهام الحسابية المعقدة - مثل معالجة الصور، والعرض ثلاثي الأبعاد، والتشفير، أو المحاكاة. هنا يأتي دور WebAssembly (WASM) - وهو تنسيق تعليمات ثنائي يتم تنفيذه في المتصفح بسرعة شبه أصلية.
أصبحت لغة Rust واحدة من أفضل المرشحين لكتابة وحدات WASM: فهي آمنة وسريعة وليس لديها جامع للقمامة. في هذه المقالة، سنشرح كيفية تجميع كود Rust إلى WebAssembly، وربطه مع JavaScript، وإنشاء تطبيقات ويب عالية الأداء حقيقية.
إعداد البيئة لـ Rust + WASM
قبل كتابة الكود، قم بتثبيت الأدوات اللازمة:
- Rust - قم بتثبيته عبر
rustup(المثبت الرسمي). - wasm-pack - الأداة الرئيسية لبناء حزم WASM.
- wasm-bindgen - مكتبة لربط Rust و JavaScript.
- Node.js و npm - لاختبار وبناء الواجهة الأمامية.
# تثبيت wasm-packcurl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
# إنشاء مشروع جديدcargo new --lib wasm-examplecd wasm-exampleبعد إنشاء المشروع، افتح Cargo.toml وأضف التبعيات:
[lib]crate-type = ["cdylib"]
[dependencies]wasm-bindgen = "0.2"كتابة أول دالة في Rust لـ WebAssembly
لننشئ دالة بسيطة تجمع رقمين وتعيد النتيجة. في src/lib.rs نكتب:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]pub fn add(a: i32, b: i32) -> i32 { a + b}الوسم #[wasm_bindgen] يقوم تلقائيًا بإنشاء غلاف JavaScript لهذه الدالة. الآن لنقم ببناء المشروع:
wasm-pack build --target webبعد البناء، ستظهر في مجلد pkg الملفات: .wasm و .js (الغلاف) و .d.ts (أنواع TypeScript).
التكامل مع HTML و JavaScript
لننشئ صفحة HTML بسيطة للاختبار:
<!DOCTYPE html><html><head> <script type="module"> import init, { add } from './pkg/wasm_example.js';
async function run() { await init(); console.log('2 + 3 =', add(2, 3)); // 5 } run(); </script></head><body> <h1>Rust + WebAssembly يعمل!</h1></body></html>افتح الملف عبر خادم محلي (مثل python3 -m http.server) - ستظهر في وحدة تحكم المتصفح النتيجة 5.
العمل مع السلاسل النصية وأنواع البيانات المعقدة
يتعامل WebAssembly مع الأرقام فقط. للعمل مع السلاسل النصية والمصفوفات والكائنات، يتم استخدام wasm-bindgen الذي يقوم تلقائيًا بتحويل الأنواع.
مثال: دالة تعيد سلسلة نصية
use wasm_bindgen::prelude::*;
#[wasm_bindgen]pub fn greet(name: &str) -> String { format!("مرحبًا، {}! أنت تستخدم Rust + WASM.", name)}في JavaScript:
import init, { greet } from './pkg/wasm_example.js';
await init();console.log(greet("أليكسي")); // "مرحبًا، أليكسي! أنت تستخدم Rust + WASM."العمل مع المصفوفات (Vec)
لنقل المصفوفات، استخدم Vec<T>. مثال - دالة تضاعف جميع العناصر:
#[wasm_bindgen]pub fn double_numbers(arr: Vec<i32>) -> Vec<i32> { arr.iter().map(|x| x * 2).collect()}كود JavaScript:
const result = double_numbers([1, 2, 3, 4]);console.log(r