وقتی کدهای خود را به فایلهای مختلف تقسیم میکنید، به راههایی نیاز دارید تا این فایلها بتوانند با یکدیگر صحبت کنند! در این بخش یاد میگیریم چطور قابلیتهای یک فایل را به اشتراک بگذاریم، آنها را در فایل دیگری فراخوانی کنیم و در نهایت با یک ابزار مدرن به نام Import Maps، آدرسدهیها را مثل یک حرفهای مدیریت کنیم.
برای اینکه بقیه فایلها بتوانند از توابع، متغیرها یا کلاسهای یک فایل استفاده کنند، شما باید آنها را صادر کنید. این کار با کلمه کلیدی export انجام میشود.
سادهترین راه این است که کلمه export را دقیقاً قبل از تعریف متغیر یا تابع قرار دهید:
export const name = "square";
export function draw(ctx, length, x, y, color) {
ctx.fillStyle = color;
ctx.fillRect(x, y, length, length);
return { length, x, y, color };
}
قانون مهم: شما میتوانید
var،let،const، توابع و کلاسها را صادر کنید؛ اما این آیتمها حتماً باید در سطح اصلی (Top-level) فایل باشند. یعنی مثلاً نمیتوانید دستورexportرا داخل یک تابع دیگر بنویسید.
یک روش تمیزتر و راحتتر این است که تمام کدهای خود را بنویسید و در آخرین خط فایل، همه مواردی را که میخواهید صادر شوند، داخل یک آکولاد {} قرار دهید:
export { name, draw, reportArea, reportPerimeter };
حالا که قابلیتها را صادر کردیم، چطور در فایل اصلی (مثلاً main.js) از آنها استفاده کنیم؟ با استفاده از دستور import:
import { name, draw, reportArea, reportPerimeter } from "./modules/square.js";
ابتدا کلمه کلیدی import.
داخل آکولاد {}، لیست مواردی که نیاز دارید (با کاما جدا میشوند).
کلمه کلیدی from.
مشخصکننده ماژول (Module Specifier): آدرس متنی فایل مقصد.
چرا از نقطهاسلش (
./) استفاده میکنیم؟ > نقطه (.) به معنی «پوشه فعلی» است. استفاده از مسیرهای نسبی (Relative Paths) مثل./modules/square.jsخیلی بهتر از نوشتن آدرسهای مطلق (Absolute) است؛ چون اگر کل پروژه را جابهجا کنید، آدرسها خراب نمیشوند و کد شما همهجا کار میکند.
به محض اینکه دستور import را بنویسید، آن توابع درست مثل توابع محلی همان فایل در دسترس هستند:
const myCanvas = create("myCanvas", document.body, 480, 320);
const reportList = createReportList(myCanvas.id);
// استفاده از تابع draw که از فایل square.js آمده است
const square = draw(myCanvas.ctx, 50, 50, 100, "blue");
reportArea(square.length, reportList);
reportPerimeter(square.length, reportList);
هشدار مهم: مقادیر وارد شده (Imported values) کاملاً فقطخواندنی (Read-only) هستند. درست مثل متغیرهای
const، شما نمیتوانید خودِ متغیر را دوباره مقداردهی کنید (مثلاً بنویسیدdraw = null)؛ اما اگر آن مقدار یک شیء (Object) باشد، میتوانید ویژگیهای داخلش را تغییر دهید.
در حالت عادی، مرورگرها برای آدرسدهی ماژولها به مسیرهای دقیق یا URLهای کامل نیاز دارند:
import { name as circleName } from "https://example.com/shapes/circle.js";
import { name as squareName, draw } from "./shapes/square.js";
اما در محیطهایی مثل Node.js، ما خیلی راحت نام پکیج را مینویسیم (مثلاً import _ from "lodash"). به این نامهای کوتاه، نامهای لخت (Bare module names) میگویند.
Import Maps به ما این امکان را میدهد که این رفتار جذاب Node.js را به مرورگرها هم بیاوریم! ما یک نقشه (یک شیء JSON) تعریف میکنیم و به مرورگر میگوییم هر وقت فلان کلمه کلیدی را دید، آن را به فلان آدرس واقعی تبدیل کند.
این نقشه با استفاده از یک تگ <script type="importmap"> در فایل HTML تعریف میشود:
<script type="importmap">
{
"imports": {
"shapes": "./shapes/square.js",
"shapes/square": "./modules/shapes/square.js",
"square": "./shapes/square.js",
"lodash": "/node_modules/lodash-es/lodash.js",
"lodash/": "/node_modules/lodash-es/",
"https://www.unpkg.com/moment/": "/node_modules/moment/"
}
}
</script>
حالا در کدهای جاوااسکریپت، به جای نوشتن مسیرهای طولانی، از کلمات کلیدی نقشه استفاده میکنیم:
// استفاده از نام لخت (Bare Name) به لطف نقشه بالا
import { name as squareName, draw } from "square";
// لود کردن پکیج و زیرمجموعههای آن
import _ from "lodash";
import fp from "lodash/fp.js";
برای اینکه مطمئن شوید مرورگر کاربر از Import Maps پشتیبانی میکند، میتوانید از کد زیر استفاده کنید:
if (HTMLScriptElement.supports?.("importmap")) {
console.log("تبریک! مرورگر از Import Maps پشتیبانی میکند.");
}
این قابلیت فقط برای قشنگی و کوتاهشدن کدها نیست؛ بلکه ۳ مشکل بزرگ در مهندسی نرمافزار را حل میکند:
اگر در کدهای خود از یک سرویس آنلاین (مثل unpkg) استفاده کردهاید، اما حالا میخواهید در زمان آفلاین بودن یا برای امنیت بیشتر، از فایلهای محلی خودتان (node_modules) استفاده کنید، نیازی نیست تکتک فایلهای جاوااسکریپت را ویرایش کنید؛ فقط نقشه را تغییر دهید:
{
"imports": {
"https://www.unpkg.com/moment/": "/node_modules/moment/"
}
}
فرض کنید یک پروژه بزرگ دارید که در یک بخش آن نیاز به نسخه قدیمی یک کتابخانه دارید و در بخشی دیگر نسخه جدید! با استفاده از کلید scopes در نقشه، میتوانید بگویید: «اگر فایلی که در پوشه X قرار دارد این ماژول را خواست، نسخه ۱ را به او بده، و اگر فایلی در پوشه Y خواست، نسخه ۲ را!»
{
"imports": {
"cool-module": "/node_modules/cool-module/version-2.js"
},
"scopes": {
"/node_modules/old-project-folder/": {
"cool-module": "/node_modules/cool-module/version-1.js"
}
}
}
برای اینکه مرورگرها فایلهای قدیمی را کش نکنند، ابزارهای فرانتاند معمولاً یک هش به نام فایل اضافه میکنند (مثلاً main-fg7744e1b.js). مشکل اینجاست که اگر این فایل تغییر کند، نامش عوض میشود و تمام فایلهای دیگر که این را import کرده بودند هم باید آپدیت شوند!
با Import Maps، کدهای شما همیشه یک نام ثابت را صدا میزنند و شما فقط و فقط نقشه را آپدیت میکنید:
{
"imports": {
"main_script": "/node/srcs/application-fg7744e1b.js",
"dependency_script": "/node/srcs/dependency-3qn7e4b1q.js"
}
}
اگر فایل وابستگی تغییر کرد و شد dependency-999999.js، کدهای جاوااسکریپت دستنخورده باقی میمانند و شما فقط همین یک خطِ نقشه را ویرایش میکنید. فوقالعاده نیست؟
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://developer.mozilla.org/en-US/docs/Web/JavaScript