WebAssembly چیست؟ چگونه WebAssembly اجرای برنامهها در مرورگر را سریعتر میکند؟
مرورگرهای امروزی فقط برای نمایش متن و تصویر استفاده نمیشوند. بسیاری از برنامههایی که در مرورگر اجرا میکنیم، از ویرایشگرهای آنلاین و ابزارهای گرافیکی گرفته تا بازیها، نرمافزارهای پردازش فایل و سرویسهای پیچیده وب، به انجام محاسبات سنگین نیاز دارند. JavaScript برای ساخت چنین برنامههایی بسیار قدرتمند و انعطافپذیر است، اما در بعضی سناریوها ممکن است اجرای محاسبات سنگین به یک گلوگاه عملکردی تبدیل شود. WebAssembly یا به اختصار Wasm برای حل بخشی از این مسئله به وجود آمده است.
WebAssembly دقیقاً چیست؟
WebAssembly یک فرمت باینری سطح پایین و قابل حمل است که میتواند بهعنوان هدف کامپایل زبانهایی مانند C، C++ و Rust مورد استفاده قرار بگیرد و در محیطهای مختلف از جمله مرورگر اجرا شود. اما WebAssembly قرار نیست جای JavaScript را بگیرد. در معماری مدرن وب، این دو فناوری میتوانند در کنار یکدیگر کار کنند؛ JavaScript میتواند رابط کاربری و منطق عمومی برنامه را مدیریت کند و WebAssembly بخشهایی را که به محاسبات سنگین یا اجرای سریع نیاز دارند بر عهده بگیرد. WebAssembly یک زبان برنامهنویسی معمولی نیست که توسعهدهنده قرار باشد تمام برنامه را با آن از ابتدا بنویسد. WebAssembly بیشتر یک فرمت باینری و هدف کامپایل است.
برای مثال، توسعهدهنده میتواند بخشی از یک برنامه را با Rust یا C++ بنویسد و سپس آن را به WebAssembly کامپایل کند. نتیجه این فرآیند یک فایل با پسوند .wasm است که مرورگر یا محیط اجرای WebAssembly میتواند آن را بارگذاری و اجرا کند. WebAssembly یک نمایش متنی نیز دارد که معمولاً با نام WAT شناخته میشود. این قالب برای انسان قابل خواندنتر است و بیشتر برای مشاهده، آموزش، آزمایش و برخی فرآیندهای توسعه کاربرد دارد.
چرا WebAssembly ساخته شد؟
یکی از اهداف اصلی WebAssembly فراهم کردن یک فرمت قابل حمل، کمحجم و مناسب برای اجرای سریع کد است. در گذشته، اجرای بسیاری از برنامههای سنگین در مرورگر به محدودیتهای محیط وب وابسته بود. WebAssembly امکان داد زبانهایی با مدلهای سطح پایین مانند C++ و Rust نیز بتوانند به سمت اجرای کد در وب حرکت کنند. در نتیجه، توسعهدهندگان میتوانند از کتابخانهها و کدهای موجود خود در برخی پروژههای وب نیز استفاده کنند، بدون اینکه مجبور باشند همه چیز را از ابتدا با JavaScript بازنویسی کنند.
WebAssembly چگونه کار میکند؟
برای درک ساده فرآیند، میتوان مسیر زیر را در نظر گرفت:
- توسعهدهنده کد را در یک زبان مناسب مانند Rust یا C++ مینویسد.
- کد با یک ابزار یا کامپایلر مناسب به WebAssembly تبدیل میشود.
- فایل
.wasmدر برنامه وب قرار میگیرد. - JavaScript میتواند ماژول WebAssembly را بارگذاری و نمونهسازی کند.
- توابع مورد نیاز از WebAssembly در اختیار برنامه قرار میگیرند.
- JavaScript و WebAssembly میتوانند در کنار یکدیگر وظایف برنامه را انجام دهند.
WebAssembly در مرورگر داخل یک محیط اجرای کنترلشده قرار میگیرد و با سیاستهای امنیتی محیط وب کار میکند.
Module و Instance در WebAssembly چیستند؟
دو مفهوم مهم در WebAssembly عبارتاند از Module و Instance.
Module را میتوان تقریباً بهعنوان نسخه کامپایلشده و بدون حالت از کد WebAssembly در نظر گرفت. این ماژول شامل کد و تعریفهای مورد نیاز برای اجرای آن است. Instance یک نمونه اجرایی از آن Module است. Instance وضعیت اجرایی مورد نیاز را در خود دارد و توابع Export شده ماژول از طریق آن در دسترس قرار میگیرند. این تفکیک به WebAssembly اجازه میدهد یک Module را در شرایط مناسب چند بار نمونهسازی یا حتی بین برخی محیطهای اجرایی مانند Workerها به اشتراک بگذارد.
Memory در WebAssembly چیست؟
یکی دیگر از مفاهیم مهم WebAssembly، Linear Memory است. این حافظه فضایی از بایتهاست که کد WebAssembly میتواند از آن برای ذخیره و خواندن داده استفاده کند. در JavaScript نیز میتوان به حافظه WebAssembly از طریق APIهای مربوط به آن دسترسی داشت. حافظه WebAssembly بر اساس صفحات مدیریت میشود و هر صفحه اندازهای برابر با 64 KiB دارد. در عمل، ارتباط بین JavaScript و WebAssembly در برنامههای واقعی میتواند شامل انتقال داده، کار با حافظه، فراخوانی توابع و تبدیل مقادیر بین دو محیط باشد.
یک مثال ساده از اجرای WebAssembly در JavaScript
برای استفاده از WebAssembly در یک برنامه وب، میتوان ماژول WASM را از سرور دریافت و سپس آن را Compile و Instantiate کرد.
برای نمونه، ساختار کلی استفاده میتواند چیزی شبیه مثال زیر باشد:
const response = await fetch("app.wasm");
const bytes = await response.arrayBuffer();
const result = await WebAssembly.instantiate(bytes);
const wasm = result.instance.exports;
console.log(wasm.someFunction());
در این مثال، فایل WebAssembly دریافت میشود، به داده باینری تبدیل میشود و سپس یک Instance از آن ساخته میشود. اگر تابعی از ماژول Export شده باشد، JavaScript میتواند آن را فراخوانی کند.
WebAssembly چه تفاوتی با JavaScript دارد؟
JavaScript و WebAssembly برای اهداف یکسانی طراحی نشدهاند. JavaScript یک زبان سطح بالاست که برای توسعه برنامههای وب، رابط کاربری، تعامل با DOM، کار با APIهای مرورگر و بسیاری از وظایف دیگر استفاده میشود. WebAssembly در سطح پایینتری قرار دارد و بیشتر بهعنوان یک هدف کامپایل برای اجرای کد کارآمد و قابل حمل طراحی شده است. به همین دلیل، استفاده از WebAssembly معمولاً به معنی حذف JavaScript نیست. در بسیاری از برنامهها JavaScript همچنان بخش اصلی رابط کاربری و منطق برنامه باقی میماند و WebAssembly فقط قسمتهای خاصی را اجرا میکند.
آیا WebAssembly از JavaScript سریعتر است؟
پاسخ این سؤال به نوع کاری که انجام میشود بستگی دارد. WebAssembly برای محاسبات مشخص و سنگین میتواند عملکرد بسیار خوبی ارائه کند و هدف آن اجرای کد با کارایی نزدیک به کد Native روی معماریهای مختلف است. اما این موضوع به معنی «همیشه سریعتر بودن WebAssembly از JavaScript» نیست. اگر برنامه مجبور باشد مقدار زیادی داده را دائماً بین JavaScript و WebAssembly جابهجا کند، هزینه این ارتباط میتواند بخشی از مزیت عملکردی را کاهش دهد. همچنین برای بسیاری از عملیات معمول رابط کاربری، JavaScript کاملاً مناسب است و استفاده از WebAssembly لزوماً مزیتی ایجاد نمیکند.
بنابراین سؤال بهتر این نیست که «Wasm سریعتر است یا JavaScript؟»، بلکه باید پرسید:
کدام بخش از برنامه واقعاً به WebAssembly نیاز دارد؟
WebAssembly در چه پروژههایی کاربرد دارد؟
WebAssembly در پروژههایی ارزش بیشتری پیدا میکند که انجام محاسبات سنگین یا اجرای کد سطح پایین بخش مهمی از عملکرد برنامه باشد.
- ویرایش تصویر و ویدئو: برخی عملیات پردازشی سنگین میتوانند از WebAssembly بهره ببرند.
- بازیهای تحت وب: موتورهای بازی و بخشهای محاسباتی سنگین میتوانند از آن استفاده کنند.
- پردازش فایل: فشردهسازی، تبدیل فرمت و برخی عملیات محاسباتی روی فایلها.
- رمزنگاری: برخی الگوریتمها و کتابخانههای رمزنگاری را میتوان در قالب WebAssembly اجرا کرد.
- محاسبات علمی و مهندسی: محاسبات عددی سنگین یکی از سناریوهای مناسب است.
- شبیهسازی: برنامههایی که نیاز به پردازشهای پیچیده و تکرارشونده دارند.
- ابزارهای حرفهای آنلاین: برخی نرمافزارهایی که پیشتر فقط بهصورت دسکتاپ اجرا میشدند، میتوانند قسمتهایی از پردازش خود را به WebAssembly منتقل کنند.
چه زبانهایی میتوانند به WebAssembly تبدیل شوند؟
WebAssembly به یک زبان خاص محدود نیست و همین موضوع یکی از مزایای مهم آن است. زبانهایی مانند C، C++، Rust و زبانهای دیگری میتوانند در شرایط و ابزارهای مناسب به WebAssembly کامپایل شوند. به این ترتیب، توسعهدهندهای که از قبل یک کتابخانه یا کد محاسباتی در یکی از این زبانها دارد، ممکن است بتواند بخشی از آن را برای استفاده در یک برنامه وب به WebAssembly منتقل کند. این ویژگی در پروژههایی که سالها کد Native داشتهاند اهمیت زیادی دارد، زیرا بازنویسی کامل یک کتابخانه بزرگ با JavaScript همیشه منطقی یا اقتصادی نیست.
WebAssembly و JavaScript چگونه با هم ارتباط برقرار میکنند؟
WebAssembly و JavaScript میتوانند در هر دو جهت با یکدیگر ارتباط داشته باشند. JavaScript میتواند توابع Export شده توسط WebAssembly را فراخوانی کند و WebAssembly نیز میتواند توابع مورد نیاز خود را از محیط میزبان دریافت کند.
به زبان ساده، میتوان معماری را به این شکل تصور کرد:
رابط کاربری و منطق عمومی
↓
JavaScript
↓
┌─────────────────┐
│ WebAssembly │
│ محاسبات سنگین │
└─────────────────┘
↓
نتیجه
این معماری به توسعهدهنده اجازه میدهد هر فناوری را در جایی استفاده کند که مناسبتر است.
مزایای اصلی WebAssembly
۱. عملکرد بالا
یکی از مهمترین دلایل استفاده از WebAssembly، قابلیت اجرای کد با عملکرد بالا است؛ مخصوصاً برای وظایف محاسباتی.
۲. قابلیت حمل
WebAssembly برای اجرا روی طیف متنوعی از معماریها و محیطها طراحی شده است. این ویژگی آن را به یک هدف مناسب برای کامپایل تبدیل میکند.
۳. استفاده از کدهای موجود
شرکتها و تیمهای توسعه میتوانند در برخی پروژهها از کدها و کتابخانههای نوشتهشده در زبانهای دیگر دوباره استفاده کنند.
۴. همکاری با JavaScript
نیازی نیست یک برنامه بهطور کامل WebAssembly باشد. میتوان فقط بخشهایی از برنامه را به Wasm منتقل کرد.
۵. کاربرد خارج از مرورگر
WebAssembly محدود به مرورگر نیست. محیطهای دیگری نیز میتوانند Wasm را اجرا کنند و استانداردهای مرتبط با WASI برای فراهم کردن رابطهای سیستم در اجرای WebAssembly خارج از وب توسعه یافتهاند.
آیا WebAssembly جای JavaScript را میگیرد؟
خیر. چنین برداشتی تصویر دقیقی از نقش این دو فناوری ارائه نمیدهد. JavaScript همچنان برای توسعه رابطهای وب، تعامل با DOM، مدیریت رویدادها، ارتباط با بسیاری از Web APIها و ساخت بخشهای مختلف برنامه بسیار مناسب است. WebAssembly نیز برای شرایطی طراحی شده است که نیاز به اجرای کد کامپایلشده و محاسباتی با کارایی بالا وجود دارد.
به همین دلیل، مدل منطقیتر این است:
JavaScript و WebAssembly رقیب مستقیم نیستند؛ آنها میتوانند مکمل یکدیگر باشند.
معایب و محدودیتهای WebAssembly چیست؟
با وجود مزایای WebAssembly، استفاده از آن همیشه بهترین انتخاب نیست.
- فرآیند توسعه و Build میتواند نسبت به یک پروژه کاملاً JavaScript پیچیدهتر باشد.
- عیبیابی برنامه ممکن است به ابزارها و دانش بیشتری نیاز داشته باشد.
- ارتباط مداوم میان JavaScript و Wasm میتواند هزینه عملکردی داشته باشد.
- برای کارهای ساده وب، استفاده از WebAssembly ممکن است پیچیدگی اضافه ایجاد کند.
- مدیریت حافظه و داده در برخی زبانهایی که به WebAssembly کامپایل میشوند میتواند نیازمند دانش تخصصی باشد.
- صرف استفاده از WebAssembly تضمین نمیکند که یک برنامه سریعتر شود؛ معماری و نوع workload اهمیت زیادی دارند.
آیا WebAssembly امن است؟
WebAssembly با هدف اجرای ایمن و Sandboxشده طراحی شده است و در مرورگر تحت سیاستها و محدودیتهای امنیتی محیط وب اجرا میشود. اما این موضوع به معنی امن بودن خودکار هر برنامه WebAssembly نیست. اگر برنامهای از یک کتابخانه مخرب یا دارای آسیبپذیری استفاده کند، WebAssembly نمیتواند جایگزین فرآیندهای امنیتی مانند بررسی وابستگیها، کنترل ورودیها، احراز هویت و مدیریت صحیح دسترسیها شود. در نتیجه، باید میان امنیت محیط اجرای WebAssembly و امنیت خود برنامه تفاوت قائل شد.
WebAssembly در خارج از مرورگر
WebAssembly در ابتدا با تمرکز بر وب ایجاد شد، اما کاربرد آن به مرورگر محدود نمانده است. امروزه میتوان WebAssembly را در محیطهایی خارج از مرورگر نیز اجرا کرد. یکی از فناوریهای مرتبط با این حوزه WASI است که برای فراهم کردن رابطهای استانداردتر جهت استفاده WebAssembly از قابلیتهایی مانند فایل، زمان، تصادفیسازی و برخی منابع سیستم طراحی شده است. این موضوع باعث شده WebAssembly بهعنوان یک فناوری قابل استفاده در سناریوهای مختلف محاسباتی خارج از صفحات وب نیز مورد توجه قرار بگیرد.
WebAssembly برای چه پروژهای مناسب است؟
قبل از استفاده از WebAssembly بهتر است یک سؤال ساده مطرح کنیم:
آیا برنامه واقعاً یک گلوگاه محاسباتی دارد که JavaScript یا راهکار فعلی بهخوبی پاسخگوی آن نیست؟
اگر پاسخ مثبت باشد، WebAssembly میتواند یک گزینه مناسب برای بررسی باشد. اما اگر پروژه یک سایت معمولی با صفحات محتوایی، فرمها، داشبوردهای ساده و عملیات استاندارد وب باشد، اضافه کردن WebAssembly فقط به دلیل «سریع بودن» آن الزاماً مزیت قابلتوجهی ایجاد نمیکند.
WebAssembly چه ارتباطی با آینده وب دارد؟
اهمیت WebAssembly فقط به سرعت اجرای چند تابع محدود نمیشود. این فناوری امکان میدهد زبانها و اکوسیستمهای مختلف به شکلی جدیتر وارد محیط وب شوند. از طرف دیگر، توسعه خود استاندارد WebAssembly نیز ادامه دارد و امکانات مختلف آن در طول زمان گسترش پیدا کردهاند. مشخصات رسمی WebAssembly اکنون نسخههای جدیدتری را نسبت به نسخه اولیه تعریف میکند و در کنار Core Specification، رابطهایی مانند JavaScript API و WASI نیز بخشهایی از اکوسیستم آن را شکل میدهند. به همین دلیل WebAssembly را میتوان فراتر از یک تکنیک ساده برای سریعتر کردن JavaScript در نظر گرفت؛ این فناوری بخشی از زیرساخت در حال توسعه برای اجرای قابل حمل کد است.
جمعبندی
WebAssembly یا Wasm یک فرمت باینری سطح پایین و قابل حمل است که به توسعهدهندگان اجازه میدهد کد نوشتهشده در زبانهایی مانند C++ و Rust را در محیطهایی مانند مرورگر اجرا کنند. مهمترین کاربرد آن زمانی است که برنامه به محاسبات سنگین، اجرای کارآمد کد یا استفاده مجدد از کتابخانههای موجود نیاز داشته باشد. با این حال، WebAssembly قرار نیست جای JavaScript را بگیرد. بهترین استفاده از آن معمولاً زمانی اتفاق میافتد که هر فناوری در جای مناسب خود قرار بگیرد: JavaScript برای بخشهای اصلی و تعاملی برنامه و WebAssembly برای قسمتهایی که از اجرای کد کامپایلشده و محاسبات کارآمد بهره میبرند.
بنابراین هنگام طراحی یک پروژه وب، بهتر است WebAssembly را نه بهعنوان یک جایگزین کامل برای JavaScript، بلکه بهعنوان یک ابزار قدرتمند برای حل مسائل مشخص در نظر بگیریم.