چطور پکیج‌هایمان را در NPM منتشر کنیم؟

?How to publish our packages in NPM

13 اسفند 1399
چطور پکیج هایمان را در NPM منتشر کنیم؟

npm چیست؟

npm یا node package manager بزرگترین وب سایت میزبانی پکیج های آماده در دنیا بوده و یکی از زیر مجموعه های گیت هاب محسوب می شود که صاحب آن ماکروسافت است. توسعه دهندگان open source از سراسر دنیا در حال استفاده و به اشتراک گذاری پکیج ها در این وب سایت می باشند و در دنیای فعلی کمتر کسی است که با npm آشنا نباشد.

ما می توانیم npm را به سه قسمت اصلی تقسیم کنیم:

  • وب سایت npm: وب سایت npm برای پیدا کردن پکیج ها و اطلاعات آن ها بسیار مفید است و می توانید در آن به شخصی سازی بخش های مختلف درباره حساب npm خود بپردازید. همچنین با ایجاد یک حساب تجاری (organizations) می توانید دسترسی به پکیج های عمومی و خصوصی را تعیین کنید.
  • NPM CLI: در حقیقت CLI یا Command Line Interface تعامل با npm از طریق ترمینال است و اکثر کاربران از همین روش با npm ارتباط برقرار می کنند تا پکیج های مورد نظرشان را دانلود کنند.
  • NPM Registry: پایگاه داده بزرگی از انواع تکنولوژی های مرتبط با جاوا اسکریپت و metadata (اطلاعات جانبی و تکمیلی) در مورد آن ها است.

ما در این مقاله در مورد نحوه انتشار پکیج در npm صحبت خواهیم کرد.

قدم اول: ساخت package.json

پکیج هایی که در npm registry ثبت می شوند باید فایل package.json را داشته باشند. همانطور که توضیح دادم npm registry همان پایگاه داده npm است و برای اینکه دیگران بتوانند پکیج شما را دانلود کنند باید آن را در registry ثبت کنید. اطلاعات مهم در فایل package.json شامل موارد زیر است:

  • وابستگی های پروژه شما را مشخص می کند (پکیج هایی که از آن ها برای ساخت پکیج خود استفاده کرده اید).
  • نسخه پکیج شما را مشخص می کند که باید از semantic versioning پیروی کند (در این مقاله به صورت خلاصه در رابطه با semantic versioning صحبت خواهیم کرد).
  • پکیج شما را قابل بازسازی می کند (کاربران دیگر با این اطلاعات می توانند خودشان پکیج شما را دوباره بسازند).

semantic versioning چیست؟

npm توصیه می کند که در هنگام به روز رسانی پکیج هایتان حتما یک فایل جدید package.json را ایجاد کرده و نسخه پکیج خود را به روز رسانی کنید. بر اساس توضیحات npm اگر بخواهیم semantic versioning را به صورت خلاصه توضیح بدهیم باید به نکات زیر توجه کنیم:

یک) semantic versioning دارای سه قسمت اصلی X.Y.Z است.

دو) اولین نسخه پکیج که منتشر می شود همیشه با عدد ۱ خواهد بود. به عبارتی اولین باری که پکیج خود را روی npm منتشر می کنید، نسخه آن 1.0.0 است.

