در این درس میخوانید
وقتی یک برنامه رشد میکند، نگهداشتن محاسبه، نمایش و ارتباط شبکه در یک فایل، تغییرها را سخت میکند. ماژول به فایل امکان میدهد بخش مشخصی را صادر کند و بخشهای دیگر فقط همان قرارداد را وارد کنند. در درس دوازدهم، یک تابع قیمت را از برنامه جدا میکنیم. هدف، افزودن ابزار زیاد نیست؛ میخواهیم وابستگیها روشن باشند و منطق مستقل از صفحه قابل آزمون شود.
یک export نامدار بسازید
فایلی به نام pricing.js بسازید و تابع زیر را در آن بگذارید. export نام تابع را برای import در فایل دیگر در دسترس قرار میدهد. تابع به document یا دادهٔ سراسری وابسته نیست و فقط دو عدد میگیرد. در این مثال فرض میکنیم ورودیها پیشتر اعتبارسنجی شدهاند؛ اگر تابع مرز دریافت دادهٔ بیرونی باشد، قرارداد اعتبارسنجی باید به آن افزوده شود.
export function calculateTotal(unitPrice, quantity) {
return unitPrice * quantity;
}این مثال به محیط مرورگر، پروژه یا Node.js نیاز دارد؛ طبق راهنمای درس اجرا کنید.اکنون app.js را کنار آن بسازید. نام داخل آکولاد باید با export نامدار سازگار باشد. مسیر نسبی با ./ شروع میشود و برای ماژول بومی مرورگر، پسوند .js را روشن مینویسیم. default export نیز وجود دارد، اما برای این مثال از نامدار استفاده میکنیم تا رابطهٔ بین دو فایل دیده شود.
import { calculateTotal } from "./pricing.js";
console.log(calculateTotal(25000, 2)); // 50000این مثال به محیط مرورگر، پروژه یا Node.js نیاز دارد؛ طبق راهنمای درس اجرا کنید.اجرای ماژول در مرورگر
در index.html از script با type برابر module استفاده کنید. ماژولهای مرورگر دامنهٔ خودشان را دارند و در strict mode اجرا میشوند. برای آزمایش، صفحه را از وبسرور محلی باز کنید؛ بازکردن مستقیم file:// میتواند به محدودیتهای ماژول و مبدأ برخورد کند. نام فایل اشتباه، پاسخ 404 یا Content-Type نامناسب از علتهای رایج خطای بارگذاری هستند؛ در Network مرورگر نتیجهٔ درخواست را ببینید.
<!doctype html>
<html lang="fa" dir="rtl">
<head><meta charset="utf-8"><title>تمرین ماژول</title></head>
<body>
<h1>نتیجه را در Console ببینید</h1>
<script type="module" src="./app.js"></script>
</body>
</html>npm چه کاری میکند؟
Node.js محیط اجرای JavaScript بیرون مرورگر است و npm ابزار مدیریت بستههای اکوسیستم آن است. package.json مشخصات پروژه، اسکریپتها و وابستگیها را نگه میدارد. dependencies برای نیازهای اجرایی پروژه و devDependencies برای ابزارهای توسعه به کار میروند؛ نحوهٔ بستهبندی نهایی به ابزار پروژه وابسته است. نصب یک بسته با npm به این معنا نیست که مرورگر، نام آن بسته را در import بومی خودکار پیدا میکند؛ برای bare import معمولاً bundler یا تنظیم import map لازم است.
node --version
npm --version
npm init -y
npm install --save-dev http-server
npx http-server . -a 127.0.0.1 -p 8080این فرمانها را در پوشهٔ آزمایشی پروژه اجرا کنید. http-server یک ابزار توسعهٔ دریافتشده از رجیستری npm است؛ برای اجرای فایلهای محلی، نام دقیق بسته و منبع آن را بررسی کنید. پس از شروع، آدرس http://127.0.0.1:8080 را در مرورگر باز کنید و نتیجهٔ 50000 را در Console ببینید. با Ctrl+C وبسرور را متوقف کنید. این سرور برای تمرین محلی است و راهنمای انتشار امن سایت روی اینترنت محسوب نمیشود.
همین ماژول را در Node اجرا کنید
برای اینکه فایلهای .js این پوشه بهصورت ES Module تفسیر شوند، ویژگی type را در package.json موجود به module تغییر دهید؛ سایر اطلاعات و وابستگیهای فایل را پاک نکنید. راه دیگر، استفادهٔ آگاهانه از پسوند .mjs است. CommonJS با require و module.exports الگوی دیگری دارد؛ در شروع، بدون بررسی قرارداد پروژه این دو را مخلوط نکنید.
// این ویژگی را در شیء اصلی package.json قرار دهید:
// "type": "module"
// سپس در ترمینال اجرا کنید:
// node app.jslockfile و نصب قابل بازتولید
پس از نصب، package-lock.json میتواند نسخهها و درخت وابستگی حلشده را ثبت کند. آن را همراه کد نگه دارید تا نصب همکار یا محیط ساخت قابل پیشبینیتر باشد. در پروژهٔ دارای lockfile هماهنگ، npm ci برای نصب تمیز و بازتولیدپذیر مناسب است و در صورت ناهماهنگی فایلها خطا میدهد. پوشهٔ node_modules معمولاً وارد مخزن نمیشود. همچنین اسکریپتها و بستههای وابسته میتوانند کد اجرا کنند؛ هر وابستگی تازه هزینهٔ نگهداری دارد.
تمرین و پاسخ پیشنهادی
فایلی به نام progress.js بسازید که درصد پیشرفت را محاسبه کند؛ اگر total صفر یا منفی بود، صفر برگرداند. تابع را از app.js وارد و برای completed برابر 5 و total برابر 20 اجرا کنید. خروجی باید 25 باشد. نام تابع و قرارداد صفر را در هر دو فایل ثابت نگه دارید. نمونهٔ زیر محتوای progress.js است و در فایل مصرفکننده باید percent را بهصورت نامدار import کنید.
export function percent(completed, total) {
if (total <= 0) return 0;
return Math.round(completed / total * 100);
}
// در app.js: import { percent } from "./progress.js";
// console.log(percent(5, 20)); // 25این مثال به محیط مرورگر، پروژه یا Node.js نیاز دارد؛ طبق راهنمای درس اجرا کنید.منابع انگلیسی
- MDN — JavaScript modules
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules
- Node.js — ECMAScript modules
- https://nodejs.org/api/esm.html
- npm — package.json
- https://docs.npmjs.com/cli/v11/configuring-npm/package-json/
این ساختار و تمرین برای مجموعهٔ درسآوند تدوین شدهاند. در درس بعد، خطاها را دستهبندی میکنیم و با debugger و breakpoint دنبال علت میگردیم.
پیشنیاز و محیط اجرای مثالها
درس 12 از ۲۰؛ پیشنیاز: درسهای قبلی مجموعه. مرورگر بهروز و Node.js LTS نصبشده لازم است. فایلهای مثال را در پوشهٔ آزمایشی بسازید؛ فرمانهای npm را داخل همان پوشه اجرا کنید.
پیشرفت روی همین مرورگر ذخیره میشود.