فایل package.json یک عنصر کلیدی در بسیاری از کدبیس‌های اپلیکیشن مبتنی بر اکوسیستم Node.js است. اگر با جاوا اسکریپت کار کرده باشید یا حتی با یک پروژه پروژه فرانت‌اند برای مدتی مشغول بوده‌اید، قطعاً با فایل package.json سروکار داشته‌اید. فایل package.json نوعی مانیفست برای پروژه محسوب می‌شود.

این فایل می‌تواند کارهای زیادی انجام دهد که در برخی موارد کاملاً نامربوط به هم هستند. برای نمونه فایل package.json یک ریپازیتوری مرکزی برای ابزارها است. همچنین جایی است که npm و yarn نام‌ها و نسخه‌های پکیج‌هایی که نصب شده‌اند را نگه‌داری می‌کنند. برای مطالعه بخش قبلی از این مجموعه مقالات آموزشی، می‌توانید به لینک زیر رجوع کنید:

ساختار فایل

در این بخش مثالی از فایل package.json را ملاحظه می‌کنید:

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

اگر مشغول ساخت یک پکیج Node.js باشید که بخواهید آن را روی npm توزیع کنید، همه چیز به سرعت تغییر می‌یابند و باید مجموعه‌ی از مشخصه‌ها را داشته باشید که به افراد دیگر برای استفاده از پکیج کمک می‌کنند. در این خصوص در ادامه بیشتر توضیح خواهیم داد. به مثال زیر از یک فایل package.json توجه کنید:

مثالی از ساختار فایل package.json

این فایل مشخصه name را تعریف می‌کند که نام اپلیکیشن یا پکیج را مشخص می‌کنند و شامل نام پوشه‌ای هستند که فایل در آن قرار دارد. در ادامه مثال بسیار پیچیده‌تری را شاهد هستیم که آن را از یک اپلیکیشن نمونه Vue.js استخراج کرده‌ایم:

در این فایل موارد زیادی وجود دارند که نیاز به توضیح دارند:

  • Name – نام اپلیکیشن/پکیج را تعیین می‌کند.
  • version – نسخه کنونی را مشخص می‌سازد.
  • desctiption – توضیح خلاصه‌ای در مورد اپلیکیشن/پکیج است.
  • main – نقطه ورود اپلیکیشن را تعیین می‌کند.
  • private – اگر به صورت true تعیین شده باشد، از انتشار تصادفی اپلیکیشن/پکیج روی npm جلوگیری می‌کند.
  • scripts – مجموعه‌ای از اسکریپت‌های Node را تعریف می‌کند که می‌توان اجرا کرد.
  • dependencies – فهرستی از پکیج‌های npm را که به صورت وابستگی نصب شده‌اند تعیین می‌کند.
  • devDependencies – فهرستی از پکیج‌های npm را تعیین می‌کند که به صورت «وابستگی‌های توسعه» (development dependencies) نصب شده‌اند.
  • Engines – تعیین می‌کند که این پکیج/اپلیکیشن روی کدام نسخه‌های Node کار می‌کند.
  • Browserslist – برای تعیین نوع مرورگرها (و نسخه‌های آن‌ها) که می‌خواهید پشتیبانی شوند استفاده می‌شود.

همه مشخصه‌های فوق از سوی npm یا دیگر ابزارهایی که استفاده می‌کنیم، مورد بهره‌برداری قرار می‌گیرند.

تحلیل مشخصه‌ها

در این بخش مشخصه‌هایی را که می‌توان استفاده کرد به تفصیل بررسی می‌کنیم. ما در جاهای مختلف از عبارت «پکیج» (package) استفاده می‌کنیم، اما همان حالت در مورد اپلیکیشن‌های محلی که از پکیج‌ها استفاده نمی‌کنند نیز صدق می‌کند. اغلب این مشخصه‌ها تنها روی وب‌سایت npm استفاده می‌شوند و موارد دیگر از سوی اسکریپت‌هایی که با کد تعامل دارند مانند npm و نظایر آن مورد بهره‌برداری قرار می‌گیرند.

name

نام پکیج را تعیین می‌کند. مثالی از آن به صورت زیر است:

نام باید کمتر از 214 کاراکتر باشد و نباید فاصله داشته باشد و تنها می‌تواند شامل حروف، خط تیره (-) و زیرخط (_) باشد. دلیل این امر آن است که وقتی روی npm منتشر می‌شود یک URL خاص دریافت می‌کند که مبتنی بر همین مشخصه است. اگر بخواهید پکیج را به صورت عمومی روی گیت‌هاب منتشر کنید، همین واقعیت در مورد خصوصیت name برای نام ریپازیتوری گیت‌هاب نیز صادق است.

