Nikode
جاوا اسکریپت

package manager

راهنمای جامع مدیریت بسته‌های جاوااسکریپت، مقایسه npm و Bun. شامل نصب، نسخه‌گذاری و بهترین شیوه‌های مدیریت وابستگی‌ها.

مقدمه

در توسعه مدرن جاوااسکریپت، بسته‌ها قطعات قابل استفاده مجدد کد هستند - کتابخانه‌ها یا ابزارهایی که می‌توانید در پروژه‌های خود نصب و استفاده کنید. یک مدیر بسته به شما کمک می‌کند تا این بسته‌ها را پیدا، نصب، به‌روزرسانی و حذف کنید. دو مدیر بسته محبوب جاوااسکریپت امروز npm (Node Package Manager) و Bun هستند. این سند توضیح می‌دهد:

  1. بسته‌ها و مدیران بسته چیستند
  2. چگونه از npm استفاده کنیم
  3. چگونه از Bun استفاده کنیم
  4. تفاوت‌های کلیدی بین npm و Bun
  5. بهترین شیوه‌ها
  6. تمرینات تکلیف

بخش 1: بسته‌ها و مدیران بسته چیستند؟

1.1 بسته‌ها

  • یک بسته (گاهی "ماژول" نامیده می‌شود) پوشه‌ای از کد است که می‌تواند شامل باشد:

    • فایل‌های جاوااسکریپت
    • فراداده (مانند نام، نسخه، نویسنده)
    • وابستگی‌ها (بسته‌های دیگری که برای کار نیاز دارد)
  • نمونه بسته‌ها:

    • Lodash (lodash) برای توابع کمکی (مثل _.map، _.cloneDeep)
    • Express (express) برای سرورهای وب
    • React (react) برای ساخت رابط‌های کاربری

وقتی یک بسته را نصب می‌کنید، می‌توانید از توابع یا اشیاء صادر شده آن در کد خود از طریق import (ESM) یا require (CommonJS) استفاده کنید.

1.2 مدیران بسته

یک مدیر بسته ابزاری است که:

  1. نصب بسته‌ها از یک ثبت مرکزی (مانند ثبت npm)
  2. مدیریت نسخه‌ها و وابستگی‌های بسته‌ها
  3. به‌روزرسانی بسته‌ها وقتی نسخه‌های جدید در دسترس هستند
  4. حذف بسته‌هایی که دیگر نیاز ندارید

بدون مدیر بسته، باید به صورت دستی کد را دانلود، کپی و پیوند دهید - بسیار مستعد خطا. با مدیر بسته، به سادگی دستوری مثل npm install lodash اجرا می‌کنید و همه چیز را مدیریت می‌کند.


بخش 2: npm (Node Package Manager)

npm قدیمی‌ترین و پرکاربردترین مدیر بسته جاوااسکریپت است. همراه با Node.js ارائه می‌شود و از ثبت npm برای دانلود بسته‌ها استفاده می‌کند.

2.1 راه‌اندازی یک پروژه (package.json)

هر پروژه مبتنی بر npm یک فایل package.json در ریشه خود دارد. این فایل فراداده را نگه می‌دارد و وابستگی‌ها را فهرست می‌کند. برای ایجاد یکی:

mkdir my-project
cd my-project
npm init

از شما خواسته می‌شود وارد کنید:

  • name (مثل my-project)
  • version (مثل 1.0.0)
  • description (مثل A demo project using npm)
  • entry point (مثل index.js)
  • author و license

اگر می‌خواهید از درخواست‌ها رد شوید و پیش‌فرض‌ها را بپذیرید، npm init -y اجرا کنید. یک package.json حداقلی ممکن است شبیه این باشد:

{
  "name": "my-project",
  "version": "1.0.0",
  "description": "A demo project using npm",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"No tests yet\""
  },
  "author": "Your Name",
  "license": "MIT",
  "dependencies": {},
  "devDependencies": {}
}
  • scripts: دستورات سفارشی که می‌توانید از طریق npm run <script-name> اجرا کنید.
  • dependencies: بسته‌هایی که پروژه شما در زمان اجرا نیاز دارد.
  • devDependencies: بسته‌هایی که فقط در طول توسعه نیاز هستند (مثل ابزارهای تست، لینترها).

2.2 نصب بسته‌ها

برای نصب یک بسته و ذخیره آن در dependencies:

npm install lodash