سه) در مورد به روز رسانی ها باید یکی از قوانین زیر را در نظر بگیرید:

    • تصحیح باگ ها و اشکالات برنامه در صورتی که backward compatible باشد (یعنی با نسخه های قبلی سازگار باشد) باید قسمت Z را افزایش دهد. به طور مثال 1.0.1 یعنی اولین بار پس از انتشار نسخه 1.0.0 می باشد که یک باگ در پکیج تصحیح می شود و این به روز رسانی با برنامه هایی که بر اساس نسخه های قبلی نوشته شده باشند سازگار خواهد بود.
    • قابلیت های جدید برنامه در صورتی که backward compatible باشد (یعنی با نسخه های قبلی سازگار باشد) باید قسمت Y را افزایش دهد. به طور مثال 1.1.0 یعنی هنوز در نسخه اصلی 1.0.0 قرار داریم اما قابلیت جدیدی به پکیج اضافه شده است. در چنین حالتی حتما بای Z را روی صفر قرار بدهید چرا که با معرفی قابلیت جدید، قسمت Z ریست شده و تصحیح باگ ها از اول شروع می شود.
    • به روز رسانی های جدیدی که با نسخه های قبلی سازگار نیستند باعث افزایش مقدار X می شوند. نوع این دسته از بروز رسانی ها اهمیتی ندارد (چه از تصحیح باگ باشند و چه ارائه قابلیتی جدید)، بلکه هر گونه تغییری که باعث ناسازگاری با نسخه های قبلی بشود باید X را افزایش دهد (مثال: 2.0.0). با افزایش X باید Y و Z نیز دوباره روی صفر ریست شوند.

فیلدهای package.json

برای ساخت فایل package.json باید از دستور npm init در ترمینال خودمان استفاده کنیم. این دستور باعث ساخت یک قالب ساده در package.json می شود و نیازی به نوشتن آن از صفر نیست. این فایل پس از تولید معمولا شکل زیر را دارد:

> npm init --yes

Wrote to /home/monatheoctocat/my_package/package.json:

{

"name": "my_package",

"description": "",

"version": "1.0.0",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"repository": {

"type": "git",

"url": "https://github.com/monatheoctocat/my_package.git"

},

"keywords": [],

"author": "",

"license": "ISC",

"bugs": {

"url": "https://github.com/monatheoctocat/my_package/issues"

},

"homepage": "https://github.com/monatheoctocat/my_package"

}

اولین فیلد مورد نظر ما در package.json فیلد name است که به نام پروژه اشاره دارد. این فیلد یک فیلد اجباری است و اگر می خواهید پکیج شما در registry ثبت شود باید این فیلد را مشخص کنید. نام پکیج شما حتما باید با حروف کوچک نوشته شده و می تواند خط فاصله یا آندراسکور (علامت _) نیز داشته باشد. دومین فیلد مهم و البته اجباری در package.json فیلد version است و باید از قوانین semantic versioning پیروی کند. این دو فیلد صد در صد اجباری هستند در غیر این صورت پکیج شما در registry ثبت نمی شود. مثال:

{

"name": "my-awesome-package",

"version": "1.0.0"

}

فیلد توصیه شده و بعدی ما author بوده که مربوط به اطلاعات نویسنده پکیج است و معمولا ساختار زیر را دارد:

