العمل مع WebAssembly وJavaScript في Node.js: دليل متقدم

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة إلى WebAssembly وتكامله مع Node.js



في تطوير الويب الحديث، غالبًا ما يصبح الأداء عاملاً حاسمًا، خاصة عند العمل مع المهام الحسابية المعقدة: معالجة الصور، التشفير، محاكاة العمليات الفيزيائية، والتعلم الآلي. يوفر WebAssembly (WASM) فرصة فريدة لتنفيذ كود مُجمّع من C/C++/Rust بسرعة تقترب من السرعة الأصلية، مباشرة في بيئة تنفيذ JavaScript.



في هذا الدليل المتقدم، سنستعرض كيفية دمج WebAssembly مع Node.js بشكل فعال، وإنشاء وحدات عالية الأداء، وتحسين التفاعل بين البيئتين. يُفترض أن القارئ على دراية بأساسيات JavaScript ولديه فهم أساسي لمفاهيم WebAssembly.



إنشاء وتجميع وحدات WASM لـ Node.js



إعداد الأدوات



للعمل مع WebAssembly في Node.js، نحتاج إلى مترجم يحول الكود المصدري من C/C++/Rust إلى كود WASM بايت. يُوصى باستخدام Emscripten - وهي مجموعة أدوات قوية لا تقوم فقط بتجميع الكود، بل تولد أيضًا أغلفة JavaScript للتكامل السهل.



# تثبيت Emscriptengit clone https://github.com/emscripten-core/emsdk.gitcd emsdk./emsdk install latest./emsdk activate latestsource ./emsdk_env.sh


كتابة كود بلغة C وتجميعه إلى WASM



لننظر في مثال لإنشاء وحدة لحساب أرقام فيبوناتشي - وهي مهمة كلاسيكية توضح مزايا WASM مقارنة بـ JavaScript الخالص عند العمل مع التكرار والحسابات.



لننشئ ملف fibonacci.c:



#include <emscripten.h>

EMSCRIPTEN_KEEPALIVEint fibonacci(int n) { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2);}

EMSCRIPTEN_KEEPALIVEint fibonacci_iterative(int n) { int a = 0, b = 1, temp; for (int i = 0; i < n; i++) { temp = a; a = b; b = temp + b; } return a;}


نقوم بتجميعه إلى WASM:



emcc fibonacci.c -o fibonacci.js -s WASM=1 -s EXPORTED_FUNCTIONS='["_fibonacci", "_fibonacci_iterative"]' -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]'


العلامة -s WASM=1 تشير إلى توليد وحدة WASM، بينما EXPORTED_FUNCTIONS تحدد الدوال التي ستكون متاحة من JavaScript.



دمج وحدة WASM في تطبيق Node.js



تحميل وتهيئة الوحدة



بعد التجميع، نحصل على ملفين: fibonacci.js (الغلاف) و fibonacci.wasm (الوحدة نفسها). في Node.js، يتم التحميل بشكل غير متزامن:



const fs = require('fs');const path = require('path');

async function loadWasmModule() { const wasmBuffer = fs.readFileSync(path.join(__dirname, 'fibonacci.wasm')); const wasmModule = await WebAssembly.instantiate(wasmBuffer, { env: { abort: () => console.log('إحباط!') } }); return wasmModule.instance.exports;}

// الاستخدام(async () => { const wasmExports = await loadWasmModule(); console.log('فيبوناتشي(40) عبر WASM:', wasmExports.fibonacci(40));})();


العمل مع الذاكرة ونقل البيانات



أحد الاختلافات الرئيسية في العمل المتقدم مع WASM هو إدارة الذاكرة. يستخدم WebAssembly ذاكرة خطية يمكن الوصول إليها من JavaScript عبر ArrayBuffer. هذا مهم بشكل خاص عند نقل مصفوفات كبيرة من البيانات.



// إنشاء دالة للعمل مع المصفوفات في WASMconst wasmCode = new Uint8Array([    0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00    // ... كود WASM البايت الكامل]);

async function processArrayWithWasm(data) { const module = await WebAssembly.instantiate(wasmCode, {}); const { memory, processData } = module.instance.exports; // تخصيص ذاكرة للمصفوفة const ptr = mo

المدونات

توصيات الكتب