فارسی

تفاوت‌های بین CommonJS و ES Modules، دو سیستم ماژول غالب در جاوا اسکریپت، را با مثال‌های عملی و دیدگاه‌هایی برای توسعه وب مدرن کاوش کنید.

سیستم‌های ماژول: CommonJS در مقابل ES Modules - راهنمای جامع

در دنیای همیشه در حال تحول توسعه جاوا اسکریپت، ماژولار بودن سنگ بنای ساخت اپلیکیشن‌های مقیاس‌پذیر و قابل نگهداری است. دو سیستم ماژول به طور تاریخی بر این حوزه تسلط داشته‌اند: CommonJS و ES Modules (ESM). درک تفاوت‌ها، مزایا و معایب آن‌ها برای هر توسعه‌دهنده جاوا اسکریپت، چه در فرانت-اند با فریم‌ورک‌هایی مانند React، Vue یا Angular و چه در بک-اند با Node.js، حیاتی است.

سیستم‌های ماژول چیستند؟

یک سیستم ماژول راهی برای سازماندهی کد در واحدهای قابل استفاده مجدد به نام ماژول فراهم می‌کند. هر ماژول بخش خاصی از عملکرد را در بر می‌گیرد و فقط قسمت‌هایی را که سایر ماژول‌ها برای استفاده به آن نیاز دارند، در معرض دید قرار می‌دهد. این رویکرد باعث ارتقاء قابلیت استفاده مجدد کد، کاهش پیچیدگی و بهبود قابلیت نگهداری می‌شود. ماژول‌ها را مانند بلوک‌های ساختمانی در نظر بگیرید؛ هر بلوک هدف خاصی دارد و شما می‌توانید آنها را برای ایجاد ساختارهای بزرگتر و پیچیده‌تر ترکیب کنید.

مزایای استفاده از سیستم‌های ماژول:

CommonJS: استاندارد Node.js

CommonJS به عنوان سیستم ماژول استاندارد برای Node.js، محیط اجرای محبوب جاوا اسکریپت برای توسعه سمت سرور، ظهور کرد. این سیستم برای رفع نبود یک سیستم ماژول داخلی در جاوا اسکریپت در زمان ایجاد Node.js طراحی شده بود. Node.js از CommonJS به عنوان روش خود برای سازماندهی کد استفاده کرد. این انتخاب تأثیر عمیقی بر نحوه ساخت اپلیکیشن‌های جاوا اسکریپت در سمت سرور داشت.

ویژگی‌های کلیدی CommonJS:

سینتکس CommonJS:

در اینجا مثالی از نحوه استفاده از CommonJS آورده شده است:

ماژول (math.js):

// math.js
function add(a, b) {
 return a + b;
}

function subtract(a, b) {
 return a - b;
}

module.exports = {
 add: add,
 subtract: subtract
};

استفاده (app.js):

// app.js
const math = require('./math');

console.log(math.add(5, 3)); // خروجی: 8
console.log(math.subtract(10, 4)); // خروجی: 6

مزایای CommonJS:

معایب CommonJS:

ES Modules (ESM): سیستم ماژول استاندارد جاوا اسکریپت

ES Modules (ESM) سیستم ماژول رسمی و استاندارد شده برای جاوا اسکریپت است که با ECMAScript 2015 (ES6) معرفی شد. هدف آنها ارائه یک روش منسجم و کارآمد برای سازماندهی کد در Node.js و مرورگر است. ESM پشتیبانی از ماژول بومی را به خود زبان جاوا اسکریپت می‌آورد و نیاز به کتابخانه‌ها یا ابزارهای ساخت خارجی برای مدیریت ماژولار بودن را از بین می‌برد.

ویژگی‌های کلیدی ES Modules:

سینتکس ES Modules:

در اینجا مثالی از نحوه استفاده از ES Modules آورده شده است:

ماژول (math.js):

// math.js
export function add(a, b) {
 return a + b;
}

export function subtract(a, b) {
 return a - b;
}

// یا به طور جایگزین:
// function add(a, b) {
//  return a + b;
// }
// function subtract(a, b) {
//  return a - b;
// }
// export { add, subtract };

استفاده (app.js):

// app.js
import { add, subtract } from './math.js';

console.log(add(5, 3)); // خروجی: 8
console.log(subtract(10, 4)); // خروجی: 6

صادرات نام‌گذاری شده در مقابل صادرات پیش‌فرض:

ES Modules هم از صادرات نام‌گذاری شده (named exports) و هم از صادرات پیش‌فرض (default exports) پشتیبانی می‌کند. صادرات نام‌گذاری شده به شما امکان می‌دهد چندین مقدار را با نام‌های مشخص از یک ماژول صادر کنید. صادرات پیش‌فرض به شما امکان می‌دهد یک مقدار واحد را به عنوان خروجی پیش‌فرض یک ماژول صادر کنید.

مثال صادرات نام‌گذاری شده (utils.js):

// utils.js
export function formatCurrency(amount, currencyCode) {
 // قالب‌بندی مقدار بر اساس کد ارز
 // مثال: formatCurrency(1234.56, 'USD') ممکن است '$1,234.56' را برگرداند
 // پیاده‌سازی به قالب‌بندی مورد نظر و کتابخانه‌های موجود بستگی دارد
 return new Intl.NumberFormat('en-US', { style: 'currency', currency: currencyCode }).format(amount);
}

export function formatDate(date, locale) {
 // قالب‌بندی تاریخ بر اساس منطقه
 // مثال: formatDate(new Date(), 'fr-CA') ممکن است '2024-01-01' را برگرداند
 return new Intl.DateTimeFormat(locale).format(date);
}
// app.js
import { formatCurrency, formatDate } from './utils.js';

