سلام?️
توی این مطلب میخوایم به سوالات زیر پاسخ بدیم:
چرا وب اسمبلی؟
چی هست؟
کجا ها به کار میاد؟
الان در چه حاله؟
وب اسمبلی WASI چیه؟
اگر ازتون بپرسن JavaScript چیه شما در جواب چی میگید؟
زبان برنامه نویسیه؟
این جواب درسته ولی کامل نیست. بزارید بگم چرا:
توی دنیای امروز خیلی کم پیش میاد کد JS ای که نوشتید رو مستقیم روی مرورگر اجرا کنید.
یا Typescript کد میزنید و تبدیلش میکنید به JS.
یا مثلا Flutter خروجی وب میگیرید که تبدیل میشه به JS
یا Kotlin و CoffeeScript و Elm و….
حتی یه وقتایی شما فکر میکنید برای مرورگرتون JS کد میزنید ولی بازم اونو میدید به یه کامپایلر تبدیلش میکنه به JS و نتیجه رو روی مرورگر اجرا میکنید.
میگی نه؟ یه کامپوننت React رو کپی کن ببر روی مرورگر ببین اجرا میشه یا نه.
میخوام بگم توی دنیای امروز JS بیشتر از اینکه یه زبان برنامهنویسی باشه یه Compilation target هه.
یعنی چون JS تنها زبان برنامه نویسیه که روی مرورگر اجرا میشه (فرض کنیم WASM وجود نداره). هر زبان یا فریمورک دیگه ای که میخواد روی مرورگر رو Target کنه باید تبدیل به JS بشه. و امروزه طرفداران این زبان ها و فریم ورک ها از خود JS خالص نوشتن خیلی بیشتر شده.
از طرفی JS طراحی نشده که یک compilation target باشه. و اصلا واسه همچین موضوعی مناسب نیست و روزگار اون رو به اینجا کشونده.
همون طور که بالاتر گفتم زبان های زیادی هستن که میتونن یه JS تبدیل بشن (Dart, Kotlin, Typescript, Elm, Lua ,... ) ولی همه اینا نسبت به JS زبون های سطح بالاتری حساب میشن و حتی اونایی که امکانات سطح پایین تر دارن وقتی حرف کامپایل شدن به JS باشه دیگه اون امکاناتشون کار نمیکنه. مثلا Kotlin قابلیت Multi Threading داره ولی وقتی بخواید برنامه ی multi thread رو که با Kotlin نوشته شده رو به JS کامپایل کنید کامپایلر بهتون خطا میده چون اصلاً JS این موضوع رو ساپورت نمیکنه.
و همین محدودیت ها که JS به عنوان یه زبون سطح بالا داره باعث میشه که زبون های سطح پایین مثل C,C++ و Rust و… که زبون های سطح پایین تری هستن نتونن بهش کامپایل بشن دلیلش هم اینه که در اصل compile یعنی تبدیل یه زبون سطح بالاتر به زبان سطح پایین تر.
مثلا فرض کنید یه برنامه C داریم که توش pointer داره. و میدونیم که توی JS ما pointer نداریم حالا کامپایلر چطور میخواد کد C رو به JS تبدیل کنه؟
نمیشه!
پس دسترسی سطح پایین به حافظه نداریم.❌
هر زبانی نمیتونه به JS تبدیل بشه (گفتیم چرا).❌
برنامه نویسی multi thread نداریم.❌
پرفورمنس زبون هایی که به JS تبدیل میشن محدود به پرفورمنس خود JS میشه.❌
حجم فایل های JS در مقایسه با فرمت های باینری بیشتره چون به عنوان یه زبان برنامه نویسی برای کم حجم بودن بهینه نشده.❌
جاوااسکریپت به عنوان یه زبون تفسیری قبل از اجرا نیاز به parse شدن و optimize شدن و... داره که همش سمت کلاینت انجام میشه و کلی حافظه و زمان لازم داره و کلی انرژی اضافه مصرف میکنه که باعث میشه پول برق زیاد بیاد و طرفداران محیط زیست ناراحت بشن❌
نکته مهم: هیچ کدوم از این حرفایی که زدیم به معنی این نیست که JS زبان برنامه نویسی بدیه. برسی JS به عنوان یه زبان اصلا موضوع این پست نیست. ولی میتونیم بپذیریم که JS اصلا Compilation target خوبی نیست.
یه Compilation Target بهتر برای مرورگر هامون?.
و با توجه به اینکه web داره با سرعت وحشتناکی پیشرفت میکنه و برنامه های تحت وب هر روز داره بزرگ تر و پیچیده تر میشن به نظر میاد مرورگر های ما به یه Compilation Target بهتر نیاز دارن.
همین موضوعاتی که ما ازش حرف زدیم سال ۲۰۱۱ بحث کارمند های موزیلا بود و نتیجه این بحثا چیزی شد به اسم asm.js که بعد ها به پروژه ی WASM یا Web assembly تبدیل شد و سال ۲۰۱۶ اولین نسخه ی stable وب اسمبلی معرفی شد، سال ۲۰۱۷ گوگل به این پروژه پیوست و سال ۲۰۱۹ به یک استاندارد رسمی توی W3C تبدیل شد و سال ۲۰۲۳ که تاریخ انتشار این پست باشه هم تقریباً همه ی مرورگر های اصلی و مهم از استاندارد WASM پشتیبانی میکنند و زبان های برنامه نویسی زیادی به واسطه ی WASM قابلیت اجرا شدن توی مرورگر هارو پیدا کردن.
لیست زبان هایی که wasm رو target میکنن.
تعریف موزیلا از WASM:
WebAssembly is a new type of code that can be run in modern web browsers — it is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++, C# and Rust with a compilation target so that they can run on the web.
میفرمایند که: WebAssembly نوع جدیدی از کد است که میتواند در مرورگرهای وب مدرن اجرا شود. یک زبان شبه اسمبلی سطح پایین با فرمت باینری جمع و جور است که با performace نزدیک به native اجرا میشود. و زبان هایی مانند C / C ++، C# و Rust را میتوان به آن کامپایل کرد تا بتوانند در وب اجرا شوند.
خیلی ها معتقد اند که WASM داره دقیقا همون ایده ی JAVA رو ادامه میده. دقیقا مثل جاوا WASM هم یه زبون میانیه که مستقل از پلتفرم/سیستم عامل و معماری پردازنده هست. یعنی شما همون فایل wasm که توی IOS با پردازنده ARM اجرا میکنید رو میتونید ببرید روی Linux با پردازنده ی X86 هم اجرا کنید. و ماشین مجازی بین wasm و سخت افزار قرار میگیره و ترجمه ها و بهینه سازی های لازم رو انجام میده. فقط فرق wasm و بایت کد Java اینه که Wasm روی مرورگر هم قابل اجرا هست و فقط مخصوص یه زبان طراحی نشده و سازگاری زیادی با انواع زبان های برنامه نویسی با انواع مدل مدیریت حافظه و... داره.
مثلا جاوا مدل مدیریت حافظه ی Garbage collector رو تحمیل میکنه واسه همین مثلا C یا Rust نمیتونن به بایت کد Java تبدیل بشن.
حالا جالبه بدونید که خود Java هم میتونه به Wasm تبدیل بشه.
وب اسمبلی داره پای لایبری های معروف غیر جاوااسکریپتی رو به وب باز میکنه مثلا ffmpeg الان نسخه WASM داره! (ایناها) و شما میتونید از امکاناتش توی مرورگر و سمت کلاینت استفاده کنید.
یا مثلا به واسته ی PyScript شما میتونید کد پایتون روی مرورگر اجرا کنید و حتی از لایبری های پایتون توی برنامه ی تحت وبتون استفاده کنید.
وب اسمبلی باعث شده یسری برنامه های قدیمی قابلیت اجرا روی مرورگر هارو پیدا کنن. مثلا AutoCad که ۳۰ سالش میشه رو آوردن روی مرورگر اجرا کردن یا مثلا میتونید ویندوز ۹۸ رو روی مرورگرتون اجرا کنید
از این دلقک بازی ها که بگذریم یه موقع هایی هست واسه یه کار خاصی پرفورمنس بالایی روی وب میخواید و JS پاسخگوی شما نیست اینجا میتونید یه ماژول wasm با یه زبون سطح پایین بنویسید و از JS توابعش رو صدا کنید.
یه موقع هست شما با JS حال نمیکنید کلا میخواید با یه زبون دیگه برنامه وب بنویسید (توی بخش بعدی بهتر توضیح میدم). و همین قضیه جک های مربوط به فریم ورک های JS که هر روز یدونه جدیدیش میاد رو ده برابر خنده دار تر میکنه.
باهاش میتونید پکیج های npm بنویسید که هم داخل مرورگر و هم توی NodeJS ازش استفاده کنید.
به کمک WASI میشه ماژول های wasm رو روی سرور اجرا کرد (جلو تر در مورد اینم حرف میزنم).
در آینده ی نزدیک احتمالا شاهد این خواهیم بود که ابزار هایی بیان که بتونیم باهاشون برنامه های دسکتاپی هم با wasm و WASI درست کنیم.
هنوز جای کار داره و در حال توسعه هست از طرفی قابل استفاده و stable هه.
یه درصد کمی از برنامه هایی که هر روز استفاده میکنید ممکنه از WASM استفاده کنن میتونید developer tools رو باز کنید توی تب network فوضولی کنید ببینید فایل با پسوند wasm. پیدا میکنید یا نه؟
مثلا نرم افزار فیگما برای render کردن بخش طراحیش از wasm و ++C استفاده میکنه (هر چند که UI اش رو با React زدن مثل اینکه)
یسری از این فریمورک هایی که گفتیم مثلا Kotlin multiplatform و Flutter توی نسخه های جدید وقتی میخواید Web رو Target کنید به جای JS به WASM تبدیل میشن.
موتور بازی سازی Unity کد های #C شما رو به WASM تبدیل میکنه و بازی های تحت وب اکثرا با WASM کار میکنن.
سه چهار ماه پیش WASM GC معرفی شد که یه garbage Collector برای WASM هست. تا قبل از WASM_GC زبان هایی که GC دارن (Kotlin, Go, Dart,...) مجبور بودن GC خودشون رو توی فایل WASM بزارن و این قضیه سایز فایل wasm دانلودی رو افزایش میداد و سرعت لود شدن صفحه رو پایین میاورد ولی الان با معرفی WASM_GC این مشکل حل شده. و باعث افزایش پرفورمنس شده.
هنوز دسترسی مستقیم به DOM و خیلی API های دیگه مرورگر نداریم و برای استفاده ازشون باید از binding های js استفاده کنیم ولی در آینده ممکنه این دسترسی مستقیم فراهم بشه. که پرفورمنس وب اپلیکیشن هایی که کلا با یه زبون دیگه پیاده سازی شدن رو با حذف کامل JS افزایش میده.
امروزه شاهد ظهور وب فریم ورک هایی برای Front end هستیم که کلا JS ندارن. مثلا Leptos , Dioxus ,Yew وب فریم ورک هایی هستن که شما با اونا میتونی با زبان Rust برنامه های وب بنویسید (تازه SSR هم دارن). از طرفی ما Blazor رو سمت طرفداران Net. داریم که با #C میتونید برنامه وب بنویسید و کلی فریم ورک ریز و درشت دیگه که میتونید با سرچ کردن زبان برنامه نویسی مورد علاقتون اونارو پیدا کنید.
از نظر پرفورمنس هم این جدول رو میتونید ببینید و در نظر داشته باشید که هنوز این فریم ورک های بر پایه wasm از binding های JS برای دسترسی به DOM استفاده میکنن و شاید این جدول وقتی که این پست رو میخونید از این رو به اون رو شده باشه.
بحث آخر این پست در مورد WASI یا Web assembly system interface هست که در نوع خودش چیز عجیبیه.
تقریبا رابطه ی Wasm و WASI مثل رابطه ی JS و NodeJS میمونه.
در واقع WASM هم مثل JS وقتی داخل Sandbox مرورگر اجرا میشه دسترسی های محدودی داره.
مثلا نمیتونه یه فایل روی سیستم رو بخونه یا کارای Network سطح پایین تر از Http مثلا TCP و UDP انجام بده. چرا چون API هاش روی مرورگر وجود ندارن.
حالا WASI چیه؟ همون API های سیستمی هست که داخل مرورگر وجود ندارن.
مثلاً یه Runtime وجود داره به اسم WasmTime که با استفاده از اون میتونید کد های WASM رو بیرون مرورگر به صورت CLI اجرا کنید. و این برنامه ی قابل اجرا برای کار های سیستمی (مثل خوندن فایل و کار با شبکه و…) از استانداردهایی که WASI تعریف کرده استفاده میکنه. که این استاندارد ها هم مثل خود WASM مستقل از پلتفرم هستن و این خیلی مهمه. اونقدر مهم که سازنده ی داکر در موردش اینجوری توییت میزنه:
میفرمایند که: اگه WASM + WASI در سال ۲۰۰۸ وجود داشت, دیگه نیازی نبود ما داکر رو بسازیم. یعنی اینقدر مهمه. وب اسمبلی آینده ی پردازش های سمت سروره. جای یک رابط سیستم استاندارد خالی بود. بیاید امیدوار باشیم که WASI به وظیفه ی خودش عمل کنه.
از طرفی WASI فقط برای cloud نیست و در آینده برنامه های GUI و CLI خواهیم دید که برای اجرا نیاز به ران تایم WASM دارن. چون اینجوری برای developer خیلی راحت تره که یه خروجی بگیره و روی یه سیستم عامل تست کنه و خیالش راحت باشه که برنامه اش همه جا همون جوری کار میکنه (مثل ایده جاوا که در موردش حرف زدیم).
نکته: دقت داشته باشید که API های WASI داخل مرورگر ها قابل دسترسی نیستن.
پس WASM یه استاندارد در حال توسعه هست که در آینده ی نزدیک قرار خیلی بیشتر اسمش رو بشنویم و ازش استفاده کنیم. جاهای خیلی مختلف و متنوعی هم بهمون کمک میکنه. واسه همین به نظرم رسید که چیزایی که ازش خونده بودم رو یه جا جمع کنم و تبدیلش کنم به این مطلبی که الان خوندید.
امیدوارم مفید بوده باشه. اگر جایی اشتباهی چیزی هست بگید من حتما اصلاحش میکنم.
اگه کنجکاویتون تموم نشده میتونید WASM IO رو سرچ کنید و ویدیو هاشو ببینید. حرف های جالبی میزنن.
با خودم قرار گذاشتم که نوشته های تکنیکال بیشتری بنویسم اگر علاقه دارید ولی ویرگول ندارید میتونید منو در توییتر, لینکدین یا اینستاگرام دنبال کنید که با خبر بشید.
کنجکاو باشید✋.