این سه کار انجام می‌دهد:

  1. lodash (آخرین نسخه) را در node_modules/ دانلود می‌کند
  2. "lodash": "^<version>" را زیر "dependencies" در package.json اضافه می‌کند
  3. package-lock.json را ایجاد یا به‌روزرسانی می‌کند تا نسخه‌های دقیق را قفل کند

برای نصب یک بسته به عنوان وابستگی توسعه:

npm install --save-dev eslint

این "eslint": "^<version>" را زیر "devDependencies" اضافه می‌کند. وابستگی‌های توسعه هنگام استقرار کد تولید بسته‌بندی نمی‌شوند (مثلاً، ساخت‌های Docker معمولاً devDependencies را حذف می‌کنند).

2.2.1 دستورات رایج npm

  • npm install (یا npm i): همه بسته‌های فهرست شده در package.json را نصب می‌کند (dependencies و devDependencies را می‌خواند).
  • npm install <package-name>@<version>: یک نسخه خاص نصب می‌کند، مثلاً npm install express@4.18.2.
  • npm update: بسته‌ها را به آخرین نسخه‌ای که محدوده semver در package.json را برآورده می‌کند به‌روزرسانی می‌کند.
  • npm uninstall <package-name>: یک بسته را از node_modules و از package.json حذف می‌کند.
  • npm outdated: بسته‌هایی را که نسخه‌های جدیدتری از آنچه package.json شما اجازه می‌دهد دارند فهرست می‌کند.
  • npm audit: آسیب‌پذیری‌های امنیتی شناخته شده در وابستگی‌های نصب شده را بررسی می‌کند.

2.3 نسخه‌گذاری معنایی (semver)

npm از نسخه‌گذاری معنایی (semver) برای مدیریت نسخه‌های بسته استفاده می‌کند. یک نسخه سه بخش دارد: MAJOR.MINOR.PATCH، مثلاً 2.5.1.

  • PATCH (x.y.1x.y.2): رفع اشکالات، بدون ویژگی‌های جدید.
  • MINOR (x.1.0x.2.0): ویژگی‌های جدید سازگار با گذشته.
  • MAJOR (1.0.02.0.0): تغییرات شکستن یا به‌روزرسانی‌های API ناسازگار.

در package.json، محدوده‌های نسخه اغلب شامل caret (^) یا tilde (~) هستند:

{
  "dependencies": {
    "lodash": "^4.17.21", // نصب آخرین نسخه 4.x.x (>=4.17.21 <5.0.0)
    "lodash": "~4.17.21" // نصب آخرین نسخه 4.17.x (>=4.17.21 <4.18.0)
  }
}

استفاده از caret (^) رایج است زیرا به‌روزرسانی‌های غیرشکستن را به طور خودکار هنگام اجرای npm update اجازه می‌دهد.

2.4 نصب سراسری در مقابل محلی

  • نصب محلی (پیش‌فرض): بسته‌ها را زیر ./node_modules/ قرار می‌دهد و آنها را در package.json پروژه شما ثبت می‌کند. از این برای کتابخانه‌هایی که کد شما به آنها وابسته است استفاده کنید.

    npm install express
  • نصب سراسری: یک بسته را در یک مکان مرکزی روی دستگاه شما نصب می‌کند و ابزارهای CLI آن را در همه جا در دسترس قرار می‌دهد. از -g یا --global استفاده کنید:

    npm install -g http-server

    حالا می‌توانید http-server را از هر ترمینال اجرا کنید. کتابخانه‌ها (React، Lodash، و غیره) را سراسری نصب نکنید - فقط ابزارهای CLI (مثل eslint، nodemon، خود npm).

2.5 package-lock.json

  • وقتی بسته‌ها را نصب یا به‌روزرسانی می‌کنید، npm یک package-lock.json ایجاد یا به‌روزرسانی می‌کند.
  • این فایل نسخه‌های دقیق وابستگی‌ها را قفل می‌کند، شامل وابستگی‌های تو در تو، تا هر نصب روی هر دستگاه کد یکسانی تولید کند.
  • دستکاری نکنید package-lock.json را به صورت دستی. آن را در کنترل نسخه commit کنید تا سازگاری برای کل تیم شما تضمین شود.

بخش 3: Bun (یک Runtime و مدیر بسته جدید جاوااسکریپت)

Bun یک runtime جاوااسکریپت جدیدتر (مثل Node.js) است که شامل مدیر بسته داخلی خود، bundler و task runner است. هدف آن سریع‌تر و کارآمدتر از Node.js + npm/Yarn بودن است.

نکته: Bun هنوز در حال تکامل است. برخی بسته‌ها یا ابزارها ممکن است هنوز 100% با Bun کار نکنند. همیشه سازگاری را قبل از پذیرش Bun برای تولید بررسی کنید.