author

نام نویسندگان پکیج را فهرست می‌کند. مثالی از آن به صورت زیر است:

این مشخصه می‌تواند با قالب زیر نیز استفاده شود:

contributors

همانند author، پروژه می‌تواند یک یا چند مشارکت‌کننده نیز داشته باشد. این مشخصه آرایه‌ای است که مشارکت‌کنندگان در پروژه را فهرست‌بندی می‌کند. مثالی از آن به صورت زیر است:

این مشخصه می‌تواند با قالب‌بندی زیر نیز باشد:

bugs

این مشخصه ابزار «ردگیری مشکلات پکیج» (package issue tracker) را به طور عمده با صفحه issues گیت‌هاب مرتبط می‌سازد. مثالی از کاربرد این مشخصه به صورت زیر است:

Homepage

صفحه اصلی پکیج را تعیین می‌کند. مثالی از آن به صورت زیر است:

version

تعیین‌کننده نسخه کنونی پکیج است. مثالی از آن به صورت زیر است:

این مشخصه امکان استفاده از نمادهای نسخه‌بندی معناشناختی (semver) را برای نسخه‌ها می‌دهد. منظور از نسخه‌بندی معنایی این است که نسخه‌های یک پکیج یا اپلیکیشن همواره با 3 عدد x.x.x بیان می‌شوند. عدد نخست این نسخه‌بندی عدد اصلی (major) است، عدد دوم نسخه فرعی (minor) و عدد سوم نیز وصله (patch) را نمایش می‌دهد.

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

license

نشان‌دهنده لایسنس یا پروانه پکیج است. مثالی از آن به صورت زیر است:

keywords

این مشخصه شامل آرایه‌ای از کلیدواژه‌ها است که با پکیج مرتبط هستند. مثالی از آن به صورت زیر است:

این کلیدواژه‌ها به پیدا شدن پکیج شما در زمان ناوبری در میان پکیج‌های مشابه یا در زمان گشتن در وب‌سایت npm کمک می‌کنند.

description

این مشخصه شامل توضیح کوتاهی از پکیج است. مثالی از آن به صورت زیر است:

این مشخصه به طور خاص در مواردی که تصمیم دارید پکیج خود را در npm منتشر کنید و افراد بتوانند بفهمند موضوع پکیج چیست، مفید خواهد بود.

repository

این مشخصه تعیین می‌کند که ریپازیتوری کجا قرار گرفته است. مثال از آن به صورت زیر است:

به پیشوند github دقت کنید. سرویس‌های پشتیبانی شده محبوب دیگری نیز وجود دارند:

شما می‌توانید سیستم کنترل نسخه را به صورت صریح معرفی کنید:

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

main

نقطه ورود پکیج را تعیین می‌کند. زمانی که این پکیج را در یک اپلیکیشن ایمپورت می‌کنید، این همان نقطه‌ای خواهد بود که اپلیکیشن برای اکپسورت ماژول‌ها جستجو خواهد کرد. مثالی از آن به صورت زیر است:

private

اگر به صورت true تنظیم شده باشد، اپلیکیشن/پکیج نمی‌تواند به صورت تصادفی روی npm منتشر شود. مثالی از آن به صورت زیر است:

scripts

مجموعه‌ای از اسکریپت‌های node را تعریف می‌کند که می‌توان اجرا کرد. مثالی از آن به صورت زیر است:

این اسکریپت‌ها اپلیکیشن‌های خط فرمان هستند. آن‌ها را می‌توان به شکل run XXXX یا yarn XXXX فراخوانی کرد که XXXX نام فرمان است. مثالی از آن به صورت زیر است:

شما می‌توانید از هر نامی که می‌خواهید برای یک فرمان استفاده کنید و اسکریپت‌ها به صورت تئوریک می‌توانند هر کاری را اجرا کنند.

dependencies

فهرستی از پکیج‌های نصب‌شده npm به عنوان وابستگی را تعیین می‌کند. زمانی که یک پکیج را با استفاده از npm یا yarn نصب می‌کنید:

این پکیج به صورت خودکار در این فهرست قرار می‌گیرد. مثالی از آن به صورت زیر است:

devDependencies

پکیج‌های npm را فهرست می‌کند که به صورت وابستگی‌های توسعه نصب شده‌اند. این موارد از dependencies که در بخش قبلی اشاره کردیم متفاوت هستند و پکیج‌هایی هستند که تنها در روی سیستم توسعه نصب می‌شوند و لازم نیست در توزیع نهایی کد وجود داشته باشند. زمانی که یک بسته را با استفاده از دستورهای npm یا yarn نصب می‌کنید:

