مقدمه
در درس قبل با «الگوی ماژول» به عنوان یک راه حل کلاسیک برای سازماندهی کد آشنا شدیم. با معرفی
استاندارد ECMAScript 2015 (ES6)، جاوااسکریپت بالاخره صاحب یک سیستم ماژول بومی و استاندارد
شد. این سیستم که به آن ES Modules یا ESM میگویند، روشی مدرن و مبتنی بر فایل برای
نوشتن
کدهای ماژولار است و امروزه به استاندارد اصلی در توسعه جاوااسکریپت (چه در مرورگر و چه در سمت سرور
با Node.js) تبدیل شده است. این سیستم بر پایه دو کلمه کلیدی اصلی کار میکند: export
و
import.
سینتکس export و import
با ESM، هر فایل جاوااسکریپت به عنوان یک ماژول مجزا در نظر گرفته میشود. این ماژول حوزه
(scope)
مخصوص به خود را دارد و متغیرهای تعریف شده در آن به صورت پیشفرض خصوصی هستند و حوزه سراسری را
آلوده نمیکنند. برای اینکه بتوانیم از یک متغیر، تابع یا کلاس در ماژول دیگری استفاده کنیم، باید
آن را به صراحت export کنیم.
خروجی گرفتن (Exporting)
دو روش اصلی برای خروجی گرفتن از یک ماژول وجود دارد:
- خروجیهای نامگذاری شده (Named Exports): به شما اجازه میدهد تا چندین مقدار را از یک
فایل export کنید. هر مقدار باید یک نام مشخص داشته باشد.
- خروجی پیشفرض (Default Export): به شما اجازه میدهد تا یک مقدار اصلی یا پیشفرض را از
یک فایل export کنید. هر ماژول تنها میتواند یک default export داشته باشد.
JAVASCRIPT - a file named utils.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export default function multiply(a, b) {
return a * b;
}
ورودی گرفتن (Importing)
برای استفاده از مقادیر export شده، در ماژول دیگر از دستور import استفاده میکنیم.
JAVASCRIPT - a file named main.js
import multiply, { PI, add } from './utils.js';
console.log('PI is:', PI);
console.log('Sum is:', add(5, 2));
console.log('Product is:', multiply(5, 2));
در این کد، خروجی پیشفرض (`multiply`) بدون آکولاد و خروجیهای نامگذاری شده (`PI` و `add`) در
داخل آکولاد وارد میشوند.
استفاده از ماژولها در مرورگر
برای اینکه به مرورگر بگوییم یک فایل اسکریپت را به عنوان یک ماژول ESM تفسیر کند (و اجازه
استفاده از import/export را بدهد)، باید به تگ <script> خود اتریبیوت type="module"
را اضافه کنیم.
HTML
<!DOCTYPE html>
<html>
<body>
<script type="module" src="main.js"></script>
</body>
</html>
وقتی مرورگر فایل main.js را میبیند، دستور import داخل آن را خوانده و یک درخواست
دیگر برای دریافت فایل utils.js نیز ارسال میکند. این روش برای پروژههای کوچک به خوبی کار
میکند، اما برای اپلیکیشنهای بزرگ با صدها ماژول، میتواند منجر به ارسال تعداد زیادی درخواست
HTTP و کندی در بارگذاری اولیه شود.
نقش ابزارهای ساخت و باندلرها
برای حل مشکل درخواستهای متعدد و همچنین افزودن قابلیتهای دیگر، در توسعه وب مدرن از ابزارهایی به
نام «باندلرهای ماژول» (Module Bundlers) مانند Vite، Webpack
و Parcel
استفاده میشود.
کار اصلی یک باندلر این است که در مرحله «ساخت» (build)، تمام کدهای جاوااسکریپت پروژه شما را
میخواند، گراف وابستگیها (dependency graph) را بر اساس دستورات import و export
ترسیم میکند، و در نهایت تمام کدها را در یک یا چند فایل بهینهسازی شده و فشرده (که به آن
"bundle" میگویند) خروجی میدهد. این فایل نهایی همان چیزی است که در محیط پروداکشن روی سرور قرار
میگیرد.
باندلرها علاوه بر این، وظایف مهم دیگری را نیز انجام میدهند:
- ترجمه کد (Transpilation): با استفاده از ابزارهایی مانند Babel، کدهای مدرن
جاوااسکریپت را به نسخههای قدیمیتر تبدیل میکنند تا با مرورگرهای بیشتری سازگار باشند.
- کوچکسازی (Minification): فضاهای خالی، کامنتها و نام متغیرها را کوتاه میکنند تا حجم
فایل نهایی به حداقل برسد.
- پردازش سایر منابع: میتوانند فایلهای CSS، SASS،
تصاویر و فونتها را نیز پردازش کرده
و در فرآیند ساخت بهینه کنند.
- سرور توسعه: یک سرور محلی با قابلیتهایی مانند `Hot Module Replacement (HMR)` فراهم
میکنند که به شما اجازه میدهد تغییرات در کد را بدون رفرش کامل صفحه مشاهده کنید.
در این درس با سیستم ماژول بومی جاوااسکریپت (ESM) و سینتکس import/export به
عنوان
روش مدرن سازماندهی کد آشنا شدیم. همچنین دیدیم که چگونه ابزارهای توسعه مانند باندلرها، این
ماژولها را برای استفاده بهینه در محیط پروداکشن پردازش میکنند. با این درس، فصل «کار با
ماژولها» به پایان میرسد. ما از الگوهای سنتی به سیستمهای مدرن رسیدیم و اکنون آمادهایم تا
کدهایمان را برای پروژههای بزرگ مقیاسپذیر کنیم. در فصل بعدی، به سراغ «کار با Workerها» خواهیم
رفت و یاد میگیریم که چگونه با اجرای اسکریپتها در ترِدهای پسزمینه، از قفل شدن رابط کاربری
جلوگیری کرده و عملکرد اپلیکیشنهای سنگین را بهبود ببخشیم.