const price = formatCurrency(19.99, 'EUR'); // اروپا
const today = formatDate(new Date(), 'ja-JP'); // ژاپن

console.log(price); // خروجی: €19.99
console.log(today); // خروجی: (بسته به تاریخ متفاوت است)

مثال صادرات پیش‌فرض (api.js):

// api.js
const api = {
 fetchData: async (url) => {
 const response = await fetch(url);
 return response.json();
 }
};

export default api;
// app.js
import api from './api.js';

api.fetchData('https://example.com/data')
 .then(data => console.log(data));

مزایای ES Modules:

معایب ES Modules:

CommonJS در مقابل ES Modules: مقایسه دقیق

در اینجا جدولی برای خلاصه‌سازی تفاوت‌های کلیدی بین CommonJS و ES Modules آورده شده است:

ویژگی CommonJS ES Modules
سینتکس Import require() import
سینتکس Export module.exports export
بارگذاری همزمان (Synchronous) غیرهمزمان (در مرورگرها)، همزمان/غیرهمزمان در Node.js
تحلیل استاتیک خیر بله
پشتیبانی بومی مرورگر خیر بله
کاربرد اصلی Node.js (تاریخی) مرورگرها و Node.js (مدرن)

مثال‌های عملی و موارد استفاده

مثال ۱: ایجاد یک ماژول ابزار قابل استفاده مجدد (بین‌المللی‌سازی)

فرض کنید در حال ساخت یک اپلیکیشن وب هستید که نیاز به پشتیبانی از چندین زبان دارد. شما می‌توانید یک ماژول ابزار قابل استفاده مجدد برای مدیریت بین‌المللی‌سازی (i18n) ایجاد کنید.

ES Modules (i18n.js):

// i18n.js
const translations = {
 'en': {
 'greeting': 'Hello, world!'
 },
 'fr': {
 'greeting': 'Bonjour, le monde !'
 },
 'es': {
 'greeting': '¡Hola, mundo!'
 }
};

export function getTranslation(key, language) {
 return translations[language][key] || key;
}
// app.js
import { getTranslation } from './i18n.js';

const language = 'fr'; // مثال: کاربر زبان فرانسه را انتخاب کرده است
const greeting = getTranslation('greeting', language);
console.log(greeting); // خروجی: Bonjour, le monde !

مثال ۲: ساخت یک کلاینت API ماژولار (REST API)

هنگام تعامل با یک REST API، می‌توانید یک کلاینت API ماژولار برای کپسوله کردن منطق API ایجاد کنید.

ES Modules (apiClient.js):

// apiClient.js
const API_BASE_URL = 'https://api.example.com';

async function get(endpoint) {
 const response = await fetch(`${API_BASE_URL}${endpoint}`);
 if (!response.ok) {
 throw new Error(`HTTP error! status: ${response.status}`);
 }
 return response.json();
}

async function post(endpoint, data) {
 const response = await fetch(`${API_BASE_URL}${endpoint}`, {
 method: 'POST',
 headers: {
 'Content-Type': 'application/json'
 },
 body: JSON.stringify(data)
 });
 if (!response.ok) {
 throw new Error(`HTTP error! status: ${response.status}`);
 }
 return response.json();
}

export { get, post };
// app.js
import { get, post } from './apiClient.js';

get('/users')
 .then(users => console.log(users))
 .catch(error => console.error('Error fetching users:', error));

post('/users', { name: 'John Doe', email: 'john.doe@example.com' })
 .then(newUser => console.log('New user created:', newUser))
 .catch(error => console.error('Error creating user:', error));

مهاجرت از CommonJS به ES Modules

مهاجرت از CommonJS به ES Modules می‌تواند یک فرآیند پیچیده باشد، به خصوص در پایگاه‌های کد بزرگ. در اینجا چند استراتژی برای در نظر گرفتن وجود دارد:

Node.js و ES Modules:

Node.js برای پشتیبانی کامل از ES Modules تکامل یافته است. شما می‌توانید با روش‌های زیر از ES Modules در Node.js استفاده کنید:

انتخاب سیستم ماژول مناسب

انتخاب بین CommonJS و ES Modules به نیازهای خاص شما و محیطی که در آن توسعه می‌دهید بستگی دارد:

نتیجه‌گیری

درک تفاوت‌های بین CommonJS و ES Modules برای هر توسعه‌دهنده جاوا اسکریپت ضروری است. در حالی که CommonJS به طور تاریخی استاندارد Node.js بوده است، ES Modules به دلیل ماهیت استاندارد، مزایای عملکردی و پشتیبانی از تحلیل استاتیک، به سرعت در حال تبدیل شدن به انتخاب ارجح برای هر دو مرورگر و Node.js هستند. با در نظر گرفتن دقیق نیازهای پروژه و محیطی که در آن توسعه می‌دهید، می‌توانید سیستم ماژولی را انتخاب کنید که به بهترین وجه با نیازهای شما مطابقت دارد و اپلیکیشن‌های جاوا اسکریپت مقیاس‌پذیر، قابل نگهداری و کارآمد بسازید.

همچنان که اکوسیستم جاوا اسکریپت به تکامل خود ادامه می‌دهد، آگاه ماندن از آخرین روندها و بهترین شیوه‌های سیستم ماژول برای موفقیت حیاتی است. به آزمایش با هر دو CommonJS و ES Modules ادامه دهید و ابزارها و تکنیک‌های مختلف موجود را برای کمک به ساخت کد جاوا اسکریپت ماژولار و قابل نگهداری کاوش کنید.