پرش به محتوای اصلی
بازگشت به صفحه اصلی

4 دقیقه مطالعه

SemVer توی npm به زبان ساده

توی این پست یاد می‌گیریم علامت‌های ^ و ~ توی نسخه‌گذاری npm دقیقاً چه کاری انجام می‌دن و npm install چطور باهاشون رفتار می‌کنه.

مقدمه: نسخه‌بندی معنایی (Semantic Versioning) چیه؟

ما موقع ریلیز کردن یا زدن hotfix، از یه ساختار مشخص برای نسخه‌ها استفاده می‌کنیم. مثلا 1.0.0 یا 1.0.1. این ساختار بر پایه یه روش استاندارد به اسم Semantic Versioning یا همون نسخه‌بندی معنایی ساخته شده.

این عددها نشون می‌دن که نسخه فعلی محصول ما چیه و چه تغییری توش اتفاق افتاده. وقتی از نسخه‌بندی معنایی استفاده می‌کنیم، بقیه توسعه‌دهنده‌ها راحت‌تر می‌فهمن که با آپدیت کردن برنامه قراره چیزی خراب بشه یا نه.

درک نسخه‌بندی معنایی

فرمت کلی نسخه‌بندی به صورت MAJOR.MINOR.PATCH هست. یعنی سه‌تا عدد که با نقطه جدا شدن:

  • نسخه Patch (عدد سمت راست): وقتی فقط یه باگ رو فیکس کردی، بدون اینکه تغییری توی قابلیت‌ها یا ساختار اصلی برنامه بدی. مثلا از 1.0.0 می‌رسیم به 1.0.1.
  • نسخه Minor (عدد وسط): وقتی یه قابلیت جدید اضافه می‌کنی ولی تغییری که دادی باعث نمی‌شه چیزی بترکه. مثلاً از 1.0.1 میره به 1.1.0.
  • نسخه Major (عدد سمت چپ): وقتی یه تغییری میدی که نسخه قبلی باهاش سازگار نیست. مثلاً از 1.2.3 میره به 2.0.0.

نسخه Pre-release

اگه بخوای نسخه آزمایشی منتشر کنی (مثل alpha یا beta)، می‌تونی یه خط تیره بذاری:

1.0.0-alpha
1.0.0-beta
1.2.0-rc.1

شروع یه پروژه

خیلی‌ها پروژه‌هاشون رو با نسخه 0.1.0 شروع می‌کنن. وقتی پروژه آماده بشه برای انتشار رسمی، نسخه رو می‌زارن 1.0.0.


SemVer توی npm یعنی چی؟

خب، توی npm هم همین ساختار نسخه‌بندی معنایی استفاده می‌شه. ولی یه چیز مهم‌تر اینه که توی فایل package.json می‌تونی تعیین کنی چه نسخه‌هایی از یه پکیج رو قبول داری. مثلاً اینو دیدی؟

"axios": "^1.2.3"

یا

"react": "~18.2.0"

اینا نشون می‌دن که چه نسخه‌هایی مجازن نصب بشن. حالا بریم ببینیم این علامت‌ها (^, ~, یا بدون علامت) دقیقاً چیکار می‌کنن.


^ (Caret) یعنی چی؟

علامت ^ می‌گه که نسخه‌هایی از پکیج رو می‌خوای که تغییرات Major نداشته باشن ولی Minor و Patch می‌تونن آپدیت بشن.

مثلاً:

"axios": "^1.2.3"

یعنی:

  • 1.2.4 ✅
  • 1.3.0 ✅
  • 1.9.9 ✅
  • 2.0.0 ❌

نکته: اگه نسخه از 1.0.0 پایین‌تر باشه (مثلاً ^0.2.3) اون‌وقت فقط Patch اجازه داره تغییر کنه چون تا قبل از نسخه 1، تغییرات Minor هم ممکنه ناسازگار باشن.


~ (Tilde) یعنی چی؟

علامت ~ یعنی فقط اجازه بده Patch آپدیت بشه، نه Minor و نه Major.

مثلاً:

"react": "~18.2.0"

یعنی:

  • 18.2.1 ✅
  • 18.2.5 ✅
  • 18.3.0 ❌
  • 19.0.0 ❌

بدون علامت (Exact Version)

وقتی می‌نویسی:

"lodash": "4.17.21"

یعنی فقط همین نسخه نصب شه. هیچ نسخه دیگه‌ای، حتی Patch جدیدتر، نصب نمی‌شه.


حالا وقتی npm install می‌زنی چی می‌شه؟

وقتی npm install رو می‌زنی، npm می‌ره بر اساس نسخه‌هایی که توی package.json نوشتی، بررسی می‌کنه آخرین نسخه‌ای که با اون محدودیت‌ها سازگاره چیه و همونو نصب می‌کنه.

مثلاً اگه نوشتی:

"vue": "^3.2.0"

و الان نسخه‌ی 3.3.1 منتشر شده، ولی هنوز 4.0.0 نیومده، npm نسخه‌ی 3.3.1 رو نصب می‌کنه چون با ^3.2.0 سازگاره.


فرق بین npm install و npm install package@version

وقتی npm install ساده می‌زنی، npm به package.json نگاه می‌کنه و نسخه‌ها رو طبق قوانین بالا انتخاب می‌کنه.

ولی وقتی بزنی:

npm install react@18.2.0

یعنی دقیقاً همون نسخه رو نصب کن و نسخه رو هم توی package.json می‌نویسه.


فایل package-lock.json چیکار می‌کنه؟

این فایل دقیقاً مشخص می‌کنه کدوم نسخه‌ها نصب شدن. حتی اگه محدودیتت باز باشه (^)، ولی وقتی یه بار نصب کردی، نسخه دقیقش توی package-lock.json می‌مونه که توی نصب‌های بعدی (روی دستگاه دیگه یا CI/CD) همون نسخه بیاد بالا و همه چیز قابل پیش‌بینی باشه.


پس اگه یه روز دیدی با اینکه پکیجت "^1.0.0" بود ولی نسخه‌ی 1.9.9 نصب شد، تعجب نکن! همه‌چی طبق برنامه‌ست 😄


📖 اگر با مشکل Memory Leak در Webpack هنگام استفاده از hash مواجه شده‌اید، پست مشکل Memory Leak هنگام استفاده از hash در Webpack رو بخونید.

منبع

اشتراک‌گذاری:Xin
نماد بصری علی عمرایی

علی عمرایی

Senior Frontend Engineer با ۵+ سال تجربه در React، Next.js، TypeScript و معماری فرانت‌اند سازمانی. درباره بهینه‌سازی، PWA، معماری و تجربه‌های پروژه‌های واقعی می‌نویسم.

نوشته‌های مرتبط

شاید این نوشته‌ها هم برات مفید باشن