3.1 نصب Bun

  1. روی macOS یا Linux، اجرا کنید:

    curl https://bun.sh/install | bash
  2. روی Windows، دستورالعمل‌های https://bun.sh/ را دنبال کنید (با استفاده از WSL یا یک build بومی).

  3. بعد از نصب، ترمینال خود را مجدداً راه‌اندازی کنید و تأیید کنید:

    bun --version

3.2 راه‌اندازی پروژه Bun (bun init)

مثل npm init، Bun می‌تواند یک package.json (و فایل‌های پروژه دیگر) را با یک دستور ایجاد کند:

bun init

از شما خواسته می‌شود برای:

  • نام پروژه
  • نسخه
  • فایل ورودی (مثل index.js)
  • توضیحات، نویسنده، مجوز

بعد از اجرای bun init، خواهید دید:

  • یک package.json مشابه npm
  • یک فایل قفل به نام bun.lockb (فرمت باینری، مخصوص Bun)

نمونه package.json ایجاد شده توسط Bun:

{
  "name": "my-bun-project",
  "version": "0.1.0",
  "main": "index.js",
  "scripts": {
    "start": "bun run index.js"
  },
  "dependencies": {}
}

3.3 نصب بسته‌ها با Bun

برای نصب یک بسته، استفاده کنید:

bun add lodash

این انجام می‌دهد:

  1. فراداده بسته را از ثبت npm به طور پیش‌فرض دریافت می‌کند.
  2. lodash را در node_modules/ نصب می‌کند.
  3. package.json را زیر "dependencies" به‌روزرسانی می‌کند.
  4. bun.lockb را برای قفل کردن وابستگی‌ها به‌روزرسانی یا ایجاد می‌کند.

اگر می‌خواهید یک وابستگی توسعه اضافه کنید:

bun add --dev eslint

معادل‌های کلیدی Bun برای دستورات npm:

هدفدستور npmدستور Bun
نصب همه وابستگی‌هاnpm installbun install
اضافه کردن یک وابستگیnpm install <pkg>bun add <pkg>
اضافه کردن یک وابستگی توسعهnpm install -D <pkg>bun add --dev <pkg>
حذف یک وابستگیnpm uninstall <pkg>bun remove <pkg>
به‌روزرسانی وابستگی‌هاnpm updatebun update
فهرست بسته‌های قدیمیnpm outdated(هنوز کاملاً پشتیبانی نمی‌شود)

3.3.1 مقایسه سرعت

  • Bun از یک resolver سریع‌تر و کد بومی برای بسیاری از کارها استفاده می‌کند، اغلب بسته‌ها را چندین برابر سریع‌تر از npm نصب می‌کند.
  • npm پایدار، بالغ و پشتیبانی شده توسط اکثر سیستم‌های CI/CD است، اما می‌تواند روی درخت‌های وابستگی بزرگ کندتر باشد.

3.4 اجرای اسکریپت‌ها با Bun

در package.json، اسکریپت‌ها به طور مشابه کار می‌کنند:

{
  "scripts": {
    "start": "node index.js",
    "test": "jest"
  }
}

برای اجرای یک اسکریپت به سبک npm، استفاده کنید:

bun run start
bun run test

Bun همچنین bun x را برای اجرای باینری‌ها از node_modules/.bin محلی شما ارائه می‌دهد:

bun x eslint .

(این eslint نصب شده محلی را بدون نیاز به npx اجرا می‌کند.)

3.5 فایل قفل Bun: bun.lockb

  • Bun از یک فایل قفل باینری (bun.lockb) به جای JSON (package-lock.json یا yarn.lock) استفاده می‌کند.
  • دستکاری نکنید bun.lockb را به صورت دستی.
  • bun.lockb را در کنترل نسخه commit کنید تا تضمین شود هر توسعه‌دهنده از همان نسخه‌های قفل شده استفاده می‌کند.

3.6 استفاده از Bun در مقابل Node.js مستقیم

  • bun run <script> به طور خودکار از runtime Bun (که بسیار سریع است) استفاده می‌کند.
  • هنوز می‌توانید node index.js اجرا کنید اگر می‌خواهید از Node.js به جای موتور JS Bun استفاده کنید (مثلاً برای تست سازگاری).

بخش 4: مقایسه npm و Bun

