آقا من تلاش کردم که تا جای ممکن فارسی بنویسم و فکر کنم تو عنوان جالب نشده پس سریع انگلیسیشو میگم که جا بیوفته.
منظورم از ماژول سیستمها همون Module System هستش که احتمالا میدونید چیه فقط شاید به این اسم نمیدونید و الان میگم.
اینکه من بخوام منطقهامو بشکنم و چندتا فایل کنم و بعد یه فایلی رو توی یه فایل دیگه بیارم ازش استفاده کنم میگیم ماژول و در JS بهخاطر اینکه در طول زمان تغییرات داشته و یکپارچه هم نبوده(مثل پایتون نبوده مثلا یه تیم پشتش باشه ورژن بده) ما چند روش داریم برای اینکه ماژولهامون رو تو یه فایل وارد کنیم(فراخوانی میگیم بهش) که دو تا از مهمترین سینتکسهاش همون Require و import هستن که در واقع require نماینده CJS(Common JS) و import نماینده (ECMAScript Module)ESM.
اون اوایل که تازه میخواستن از ماژول استفاده کنن سریع راهحلی که دادن این بود که require استفاده کنیم و در واقع گویا Node.js هم این راهحلو داد و بهش گفتن CommonJS و بعدها هم ECMAScript راه حل دیگهای داد که یکم بهتر بود و اسمش شد ECMAScript Module که مرسومتره و با همون import استفاده میکنیم ازش و یکی از مهمترین فرقاشون اینه که require وایمیسه که کل فایل لود بشه (در واقع Synchronous هستش) و بعد میره خط بعدی اما import اینطوری نیستش و میتونه همزمان کدای فایل اصلی رو اجرا کنه و وقتی اون ماژولی که فراخونده بود لود شد اونم بیاره تو بازی که خب طبیعتا سریعتره.
پسوندهای هر کدوم هم اینطوریه:
این دوتا البته مرسومترین ها هستن و انواع دیگه از جمله AMD, UMD هم داریم که لینک توضیحات مختصر اونا هم پایین اینجا میذارم.
حالا یه نکته مهم اینه که این دو تا سیستم عملا اکوسیستم JS رو دوپاره کردهن و برای پکیج نوشتن دقت کرده باشید معمولا دو نسخه از این دو تا سیستم رو میذارن که هر کس از هر کدوم که داره استفاده میکنه به مشکل نخوره.
توی ESM خیلی ساده میتونیم فایل .cjs رو فراخوانی کنیم ولی تو CJS چون گفتیم synchronous هست با لطائفالحیل باید کاری کنیم تا .mjs فراخوانی شه:
const example = await import("./example.mjs")
import example from "./example.cjs"
در واقع چون برای فراخوانی ESM در CJS به شکل عادی ناتوانیم مجبوریم به جای require از فانکشن import استفاده کنیم و await هم میکنیم تا لود شه و بعد مابقی کد اجرا شه که CJS ناراحت نشه.
پیشنهاد میشه که همه از ESM استفاده کنن و یه قرارداد باشه تا کمکم کل اکوسیستم به این سمت بره(یکپارچه) و کدهای با استایل سیستم CJS بازنویسی بشن
امااااا قبلا اگه باندلرهاتون رو بعد از بیلد نگاه کرده بودید میدیدید که شما ماژول رو import کردید ولی خروجی دارید require میبینید(البته بستگی به کانفیگی که مثلا روی وبپکتون انجام دادید هم داشت و الخ) که چندان کار جالبی نبود ولی بخاطر پشتیبانی مرورگرا اینکارو میکردن که خیالشون از اجرای کد راحت باشه ولی بعضا میتونه تو فایلای بزرگ توی کارکرد تاثیراتی بذاره اما چون دیگه تقریبا همه مرورگرا ESM رو پشتیبانی میکنن الان کمتر این تغییرو توی بیلد میبینید.
حالا این وسط کوفتهبرنجی پر سروصدا (Bun) هم اومده گفته من این مشکل رو حل کردم و دیگه نگران اینکه ماژولتون ESM هست یا CJS نباشید که اگه واقعا اینکارو کرده باشه بعد از شاید یکدهه به این مشکل عجیب پایان داده و دست و جیغ و هورا !!
حالا یه نکته پایانی هم بگم اگه از هر دو نوع ماژول سیستمها برای فراخوانی استفاده کنیم میتونه مشکلساز بشه که بهش میگن Dual Package Hazard :)
ایدهی زیبا و توضیح زیباتر این مفاهیم رو بیشتر و در ابتدا از "Matt Pocock" در ویدیویی که لینکش رو میذارم فرا گرفتم و مابقی رو پراکنده از لینکهایی که پیدا کردم که اونا هم میذارم.
https://medium.com/@halilatilla/differences-between-javascript-modules-cjs-amd-umd-and-esm-f60124de131b#:~:text=CommonJS%20(CJS)%3A,and%20provides%20a%20simple%20syntax