تولد و مرگ JavaScript
JavaScript با امتیازات بسیار محدودی در مرورگر اجرا میشود. با این حال، این زبان سرورها، ابزارهای ساخت (build tools) و حتی پایگاههای داده را مدیریت میکند. این یک برنامه از پیش تعیین شده نبود؛ بلکه مجموعهای از وصلهها بود که بر پایه تصمیمی از سال ۱۹۹۵ بنا شد.
در سال ۲۰۱۴، گری برنهاردت سخنرانیای با عنوان «تولد و مرگ JavaScript» ارائه داد. بسیاری آن را یک پیشگویی شکستخورده میبینند، اما من آن را ابزاری تشخیصی برای درک اصطکاکهای معماری میدانم.
برنهاردت مسیری کنایهآمیز را توصیف کرد. JavaScript به عنوان یک زبان ساده (toy language) شروع به کار کرد. این زبان تنها به این دلیل زنده ماند که تنها زبان موجود در مرورگر بود. این انحصار باعث شد تا حتی اگر بهترین انتخاب فنی نبود، پرکاربردترین زبان در جهان از نظر اجرا باشد.
تنش اصلی ساده است: مرورگر نیاز دارد کدها را به شکلی ایمن و سریع اجرا کند. این دو هدف اغلب با هم در تضاد هستند.
در سال ۲۰۱۴، پیشبینی میشد که WebAssembly جایگزین JavaScript شود. اما این اتفاق نیفتاد. WebAssembly پایدار است و برای مواردی مانند Figma یا Google Earth بسیار مفید است، اما نتوانست جایگزین JavaScript به عنوان یک زبان برنامهنویسی اپلیکیشن شود.
در عوض، JavaScript دچار جهش شد. TypeScript، باندلرها (bundlers) و محیطهای اجرایی (runtimes) جدیدی مانند Deno یا Bun، همگی تلاشهایی برای رفع همان اصطکاکهایی هستند که برنهاردت شناسایی کرده بود.
از این سخنرانی برای فرار از یادگیری JavaScript استفاده نکنید. همچنین از آن برای توجیه مهاجرت به WebAssembly، پیش از آنکه با مشکل واقعی در عملکرد (performance) مواجه شوید، استفاده نکنید.
از آن استفاده کنید تا این سوالات را درباره پشته تکنولوژی (stack) خود بپرسید:
• آیا از این ابزار استفاده میکنم چون بهترین راه حل برای این مشکل است؟ • آیا از آن استفاده میکنم چون تنها چیزی است که در این زمینه کار میکند؟ • آیا پیچیدگی ابزارهای من یک مشکل واقعی را حل میکند یا فقط آن را به جای دیگری منتقل میکند؟ • اگر امروز از صفر شروع میکردم، باز هم این را انتخاب میکردم؟
اگر از TypeScript در سمت سرور استفاده میکنید، به امنیت نوع (type safety) دست مییابید اما بار اضافیِ کامپایل (compilation overhead) را هم تحمیل میکنید. اگر از Next.js استفاده میکنید، از قابلیتهای بیشتری بهرهمند میشوید اما پیچیدگی کشینگ (caching) را نیز اضافه میکنید. اینها موازنههای (trade-offs) واقعی هستند.
رایجترین اشتباه این است که وقتی مشکل در واقع استفاده نادرست است، زبان را مقصر بدانید. اگر کدهای همگام (synchronous) سنگینی بنویسید که حلقه رویداد (event loop) را مسدود کند، مشکل از شماست، نه JavaScript.
از جستجو برای یک جایگزین جادویی دست بردارید. شروع کنید به اندازهگیری گلوگاههای (bottlenecks) واقعی خود.