این پکیج به صورت خودکار در این فهرست قرار می‌گیرد. مثالی از آن به صورت زیر است:

Engines

تعیین می‌کند که این پکیج/اپلیکیشن روی کدام نسخه‌ها از Node.js و دیگر فرمان‌ها کار می‌کند. مثالی از آن به صورت زیر است:

browserslist

این مشخصه برای این استفاده می‌شود که مشخص شود کدام مرورگرها (و کدام نسخه از آن‌ها) پشتیبانی می‌شوند. این مشخصه از سوی Babel ،Autoprefixer و دیگر ابزارها پشتیبانی می‌شود تا تنها polyfill-ها و fallback-های مورد نیاز مرورگرهای هدف اضافه شوند. مثالی از آن به صورت زیر است:

این پیکربندی به آن معنی است که می‌خواهیم از 2 نسخه اصلی همه مرورگرهایی که دست‌کم 1% استفاده دارند به جز IE8 و پایین‌تر، پشتیبانی شود. آمار این مرورگرها از وب‌سایت CanIUse.com (+) استخراج می‌شود.

مشخصه‌های خاص دستور

فایل package.json می‌تواند میزبان پیکربندی خاص دستور، برای نمونه Babel ،ESLint و موارد دیگر باشد. هر یک از این موارد مشخصه خاصی مانند eslintConfig ،babel و موارد دیگر دارند. این مشخصه‌ها به نام مشخصه‌های خاص دستور شناخته می‌شوند و شیوه استفاده از آن‌ها را می‌توان در مستندات مربوط به دستور/پروژه یافت.

نسخه‌های پکیج

در بخش قبلی توضیح‌هایی در مورد اعداد نسخه‌ها مانند 3.0.0~ یا 0.13.0^ ارائه کردیم. شاید بپرسید معنی آن‌ها چیست و از کدام روش‌های دیگر برای توصیف نسخه می‌توان استفاده کرد. این نماد تعیین می‌کند که پکیج کدام به‌روزرسانی‌ها از آن وابستگی می‌پذیرد.

با فرض این که از semver استفاده می‌کنید، همه نسخه‌ها 3 رقم دارند که رقم نخست انتشار اصلی، دومی انتشار فرعی و سومی انتشار وصله است و قواعد زیر در مورد آن‌ها صدق می‌کند:

  • ~: اگر عدد به صورت 0.13.0~ نوشته شود، بدین معنی است که می‌خواهید صرفاً انتشار وصله استفاده شود. در این حالت 0.13.1 درست است، اما 0.14.0 صدق نمی‌کند.
  • ^: اگر عدد به صورت 0.13.0^ نوشته شده باشد، به این معنی است که انتشارهای وصله و فرعی نصب می‌شوند. برای نمونه 0.13.1، 0.14.0 و مواردی از این دست.
  • *: اگر عدد به صورت * نوشته باشد، به این معنی است که همه به‌روزرسانی‌ها شامل ارتقای نسخه‌های اصلی مورد قبول است.
  • >: این مقدار به آن معنی است که هر نسخه‌ای بالاتر از آن که تعیین شده مورد قبول است.
  • >=: نسخه‌ای معادل یا بالاتر از آن که تعیین شده مورد پذیرش است.
  • <=: نسخه‌ای معادل یا پایین‌تر از آن که تعیین شده مورد قبول است.
  • <: هر نسخه‌ای پایین‌تر از آن که اشاره کرده پذیرش می‌شود.

قواعد دیگری مانند زیر نیز وجود دارند:

  • no symbol: تنها نسخه خاصی که تعیین شده مورد پذیرش است.
  • Latest: از آخرین نسخه موجود استفاده می‌شود.

همچنین می‌توان برخی از قواعد فوق را برای داشتن بازه‌های خاص با هم ترکیب کرد برای نمونه:

باعث می‌شود که از نسخه 1.0.0 یا انتشارهایی از 1.1.0 به بالا و پایین‌تر از 1.2.0 استفاده کنیم.

فایل package-lock.json

فایل package-lock.json به صورت خودکار در زمان نصب کردن پکیج‌های node ایجاد می‌شود. npm در نسخه 5 فایل package-lock.json را معرفی کرده است. در بخش قبلی در مورد فایل package.json که رواج و قدمت بیشتری دارد توضیحات مفصلی ارائه کردیم. هدف از این فایل آن است که ردپای نسخه دقیق هر پکیج که نصب می‌شود، حفظ شود، به طوری که محصول 100% به همان ترتیبی که پکیج‌ها از سوی نگه‌دارندگانشان به‌روزرسانی می‌شوند، قابل بازتولید باشنبد.