Your Name <email@example.com> (http://example.com)

توجه کنید که این فیلد اختیاری است. راهنمای انتشار پکیج در npm در قسمتی از توضیحات خود پیشنهاد می دهد که از بخش description در فایل package.json استفاده کنید تا دیگران بتوانند راحت تر و با یک جست و جوی ساده آن را پیدا کنند.

در صورتی که نمی خواهید اطلاعات شخصی خود را به صورت دستی در تک تک فایل های package.json وارد کنید می توانید آن ها را به صورت پیشفرض درون npm ذخیره کنید تا در فعات بعدی به صورت خودکار برایتان تولید شوند:

> npm set init.author.email "example-user@example.com"

> npm set init.author.name "example_user"

> npm set init.license "MIT"

قدم دوم: ساخت ماژول و انتشار پکیج

آیا با node modules یا ماژول های node آشنا هستید؟ اگر بخواهیم انتشار پکیج در npm را انجام دهیم، نمی توانیم تمام سورس کد را مستقیما به آن ارسال کنیم بلکه باید آن را در قالب یک ماژول پیاده سازی کنیم.

همانطور که توضیح دادم اولین مرحله تعریف یک فایل package.json است که با دستور npm init انجام می شود. البته در صورتی که ماژول شما scoped باشد باید از دستور زیر استفاده کنید:

npm init --scope=@scope-name

به جای scope-name باید نام scope خود را قرار بدهید. در صورتی که با scope ها آشنا نیستید من به صورت خلاصه آن را برایتان توضیح می دهم. زمانی که شما در سایت npm ثبت نام می کنید، scope یا دامنه خاصی به شما تعلق می گیرد که بر اساس username شما است. شما می توانید از این scope به عنوان یک namespace برای برقراری ارتباط بین پکیج هایتان استفاده کنید. به مثال زیر توجه کنید:

@npm/package-name

در این کد npm (چیزی که بین @ و / قرار دارد) همان scope ما است.

@npmcorp/package-name

در این کد npmcorp همان scope شما است. پکیج هایی که دارای scope باشند scoped و پکیج هایی که بدون scope باشند unscoped نامیده می شوند. من فعلا به طور کلی در مورد انتشار پکیج در npm صحبت می کنیم و سپس به صورت جداگانه و جزئی تر در رابطه با انتشار پکیج های scoped و unscoped صحبت خواهیم کرد. فعلا در نظر داشته باشید که برای تولید فایل package.json برای پکیج های unscoped از دستور npm init و برای پکیج های scoped از دستور زیر استفاده می شود:

npm init --scope=@scope-name

در مرحله بعدی حتما فیلدهای name و version را پر کنید. با این کار قسمت اول عملیات تمام شده است و به قسمت دوم می رسیم. در این قسمت بحث کدنویسی پیش می آید؛ پکیج شما باید دارای فایل هایی باشد که مقدار خاصی را export می کنند. در نظر داشته باشید که افراد دیگر می خواهند از پکیج شما استفاده کنند بنابراین شما باید به نحوی کدهای پکیج خود را export کنید تا دیگران بتوانند آن را import کنند. برای انجام این کار روش های مختلفی وجود دارد و از آنجایی که بحث بسیار مفصلی است، نمی توانیم آن را در این مقاله بگنجانیم. اگر بخواهم به زبان ساده بگویم شما باید کدهایتان را با ساختاری بنویسید که قابل export باشند. برخی از پروژ ها از یک فایل مرکزی index استفاده کرده و تمام بخش های مختلف یک پکیج را در آن export کرده و سپس از آن فایل اصلی به پروژه های دیگری export می کنند. یک مثال ساده:

exports.printMsg = function() {

console.log("This is a message from the demo package");

}

ما در این مثال فقط تابع printMsg خود را export کرده ایم.

مرحله سومِ انتشار پکیج در npm، ارسال پکیج خود به npm است اما قبل از آن مطمئن شوید که به وب سایت npm رفته و یک حساب کاربری ایجاد کنید. پس از ایجاد حساب کاربری باید از طریق ترمینال خود وارد حسابتان شوید. این کار با دستور npm login انجام می شود. زمانی که این دستور را اجرا کنید از شما خواسته می شود تا نام کاربری و رمز عبور خود را وارد نمایید. زمانی که این کار را کردید آماده ارسال پکیج خواهیم بود:

  • در صورتی که پکیج شما scoped است از دستور npm publish --access public استفاده نمایید. دلیل پاس دادن access-- این است که پکیج های scoped به صورت خودکار private (خصوصی) هستند بنابراین برای اینکه آن ها را عمومی کنیم و بقیه به آن دسترسی داشته باشند باید access-- را نیز پاس داده و آن را روی public (عمومی) تنظیم کنیم.
  • برای پکیج های unscoped نیز از دستور npm publish استفاده می کنیم.

نکته: پکیج های unscoped به صورت پیش فرض private هستند بنابراین نمی توانیم آن ها را در registry عمومی npm منتشر کنیم. به همین دلیل باید flag ای به نام access را روی public تنظیم کنیم. توجه داشته باشید که شما اجازه انتشار پکیج های scoped را روی registry عمومی npm ندارید بلکه دسترسی به صورت مستقیم توسط صاحب پکیج انجام می شود.

طبیعتا name در package.json به عنوان نام پکیج شما در npm انتخاب می شود بنابراین باید از قوانین npm تبعیت کند (به طور مثال غیرتکراری و یکتا باشد، الفاظ توهین آمیز نداشته باشد و الی آخر). در صورتی که تمام این موارد را رعایت کرده باشید پیام موفقیت آمیز بودن آپلود پروژه را دریافت می کنید.

حالا تنها کاری که مانده مرحله چهارمِ انتشار پکیج در npm یعنی تست پکیج است:

npm install <your-module-name>

من با این دستور پکیج خودم را نصب می کنیم‌ (طبیعتا به جای <your-module-name> باید نام پکیج خود را قرار بدهید) و سپس آن را در پروژه ای استفاده می کنم تا مطمئن شویم همه چیز بدون مشکل اجرا می شود.

اطلاعات تکمیلی: فایل README

npm و دیگر برنامه نویسان پیشنهاد می دهند جهت راحتی در جست و جو پکیج شما و همچنین راحتی در استفاده از آن، بهتر است یک فایل README را در مسیر اصلی پکیج (root address) خود قرار دهید که نحوه استفاده از آن را توضیح می دهد. این فایل README ابتدا باید اطلاعاتی کلی راجع به پکیج شما را ارائه دهد (به طور مثال پکیج شما چیست و در چه زمینه ای کاربرد دارد)، سپس نحوه نصب، استفاده و پیکربندی آن را برای دیگران توضیح بدهید. در ضمن در نظر داشته باشید که دقیقا مانند گیت هاب، هر چه درون فایل README بنویسید در صفحه اصلی پکیج در npm نمایش داده خواهد شد به همین جهت حتما باید آن را در مسیر اصلی پکیج (root address) قرار بدهید نه در پوشه های دیگر.

فایل README از markdown پشتیبانی می کند بنابراین پسوند آن md خواهد بود (README.md). شما باید این فایل را به صورت ساده در سیستم خود ساخته و اطلاعات مورد نظر را در آن بنویسید. در صورتی که با markdown آشنایی ندارید، من در این مقاله به صورت خلاصه آن را توضیح خواهم داد.

قوانین markdown به صورت خلاصه

من در این قسمت انواع و اقسام دستورات markdown را برایتان توضیح می دهم. شما می توانید برای تست این دستورات به وب سایت stackedit.io مراجعه نمایید و کدهای این مقاله را در آن قرار بدهید.  stackedit یک ویرایشگر آنلاین markdown است و به شما اجازه می دهد که نتیجه markdown را مشاهده کنید.

استایل دهی متون

برای توپُر کردن متن (bold) از علامت ** و برای مورب کردن آن از * استفاده می کنیم. همچنین برای لینک دار کردن یک متن باید از ساختار (link)[text] استفاده کنید. به مثال های زیر توجه کنید:

A **bold word** --> A

bold word

An *italic word* --> An

italic word

This is a [link to Google!](https://google.com) --> This is a

link to Google!


لیست ها

برای ساخت لیست ها در markdown باید نوع لیست را در نظر بگیریم. اگر لیست شما ترتیبی است  باید از اعداد استفاده کنید:

  1. One
  2. Two
  3. Three

با این کار دقیقا لیستی به همین شکل را دریافت می کنید. در صورتی که می خواهید لیست شما غیرترتیبی باشد از علامت * استفاده نمایید:

* Markdown with Roxo

* Dev Tutorials

با انجام این کار لیستی به شکل زیر دریافت می کنید:

  • Markdown with Roxo
  • Dev Tutorial

البته به جای * می توانید از - (علامت فاصله) نیز استفاده کنید و فرورفتگی هر کدام از این علامت ها وابستگی آن به عضو دیگر لیست را نمایش می دهد. به طور مثال:

- some list

- some list

- sub list 1

- sub list 2

دقت کنید که دو مورد آخر قبل از علامت - دو عدد اسپیس دارند. این کار باعث تولید لیستی به شکل زیر می شود:

  • some list
  • some list
    • ◦ sub list 1
    • ◦ sub list 2

تصاویر

برای استفاده از تصاویر در markdown باید از ساختار (imageURL)[description]! استفاده کنید. مثال:

![Image of Yaktocat](https://octodex.github.com/images/yaktocat.png)

با نوشتن این خط در فایل markdown خود می توانید یک تصویر را نشان بدهید.

تیتر ها و نقل قول

برای تعریف heading یا تیتر ها در markdown باید از علامت # استفاده کنید به طوری که # در آن برابر h1 و ## برابر h2 و ### برابر h3 و #### برابر h4 و ##### برابر h5 و ###### برابر h6 می باشد. مثال:

### This is a third-tier heading

همچنین برای نقل قول (quote) کردن سخنان افراد دیگر باید از علامت < در ابتدای آن خط استفاده کنید:

> Coffee. The finest organic suspension ever devised... I beat the Borg with it.

> - Captain Janeway

نوشتن کد

برای نوشتن کد در markdown چند روش مختلف وجود دارد. در صورتی که کد شما بسیار کوتاه بوده و قرار است درون یک خط با نوشته های عادی باشد از علامت back tic استفاده کنید که به شکل ` می باشد. به طور مثال `var example = true` در markdown به شکل  var example = true نمایش داده می شود. در صورتی که کد شما چند خطی است باید آن را با چهار اسپیس از ابتدای خط جدا کنید. مثال:

if (isAwesome){

return true

}

البته اگر از این روش خوشتان نمی آید می توانید از روش code fencing استفاده کنید که با سه علامت back tic پشت سر هم انجام می شود. در این روش نیازی به ایجاد فرورفتگی با اسپیس نیست، بلکه باید ابتدا و انتهای کد را با سه علامت back tic مشخص کنید.

```

if (isAwesome){

return true

}

```

همچنین در صورتی که می خواهید syntax highlighting (رنگ گذاری کدها) برایتان فعال شود باید نام زبان برنامه نویسی را در کنار back tic های اول ذکر کنید. مثال:

```javascript

if (isAwesome){

return true

}

```

موارد اختصاصی markdown در گیت هاب

مواردی که بالاتر برایتان توضیح دادم، استاندارد های جهانی markdown هستند اما گیت هاب چند مورد اضافی را ابداع کرده و به صفحات خود اضافه نموده است. ما در این قسمت به بررسی این موارد می پردازیم اما یادتان باشد که تمامی آن ها مخصوص گیت هاب هستند و به احتمال زیاد در وب سایت های دیگر جواب نمی دهند. اولین مورد task list ها هستند که به شما اجازه ایجاد یک todo list ساده را می دهند. شما می توانید با نوشتن علامت x در آن ها، تیکشان را فعال کنید تا به دیگر کاربران بفهمانید که کار انجام شده است:

- [x] @mentions, #refs, [links](), **formatting**, and <del>tags</del> supported

- [x] list syntax required (any unordered or ordered list supported)

- [x] this is a complete item

- [ ] this is an incomplete item

همانطور که در ابتدای این مقاله توضیح دادم برای مشاهده نتیجه این کد می توانید آن را درون وب سایت stackedit.io قرار بدهید.

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

First Header | Second Header

------------ | -------------

Content from cell 1 | Content from cell 2

Content in the first column | Content in the second column

خط اول که عبارات first header و second header را دارد، همان header (عناوین ستون ها) جدول است و علامت | (به آن علامت pipe می گوییم) این دو ستون را از هم جدا می کند.  سپس باید از خط فاصله ها و علامت | استفاده کنید تا شروع جدول را مشخص کنید در غیر این صورت جدول شما ساخته نمی شود (علامت | به تنهایی کافی نیست). از این قسمت به بعد تا هر جایی که علامت | را داشته باشید جدول محسوب خواهد شد. البته تعداد زیاد علامت های خط فاصله برای تعریف شروع جدول اجباری نیست بلکه برای راحت تر دیده شدن آن است. شما می توانید به شکل زیر جدول های خود را تعریف کنید:

First Header | Second Header

- | -

Content from cell 1 | Content from cell 2

Content in the first column | Content in the second column

مورد بعدی هش های SHA-1 هستند (SHA-1 hash). هر زمان که شما یک هش SHA-1 را در گیت هاب بنویسید، این هش به صورت خودکار تبدیل به لینکی برای یکی از commit ها می شود. چند مثال ساده:

16c999e8c71134401a78d4d46435517b2271d6ac

mojombo@16c999e8c71134401a78d4d46435517b2271d6ac

mojombo/github-flavored-markdown@16c999e8c71134401a78d4d46435517b2271d6ac

این قابلیت مخصوص گیت هاب بوده و در stackedit کار نمی کند.

قابلیت بعدی ما mention کردن یا صدا زدن کاربران با username آن ها است. برای این کار از علامت @ استفاده کنید (مثال username@). قابلیت دیگر ما قابلیت Strikethrough است که یعنی روی خطوط خط می کشد (این یک مثال از Strikethrough است تصویر). برای انجام این کار باید از دو علامت tilde استفاده کنید (مثال ~~some text here~~). در نهایت قابلیت emoji ها را نیز داریم که  لیست کامل آن ها در این لینک موجود است.

ویرایش package.json

در صورتی که فایل package.json خود را ویرایش کردید، باید دستورات زیر را اجرا کنید تا همه چیز در سمت npm نیز به روز رسانی شود:

npm version patch

npm publish

ساخت یک پکیج unscoped و scoped

همانطور که گفته شد شما به صورت پیش فرض اجازه انتشار پکیج های scoped را در registry عمومی npm ندارید بنابراین برای انتشار عمومی یک پکیج باید به دنبال پکیج unscoped باشیم. شما به عنوان یک کاربر npm می توانید کدهای مورد استفاده خود را به صورت یک پکیج در آورده و در npm قرار دهید تا کاربران دیگر نیز از آن استفاده کنند. پکیج هایی که unscoped هستند همیشه public (عمومی) بوده و تنها با نامشان هدف قرار می گیرند. به طور مثال:

npm install axios

حالا که با نکات اولیه آشنا شدیم باید به این سوال پاسخ دهیم که چطور می توان یک پکیج unscoped را در npm قرار داد. در ابتدا یک پوشه دلخواه ایجاد کرده و به آن می رویم:

mkdir my-test-package

cd my-test-package

در مرحله بعدی باید این پوشه را تحت مدیریت npm در بیاوریم. طبیعتا برای این کار از دستور npm init استفاده می کنیم. با این کار یک فایل package.json برایتان ساخته می شود. در مرحله بعدی فایل README را ساخته و توضیحات پکیج به همراه روش استفاده را در آن قرار می دهید. در عین حال باید URL خاصی را برای پکیج خود داشته باشیم (مثلا لینک repo در گیت هاب) بنابراین این لینک را نیز به گیت اضافه می کنیم:

git init

git remote add origin git://git-remote-url

طبیعتا باید به جای git://git-remote-url از URL پکیج خودتان استفاده کنید. با انجام این کار پروژه ما توسط git ردیابی می شود تا در صورت خطا بتوانیم به نسخه های قبلی برگردیم. قدم بعدی یکی از مهم ترین قسمت های ممکن است که معمولا توسط افراد نادیده گرفته می شود: حذف اطلاعات حساس! بسیاری از افراد فراموش می کنند که اطلاعات حساسی مانند کلیدهای شخصی، رمز های عبور، اطلاعات حقوقی، اطلاعات کارت های بانکی و اعتباری و غیره را قبل از ثبت در npm حذف کنند. چنین اطلاعات حساسی می توانند به باعث ضربه زدن به کاربران شما، زیر ساخت شما، مدت توسعه و حتی دعاوی حقوقی شود بنابراین npm پیشنهاد می کند حتما این اطلاعات حساس را حذف کنید.

برای ساخت پکیج های scoped نیز همین روش را پیش می گیرید اما برای ساخت فایل package.json از دستور npm init --scope=@my-username و برای انتشار آن از دستور npm publish --access public استفاده می کنیم.

در نظر داشته باشید که پس از انتشار پکیج خود در npm بهتر است دستور npm audit را اجرا کنید تا در صورت وجود مشکل امنیتی در کدهایتان از آن با خبر شوید.


منبع: وب سایت npmjs

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.