در قسمت قبل در رابطه با راه اندازی محیط آماده webpack و babel صحبت کردیم اما قبل از آنکه کدنویسی این برنامه را شروع کنیم باید در مورد ES Module ها هم صحبت کنیم. اگر یادتان باشد در پروژه قبلی (برنامه مدیریت کالری غذا) تمام کدهای خود را در یک فایل App.js نوشتیم که باعث شد فایل ما بسیار شلوغ بشود. Module ها در جاوا اسکریپت به ما اجازه می دهند که یک module را به فایل خودمان اضافه کنیم. منظور چیست؟ یعنی یک فایل دیگر جاوا اسکریپت یا یک ماژول دیگر که از طریق npm نصب شده است (مثلا axios) را درون فایل فعلی خود import کنید. بدین صورت کدهای ما در چند فایل مختلف قرار می گیرد و یک فایل شروع نخواهد شد. همچنین برخی از کدهای جاوا اسکریپت در پروژه ها در namespace خودشان اجرا نشده و باعث تداخلاتی می شوند. module ها این مشکل را حل می کنند. در ضمن ماژول ها می توانند هر چیزی باشند، مثلا یک تابع باشند یا یک شیء باشند و غیره، بنابراین ساده ترین تعریف آن «یک تکه کد» است.
مشکل اینجاست که اگر مرورگر کسی از module ها پشتیبانی نکند (که بیشتر مرورگر ها در سال 2020 از این ویژگی پشتیبانی می کنند و هدف این پروژه فقط هدف تمرینی است) و بخواهیم به صورت دستی کدهایمان را درون چند فایل قرار دهیم، باید آن ها را با چندین تگ script وارد فایل HTML کنیم. این کار مشکل دارد چرا که تعداد درخواست های بین مرورگر و سرور زیاد می شود (هر فایل یک درخواست جداگانه ارسال خواهد کرد) و سرعت باز شدن صفحه به شدت کند خواهد شد. همچنین در برخی از موارد ممکن است باعث تداخل بین فایل های مختلف شویم (مثلا وابستگی یک فایل بعد از خود فایل بارگذاری شود که خودش باعث خطا خواهد شد و الی آخر).
ما انواع مختلف سیستم های module را برای جاوا اسکریپت داریم (commonjs و amd و harmony و ...) که حالت های مختلفی برای وارد کردن و خروجی گرفتن از فایل ها و کدها هستند (در اصل همگی یکی هستند اما syntax هر کدام فرق می کند) اما من می خواهم در مورد commonjs صحبت کنم و از syntax آن استفاده خواهم کرد. توجه کنید که commonjs اصلا در مرورگر ها قابل اجرا نیستند و توسط nodeJS پیاده سازی شده اند. برای اجرای آن ها به یک module bundler مثل webpack نیاز داریم.
برای شروع درون پوشه src یک فایل جدید به نام mymodule1.js ایجاد کنید. برای شروع می گوییم:
module.exports =
این کد می گوید که کدهای پس از علامت مساوی قرار است یک ماژول برای من باشند و تو باید آن ها را export کنی، یعنی از آن ها خروجی بگیری تا بعدا فایل های دیگر بتوانند آن را import کنند (از کدهای آن استفاده کنند). من فعلا کد ساده ای می نویسم و فقط یک شیء را به آن می دهم:
module.exports = { name: 'Amir', email: 'test@test.com' }
این کد module ما است! حالا می توانیم به app.js برویم و کدهای Hello world آن را پاک کنیم تا صفحه خالی شود. سپس برای استفاده از ماژولی که در فایل mymodule1.js تعریف کرده بودیم به صورت زیر عمل می کنیم:
// CommonJS Module Syntax const person = require('./mymodule1'); console.log(person.name);
کد بالا در مرورگر به ما Amir را می دهد بنابراین در یک فایل به اطلاعات فایل دیگر دسترسی خواهیم داشت. بدین صورت تمام ماژول های ما (حتی اگر هزار عدد هم باشند) در یک فایل نهایی (app.bundle.js) قرار می گیرند و فقط همان یک فایل به مرورگر داده خواهد شد. این روش، روش commonjs بود.
حالا باید با syntax دیگری که مخصوص ES 2015 modules است آشنا شویم. من یک فایل دیگر به نام mymodule2.js می سازم و به شکل زیر عمل می کنم:
export const person = { name: 'John', age: 30 }
همانطور که می بینید فقط باید کلیدواژه Export را به آن اضافه کنیم. برای دسترسی به این ماژول در فایل های دیگر نیز به شکل زیر عمل می کنیم:
// ES2015 Module import { person } from './mymodule2';
این کد دقیقا معادل کد require در سیستم commonjs است. یعنی اگر بخواهیم ماژولی را بر اساس نامش وارد کنیم باید آن را درون علامت های {} قرار دهیم. حالا به فایل mymodule2.js برمی گردیم و یک ماژول دیگر را نیز می نویسیم:
export const person = { name: 'John', age: 30 } export function sayHello() { return `Hello ${person.name}`; }
این بار ماژول من یک تابع است. حالا می توانیم هر دو را با ویرگول جدا کرده و در یک دستور وارد فایل app.js کنیم:
// ES2015 Module import { person, sayHello } from './mymodule2';
حالا ممکن است در فایل شما صد ها ماژول باشد و بخواهید به همه آن ها دسترسی داشته باشید بنابراین نمی توان تک تک آن ها را نام برد تا وارد فایل شوند. راه حل به شکل زیر است:
import * as mod from './mymodule2';
ستاره یعنی همه چیز، تمام ماژول هایی که وجود دارند. زمانی که می گوییم as mod یعنی یک نام مستعار به نام mod را برای این import انتخاب کرده ایم، یعنی تمام ماژول های موجود در این فایل را با نام مستعار mod وارد این فایل کن. شما می توانید این نام را هر چیزی بگذارید. مثال استفاده:
import * as mod from './mymodule2'; console.log(mod.person.name); console.log(mod.sayHello());
بدین صورت می توانیم به موارد درون فایل ماژول ها دسترسی داشته باشیم. حالا دوباره به فایل mymodule2 بروید:
export const person = { name: 'John', age: 30 } export function sayHello() { return `Hello ${person.name}`; } const greeting = 'Hello World'; export default greeting;
زمانی که یک ماژول را به عنوان default تعیین و export کنیم (مانند رشته greeting در کد بالا) دیگر نیازی نیست که آن را درون علامت های {} بگذاریم. مثال استفاده در فایل app.js:
import greeting from './mymodule2'; console.log(greeting);
کد بالا به خوبی کار می کند.
امیدوارم مفهوم کلی ماژول ها را درک کرده باشید. از جلسه بعد شروع به کدنویسی UI کرده و برنامه را به شما معرفی خواهم کرد.
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.