ویژگیnpmBun
سن و بلوغمنتشر شده 2010، بسیار پایدار و پرکاربردمنتشر شده 2022، به سرعت در حال تکامل اما جدیدتر
سرعتمعمولاً کندتر روی نصب‌های بزرگبسیار سریع - خصوصاً برای نصب‌ها و اجرای اسکریپت
فرمت فایل قفلpackage-lock.json (JSON)bun.lockb (باینری)
ثبتثبت npm به طور پیش‌فرضثبت npm به طور پیش‌فرض (می‌توان ثبت‌های جایگزین اضافه کرد)
نحو CLInpm install، npm run، npm uninstall، و غیرهbun add، bun remove، bun run، bun install
سازگاریبا همه بسته‌ها و ابزارهای Node.js کار می‌کندهدف سازگاری با اکثر بسته‌های npm است، اما برخی addon های بومی یا اسکریپت‌ها ممکن است شکست بخورند
نصب سراسریnpm install -g <pkg>bun install -g <pkg>
اجرای اسکریپت‌هابه طور پیش‌فرض از Node.js استفاده می‌کندبه طور پیش‌فرض از runtime JS Bun استفاده می‌کند
اکوسیستم و ابزارهای جامعهاکوسیستم عظیم، بسیاری آموزش‌ها، بسیاری یکپارچه‌سازی‌های CI/CDاکوسیستم در حال رشد؛ Bun را به عنوان جایگزین drop-in یکپارچه کنید، اما خطوط ساخت را بررسی کنید

4.1 انتخاب بین npm و Bun

  • از npm استفاده کنید اگر:

    • به حداکثر پایداری و سازگاری نیاز دارید.
    • خط CI/CD شما قبلاً انتظار npm یا yarn را دارد.
    • از بسته‌های قدیمی یا مبهم استفاده می‌کنید که ممکن است با Bun خوب کار نکنند.
  • از Bun استفاده کنید اگر:

    • نصب‌ها و ساخت‌های سریع‌تر می‌خواهید.
    • یک پروژه جدید شروع می‌کنید و می‌خواهید آزمایش کنید.
    • با عیب‌یابی گاه‌به‌گاه مشکلات سازگاری راحت هستید.

حتی می‌توانید ترکیب کنید: از Bun محلی برای سرعت استفاده کنید، اما اسکریپت‌های npm را در CI نگه دارید تا تأیید کنید Bun آنجا کار می‌کند.


بخش 5: بهترین شیوه‌ها

5.1 همیشه فایل قفل خود را commit کنید

  • برای npm: package-lock.json را commit کنید.
  • برای Bun: bun.lockb را commit کنید.
  • این تضمین می‌کند که همه در تیم شما (یا در محیط CI شما) نسخه‌های یکسان وابستگی‌ها را نصب کنند.

5.2 جدا کردن Dependencies در مقابل DevDependencies

  • Dependencies: زمانی که کد شما در تولید اجرا می‌شود نیاز است (مثل express، react).
  • DevDependencies: فقط در طول توسعه نیاز است (مثل eslint، jest، webpack).

مثال:

npm install express        # => به "dependencies" اضافه شد
npm install --save-dev jest # => به "devDependencies" اضافه شد

یا با Bun:

bun add express
bun add --dev jest

5.3 نسخه‌گذاری معنایی و محدوده‌های نسخه

  • به طور پیش‌فرض از caret (^) استفاده کنید تا به‌روزرسانی‌های جزئی/پچ هنگام اجرای npm update یا bun update اعمال شوند.
  • از ستاره‌ها (*) یا محدوده‌های بیش از حد گسترده که می‌توانند تغییرات شکستن غیرمنتظره ایجاد کنند اجتناب کنید.

مثال در package.json:

"dependencies": {
  "lodash": "^4.17.21",
  "express": "^4.18.2"
}

5.4 بهداشت فایل قفل

  • بعد از اضافه یا حذف وابستگی‌ها، اجرا کنید:

    • npm: npm install برای به‌روزرسانی package-lock.json.
    • Bun: bun install برای به‌روزرسانی bun.lockb.
  • فایل‌های قفل را دستی ویرایش نکنید.

5.5 نام‌گذاری و استفاده از اسکریپت

  • از نام‌های اسکریپت واضح استفاده کنید. مثلاً:

    "scripts": {
      "start": "node index.js",
      "dev": "nodemon index.js",
      "build": "webpack --config webpack.config.js",
      "test": "jest"
    }
  • اسکریپت‌ها را به طور مداوم اجرا کنید:

    • npm: npm run dev
    • Bun: bun run dev یا bun x jest (اگر می‌خواهید یک باینری مستقیماً اجرا کنید)

