ماژول‌های ECMAScript در Node.js

ماژول‌های ECMAScript (ESM) استاندارد رسمی برای بسته‌بندی کد جاوااسکریپت هستند. این ماژول‌ها با استفاده از دستورهای import و export تعریف می‌شوند و در Node.js به‌طور کامل پشتیبانی می‌شوند. Node.js علاوه بر پشتیبانی از ESM، امکان تعامل با سیستم قدیمی CommonJS را نیز فراهم می‌کند. توسعه‌دهندگان می‌توانند با استفاده از پسوند .mjs، فیلد "type": "module" در فایل package.json یا فلگ --input-type=module فایل‌ها را به‌عنوان ماژول ECMAScript مشخص کنند. این ماژول‌ها قابلیت‌های مدرن مانند import.meta، بارگذاری پویا (import())، و پشتیبانی از JSON و WASM را ارائه می‌دهند.

import / export.mjs / .cjs / package.json typerelative, bare, and absolute specifiersfile:, node:, data: URLs

~4 دقیقه مطالعه • بروزرسانی ۸ دی ۱۴۰۴

1. معرفی


ماژول‌های ES با استفاده از import و export تعریف می‌شوند. برای مثال:


// addTwo.mjs
export function addTwo(num) {
  return num + 2;
}

// app.mjs
import { addTwo } from './addTwo.mjs';
console.log(addTwo(4)); // خروجی: 6

2. فعال‌سازی ماژول‌های ES


  • فایل‌هایی با پسوند .mjs.
  • فایل package.json با فیلد "type": "module".
  • استفاده از فلگ --input-type=module.

برای فعال‌سازی CommonJS می‌توان از پسوند .cjs یا "type": "commonjs" استفاده کرد.


3. Specifierها در import


  • نسبی: ./startup.js یا ../config.mjs.
  • Bare: some-package یا some-package/shuffle.
  • مطلق: file:///opt/nodejs/config.js.

در specifierهای نسبی و مطلق باید پسوند فایل به‌طور کامل ذکر شود.


4. URLها


  • ماژول‌ها به‌صورت URL بارگذاری و cache می‌شوند.
  • پروتکل‌های file:، node: و data: پشتیبانی می‌شوند.
  • پروتکل data: از JavaScript، JSON و WASM پشتیبانی می‌کند.

5. Import Attributes


ویژگی‌های import امکان مشخص کردن نوع ماژول را فراهم می‌کنند:


import fooData from './foo.json' with { type: 'json' };

برای وارد کردن JSON باید ویژگی type: 'json' مشخص شود.


6. ماژول‌های داخلی


ماژول‌های داخلی Node.js دارای named exports و یک default export هستند:


import { readFile } from 'node:fs';
import EventEmitter from 'node:events';

برای همگام‌سازی named exports می‌توان از module.syncBuiltinESMExports() استفاده کرد.


7. بارگذاری پویا با import()


import() امکان بارگذاری غیرهمزمان ماژول‌ها را فراهم می‌کند و هم در CommonJS و هم در ES پشتیبانی می‌شود.


8. ویژگی‌های import.meta


  • import.meta.url: آدرس کامل فایل ماژول.
  • import.meta.filename: مسیر کامل فایل ماژول.
  • import.meta.dirname: نام پوشهٔ جاری ماژول.
  • import.meta.main: اگر ماژول نقطهٔ ورود برنامه باشد مقدار true دارد.

9. مثال: import.meta.main


export function foo() { return 'Hello, world'; }

function main() {
  console.log(foo());
}

if (import.meta.main) main();

نتیجه‌گیری


ماژول‌های ECMAScript در Node.js روشی مدرن و استاندارد برای سازمان‌دهی کد هستند. با استفاده از دستورهای import و export، پشتیبانی از JSON و WASM، و ویژگی‌هایی مانند import.meta، توسعه‌دهندگان می‌توانند برنامه‌هایی تمیز، قابل تعامل و آینده‌نگر ایجاد کنند.


1. import.meta.resolve


import.meta.resolve(specifier) یک رشتهٔ URL مطلق برمی‌گرداند که نشان‌دهندهٔ مسیر حل‌شدهٔ ماژول است. این قابلیت مشابه require.resolve عمل می‌کند اما در محیط ESM استفاده می‌شود.


const asset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css

import.meta.resolve('./dep.js');
// file:///app/dep.js

این ویژگی می‌تواند عملیات همگام روی فایل‌سیستم انجام دهد و در loaders سفارشی در دسترس نیست.


2. تعامل با CommonJS


  • دستور import می‌تواند ماژول‌های CommonJS را بارگذاری کند.
  • در این حالت، module.exports به‌عنوان default export ارائه می‌شود.
  • Node.js تلاش می‌کند با تحلیل استاتیک، named exports را نیز شناسایی کند.

// cjs.cjs
exports.name = 'exported';

// ESM
import { name } from './cjs.cjs';
console.log(name); // 'exported'

3. تفاوت‌های ESM و CommonJS


  • در ESM خبری از require، exports یا module.exports نیست.
  • __filename و __dirname با import.meta.filename و import.meta.dirname جایگزین می‌شوند.
  • برای بارگذاری Addonها باید از module.createRequire() یا process.dlopen استفاده کرد.
  • require.main با import.meta.main جایگزین می‌شود.
  • کش ماژول‌ها در ESM مستقل از require.cache است.

4. JSON Modules


JSON باید با ویژگی with { type: 'json' } وارد شود:


import config from './package.json' with { type: 'json' };

5. WASM Modules


  • پشتیبانی از import در دو فاز: Source Phase و Instance Phase.
  • Source Phase امکان بارگذاری مستقیم WebAssembly.Module را فراهم می‌کند.
  • Instance Phase فایل‌های .wasm را مانند ماژول‌های معمولی بارگذاری می‌کند.

6. Top-level await


در ESM می‌توان از await در سطح بالا استفاده کرد:


// a.mjs
export const five = await Promise.resolve(5);

// b.mjs
import { five } from './a.mjs';
console.log(five); // 5

7. الگوریتم Resolution


الگوریتم پیش‌فرض ESM مبتنی بر URL است و شامل ویژگی‌های زیر است:


  • حل مسیر نسبی و مطلق.
  • عدم پشتیبانی از پسوندهای پیش‌فرض.
  • عدم پشتیبانی از پوشه‌ها به‌عنوان main.
  • پشتیبانی از node_modules برای bare specifiers.

نتیجه‌گیری


ویژگی import.meta.resolve و قابلیت‌های تعامل بین ESM و CommonJS در Node.js ابزارهای قدرتمندی برای مدیریت ماژول‌ها فراهم می‌کنند. با پشتیبانی از JSON، WASM و top-level await، توسعه‌دهندگان می‌توانند برنامه‌هایی مدرن، انعطاف‌پذیر و چندمنظوره بسازند.


نوشته و پژوهش شده توسط دکتر شاهین صیامی