تفاوت require و import در JS یا مختصری از ماژول سیستم‌ها در JS

آقا من تلاش کردم که تا جای ممکن فارسی بنویسم و فکر کنم تو عنوان جالب نشده پس سریع انگلیسیشو میگم که جا بیوفته.منظورم از ماژول سیستم‌ها همون Module System هستش که احتمالا میدونید چیه فقط شاید به این اسم نمیدونید و الان میگم.CJS vs ESM in JSماژول و ماژول سیستم در JSاینکه من بخوام منطق‌هامو بشکنم و چندتا فایل کنم و بعد یه فایلی رو توی یه فایل دیگه بیارم ازش استفاده کنم میگیم ماژول و در JS به‌خاطر اینکه در طول زمان تغییرات داشته و یکپارچه هم نبوده(مثل پایتون نبوده مثلا یه تیم پشتش باشه ورژن بده) ما چند روش داریم برای اینکه ماژول‌هامون رو تو یه فایل وارد کنیم(فراخوانی میگیم بهش) که دو تا از مهم‌ترین سینتکس‌هاش همون Require و import هستن که در واقع require نماینده CJS(Common JS) و import نماینده (ECMAScript Module)ESM.اون اوایل که تازه میخواستن از ماژول استفاده کنن سریع راه‌حلی که دادن این بود که require استفاده کنیم و در واقع گویا Node.js هم این راه‌‌حلو داد و بهش گفتن CommonJS و بعدها هم ECMAScript راه حل دیگه‌ای داد که یکم بهتر بود و اسمش شد ECMAScript Module که مرسوم‌تره و با همون import استفاده می‌کنیم ازش و یکی از مهم‌ترین فرقاشون اینه که require وایمیسه که کل فایل لود بشه (در واقع Synchronous هستش) و بعد میره خط بعدی اما import اینطوری نیستش و میتونه همزمان کدای فایل اصلی رو اجرا کنه و وقتی اون ماژولی که فراخونده بود لود شد اونم بیاره تو بازی که خب طبیعتا سریعتره.پسوندهای هر کدوم هم اینطوریه:CJS --> .cjsESM --> .mjsاین دوتا البته مرسوم‌ترین ها هستن و انواع دیگه از جمله AMD, UMD هم داریم که لینک توضیحات مختصر اونا هم پایین اینجا میذارم.دوپارگی(چندپارگی) مسئله همیشگی در JSحالا یه نکته مهم اینه که این دو تا سیستم عملا اکوسیستم JS رو دوپاره کرده‌ن و برای پکیج نوشتن دقت کرده باشید معمولا دو نسخه از این دو تا سیستم رو میذارن که هر کس از هر کدوم که داره استفاده میکنه به مشکل نخوره.مثالی از قرار دادن هر دو شیوه مرسوم ماژول سیستم در پکیج‌هانحوه فراخوانی هر یک از ماژول‌ها با ماژول سیستم دیگرتوی ESM خیلی ساده میتونیم فایل .cjs رو فراخوانی کنیم ولی تو CJS چون گفتیم synchronous هست با لطائف‌الحیل باید کاری کنیم تا .mjs فراخوانی شه:Importing ESM(.mjs) into CJSconst example = await import(&quot./example.mjs&quot)Importing CJS(.cjs) into ESMimport example from &quot./example.cjs&quotدر واقع چون برای فراخوانی ESM در CJS به شکل عادی ناتوانیم مجبوریم به جای require از فانکشن import استفاده کنیم و await هم میکنیم تا لود شه و بعد مابقی کد اجرا شه که CJS ناراحت نشه.ESM یا CJS ؟؟پیشنهاد میشه که همه از ESM استفاده کنن و یه قرارداد باشه تا کم‌کم کل اکوسیستم به این سمت بره(یکپارچه) و کدهای با استایل سیستم CJS بازنویسی بشنمسئله باندلرهاامااااا قبلا اگه باندلرهاتون رو بعد از بیلد نگاه کرده بودید میدیدید که شما ماژول رو import کردید ولی خروجی دارید require میبینید(البته بستگی به کانفیگی که مثلا روی وب‌پکتون انجام دادید هم داشت و الخ) که چندان کار جالبی نبود ولی بخاطر پشتیبانی مرورگرا اینکارو میکردن که خیالشون از اجرای کد راحت باشه ولی بعضا میتونه تو فایلای بزرگ توی کارکرد تاثیراتی بذاره اما چون دیگه تقریبا همه مرورگرا ESM رو پشتیبانی میکنن الان کمتر این تغییرو توی بیلد میبینید.تبدیل import به require بعد از بیلد توسط باندلرکوفته برنجی و ادعای پاسخ به مسئله‌ی قدیمیحالا این وسط کوفته‌برنجی پر سروصدا (Bun) هم اومده گفته من این مشکل رو حل کردم و دیگه نگران اینکه ماژولتون ESM هست یا CJS نباشید که اگه واقعا اینکارو کرده باشه بعد از شاید یک‌دهه به این مشکل عجیب پایان داده و دست و جیغ و هورا !!حالا یه نکته پایانی هم بگم اگه از هر دو نوع ماژول سیستم‌ها برای فراخوانی استفاده کنیم میتونه مشکل‌ساز بشه که بهش میگن Dual Package Hazard :)Dual Package Hazard یا فراخوانی یک ماژول با دو ماژول سیستم منابع و تشکر :)ایده‌ی زیبا و توضیح زیباتر این مفاهیم رو بیشتر و در ابتدا از "Matt Pocock" در ویدیویی که لینکش رو میذارم فرا گرفتم و مابقی رو پراکنده از لینک‌هایی که پیدا کردم که اونا هم میذارم. https://www.youtube.com/watch?v=6_JNPmjSevohttps://adamcoster.com/blog/commonjs-and-esm-importexport-compatibility-examplesجهت مطالعه‌ی مختصر باقی ماژول سیستم‌ها:https://medium.com/@halilatilla/differences-between-javascript-modules-cjs-amd-umd-and-esm-f60124de131b#:~:text=CommonJS%20(CJS)%3A,and%20provides%20a%20simple%20syntax