5.6 چه زمانی ارتقا یا مهاجرت کنید

  • اگر یک پروژه پایدار با npm دارید، می‌توانید با Bun در یک شاخه یا fork جداگانه آزمایش کنید.

  • مجموعه تست خود را تحت Bun اجرا کنید:

    bun run test
  • قبل از تغییر کامل، اطمینان حاصل کنید که ساخت شما (bundle تولید) تحت Bun همانطور که انتظار می‌رود کار می‌کند. برخی ماژول‌های بومی یا API های مخصوص Node ممکن است نیاز به polyfill یا تنظیمات داشته باشند.


بخش 6: تمرینات تکلیف

  1. راه‌اندازی یک پروژه با استفاده از npm و اضافه کردن وابستگی‌ها

    • یک پوشه جدید npm-demo ایجاد کنید.
    • npm init -y اجرا کنید تا package.json تولید شود.
    • express را به عنوان وابستگی و nodemon را به عنوان devDependency نصب کنید.
    • تأیید کنید که package.json شامل ورودی‌های صحیح زیر "dependencies" و "devDependencies" است.
    • npm install اجرا کنید تا package-lock.json تولید شود.
  2. راه‌اندازی یک پروژه با استفاده از Bun و مقایسه

    • در یک پوشه جداگانه bun-demo، bun init اجرا کنید.
    • express و nodemon را با bun add express و bun add --dev nodemon نصب کنید.
    • تأیید کنید که package.json و bun.lockb ایجاد شده‌اند و شامل اطلاعات صحیح هستند.
    • سرعت npm install در مقابل bun install را با اضافه کردن چند بسته بیشتر (مثل lodash، axios، jest) مقایسه کنید. زمان‌ها را یادداشت کنید.
  3. آزمایش با اسکریپت‌ها

    • در npm-demo/package.json، یک اسکریپت "dev": "nodemon index.js" اضافه کنید.
    • در bun-demo/package.json، یک اسکریپت "dev": "bun run index.js" اضافه کنید.
    • یک index.js ساده ایجاد کنید که "Hello, package manager!" را در کنسول ثبت کند.
    • npm run dev را در npm-demo و bun run dev را در bun-demo اجرا کنید. تأیید کنید که هر دو پیام را چاپ می‌کنند و روی تغییرات فایل reload می‌کنند (با استفاده از nodemon برای npm، و restart دستی برای Bun در صورت لزوم).
  4. تمرین نسخه‌گذاری معنایی

    • در npm-demo، یک بسته با نسخه خاص نصب کنید: npm install lodash@4.17.20.
    • package.json خود را به‌روزرسانی کنید تا از "lodash": "^4.17.20" استفاده کند.
    • npm outdated اجرا کنید تا ببینید آیا نسخه جدیدتری در دسترس است. اگر بله، npm update اجرا کنید و تأیید کنید که package.json و package-lock.json بر اساس آن به‌روزرسانی می‌شوند.
    • همان مراحل را در bun-demo با استفاده از bun add lodash@4.17.20 و bun update تکرار کنید.
  5. بررسی سازگاری فایل قفل

    • repo npm-demo خود را به پوشه دیگری clone کنید (شبیه‌سازی یک هم‌تیمی).
    • npm install اجرا کنید. اطمینان حاصل کنید که node_modules دقیقاً مثل پوشه اصلی پر شده است (شامل وابستگی‌های تو در تو).
    • با bun-demo در یک clone تازه تکرار کنید: bun install اجرا کنید و محتوای node_modules را مقایسه کنید.

نتیجه‌گیری

حالا درک واضحی از دارید:

  • بسته‌ها چیستند و چرا مدیران بسته وجود دارند
  • چگونه از npm استفاده کنیم: راه‌اندازی، نصب، نسخه‌گذاری، اسکریپت‌ها، فایل قفل
  • چگونه از Bun استفاده کنیم: راه‌اندازی، نصب، دستورات مخصوص Bun، فایل قفل
  • تفاوت‌های کلیدی بین npm و Bun تا به شما کمک کند آنها را انتخاب یا ترکیب کنید
  • بهترین شیوه‌ها برای نسخه‌گذاری، فایل‌های قفل، وابستگی‌های dev در مقابل prod، و اسکریپت‌ها

تکمیل تکلیف تمرین عملی می‌دهد. چه با npm برای بلوغ آن بمانید یا با Bun برای سرعت آزمایش کنید، قادر خواهید بود وابستگی‌ها را با اطمینان در هر پروژه جاوااسکریپت مدیریت کنید. موفق باشید!