این فایل یک مشکل خاص را که فایل package.json حل‌نشده باقی گذاشته بود حل می‌کند. در فایل package.json می‌توان با استفاده از نمادگذاری semver تعیین کرد که می‌خواهیم کدام نسخه‌ها ارتقا یابند. برای نمونه به مثال‌های زیر توجه کنید:

  • اگر بنویسیم 0.13.0~ به این معنی است که می‌خواهیم انتشارهای وصله به‌روزرسانی شود، برای مثال 0.1.13.1، 0.14.0 و غیره.
  • اگر بنویسیم 0.13.0^ به این معنی است که می‌خواهیم انتشارهای وصله و فرعی به‌روزرسانی شوند یعنی 0.13.1، 0.14.0 و غیره.
  • اگر بنویسیم 0.13.0 به این معنی است که همواره می‌خواهیم آن نسخه دقیق تعیین شده مورد استفاده قرار گیرد.

چرا به آن نیاز داریم؟

ما معمولاً پوشه node_modules را به گیت کامیت نمی‌کنیم، چون عموماً پوشه بزرگی است و زمانی که پروژه را روی ماشین دیگری با استفاده از دستور npm install کپی کنیم، در صورتی که از ساختار ~ استفاده کرده باشیم یک نسخه وصله از پکیج انتشار می‌یابد که باید نصب شود. همین وضعیت در مورد ^ و انتشارهای فرعی نیز صدق می‌کند.

اگر عدد دقیق نسخه مثلاً به صورت 0.13.0 تعیین شده باشد، تحت تأثیر این مشکل قرار نخواهید گرفت. در هر حال ممکن است خود شما یا کس دیگری تلاش کنید تا پروژه را در سمت دیگر با اجرای دستور npm install مقداردهی اولیه کنید.

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

فایل package-lock.json نسخه نصب‌شده کنونی از هر پکیج را ثابت می‌کند و npm از آن نسخه‌های دقیق در زمان استفاده از دستور npm install بهره خواهد گرفت. این مفهوم جدیدی نیست و ابزارهای مدیریت بسته در زبان‌های برنامه‌نویسی دیگر مثلاً کامپوزر در PHP سال‌ها است که از سیستم مشابهی استفاده می‌کنند. اگر پروژه عمومی باشد یا همکارانی داشته باشید و یا اگر از گیت به عنوان منبعی برای توزیع استفاده کنید، فایل package-lock.json باید به ریپازیتوری گیت کامیت شود تا افراد دیگر بتوانند آن را واکشی کنند.

نسخه‌های وابستگی‌ها در زمان اجرای دستور npm update در فایل package-lock.json به‌روزرسانی خواهند شد.

مثال

در این بخش مثالی از ساختار یک فایل package-lock.json ارائه می‌کنیم که در زمان اجرای دستور npm install cowsay در یک پوشه خالی به دست می‌آید:

ما cowsay را نصب کرده‌ایم که به موارد زیر وابسته است:

  • get-stdin
  • optimist
  • string-width
  • strip-eof

چنان که در مشخصه requires می‌بینیم، این پکیج‌ها به نوبه خود نیازمند پکیج‌های دیگری هستند:

  • ansi-regex
  • is-fullwidth-code-point
  • minimist
  • wordwrap
  • strip-eof

این موارد در فایل با ترتیب الفبایی اضافه شده‌اند و هر یک فیلد version، یک فیلد resolved که به مکان پکیج اشاره دارد و یک رشته دارند که از آن برای اعتبارسنجی پکیج استفاده می‌کنیم. بدین ترتیب به پایان این بخش از سری مقالات آموزش Node.js می‌رسیم. در بخش بعدی در مورد برخی دستورهای دیگر npm صحبت خواهیم کرد.

برای مطالعه قسمت بعدی این مجموعه مطلب آموزشی روی لینک زیر کلیک کنید:

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

میثم لطفی (+)

«میثم لطفی» دانش‌آموخته ریاضیات و شیفته فناوری به خصوص در حوزه رایانه است. وی در حال حاضر علاوه بر پیگیری علاقه‌مندی‌هایش در رشته‌های برنامه‌نویسی، کپی‌رایتینگ و محتوای چندرسانه‌ای، در زمینه نگارش مقالاتی با محوریت نرم‌افزار نیز با مجله فرادرس همکاری دارد.

بر اساس رای 2 نفر

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *