{"id":13394333,"url":"https://github.com/elsewhencode/project-guidelines","last_synced_at":"2025-05-14T23:01:46.251Z","repository":{"id":37411530,"uuid":"95876775","full_name":"elsewhencode/project-guidelines","owner":"elsewhencode","description":"A set of best practices for JavaScript projects","archived":false,"fork":false,"pushed_at":"2024-12-09T07:59:04.000Z","size":507,"stargazers_count":29564,"open_issues_count":15,"forks_count":3213,"subscribers_count":619,"default_branch":"master","last_synced_at":"2025-05-07T22:02:01.111Z","etag":null,"topics":["best-practices","guidelines","how-to","javascript","javascript-best-practices","maintainability"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elsewhencode.png","metadata":{"files":{"readme":"README-ir.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-06-30T10:17:55.000Z","updated_at":"2025-05-07T12:25:07.000Z","dependencies_parsed_at":"2024-05-10T20:46:22.205Z","dependency_job_id":"9e8cb9e7-18b8-486d-a839-7788f23380d9","html_url":"https://github.com/elsewhencode/project-guidelines","commit_stats":{"total_commits":143,"total_committers":79,"mean_commits":"1.8101265822784811","dds":0.6923076923076923,"last_synced_commit":"3d5e2b378413878ec69d190cf1041235d8833cd6"},"previous_names":["wearehive/project-guidelines"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elsewhencode%2Fproject-guidelines","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elsewhencode%2Fproject-guidelines/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elsewhencode%2Fproject-guidelines/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elsewhencode%2Fproject-guidelines/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elsewhencode","download_url":"https://codeload.github.com/elsewhencode/project-guidelines/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254243353,"owners_count":22038044,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["best-practices","guidelines","how-to","javascript","javascript-best-practices","maintainability"],"created_at":"2024-07-30T17:01:16.300Z","updated_at":"2025-05-14T23:01:46.126Z","avatar_url":"https://github.com/elsewhencode.png","language":"JavaScript","readme":"[中文版](./README-zh.md)\n| [日本語版](./README-ja.md)\n| [한국어](./README-ko.md)\n| [Русский](./README-ru.md)\n| [Português](./README-pt-BR.md)\n| [Italiana](./README-it.md)\n| [English](./README.md)\n| [Persian/فارسی](./README-ir.md)\n\n\u003cp align=\"right\"\u003e\n  \u003ca href=\"https://www.elsewhen.com/\"\u003e\n    \u003cimg src=\"./images/elsewhen-logo.png\" width=\"180\" height=\"180\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# دستورالعمل‌های پروژه \u0026middot; [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)\n\n\u003e وقتی که شروع و توسعه یک پروژه جدید برای شما شبیه به حرکت در یک میدان سبز و خالی (که هیچ ساختاری ندارد) است (استعاره از شروع کردن یک پروژه یا کار جدید از ابتدا و بدون هیچ محدودیت و ساختاری است)، نگهداری از آن می‌تواند کابوسی پیچیده و تاریک برای شخص دیگری باشد.\n\u003e در اینجا لیستی از دستورالعمل‌ها آمده است که ما آن‌ها را پیدا کرده‌ایم، نوشته‌ایم و گردآوری کرده‌ایم و فکر می‌کنیم که برای اکثر پروژه‌های جاوااسکریپت در [elsewhen](https://www.elsewhen.com) به خوبی عمل می‌کند.\n\u003e اگر می‌خواهید یک روش بهینه را به اشتراک بگذارید، یا فکر می‌کنید یکی از این دستورالعمل‌ها باید حذف شود، [با خیال راحت آن را با ما به اشتراک بگذارید](http://makeapullrequest.com).\n\n\u003chr\u003e\n\n- [گیت/Git](#git)\n  - [برخی از قوانین Git](#some-git-rules)\n  - [گردش‌کار گیت/Git workflow](#git-workflow)\n  - [نگارش بهتر متن کامیت‌ها](#writing-good-commit-messages)\n- [مستندات](#documentation)\n- [متغیرهای محیطی/Environments](#environments)\n  - [ایجاد محیط‌های توسعه‌ی یکپارچه/Consistent dev environments](#consistent-dev-environments)\n  - [وابستگی‌های یکسان و هماهنگ/Consistent dependencies](#consistent-dependencies)\n- [وابستگی‌ها/Dependencies](#dependencies)\n- [تست کردن/Testing](#testing)\n- [ساختار و نام‌گذاری/Structure and Naming](#structure-and-naming)\n- [سبک کدنویسی/Code style](#code-style)\n  - [برخی از دستورالعمل‌های code style](#code-style-check)\n  - [اعمال استانداردهای سبک کدنویسی](#enforcing-code-style-standards)\n- [ثبت وقایع/Logging](#logging)\n- [ای‌پی‌آی/API](#api)\n  - [طراحی API](#api-design)\n  - [امنیت ای‌پی‌آی/API security](#api-security)\n  - [مستندسازی ای‌پی‌آی/API documentation](#api-documentation)\n- [دسترس‌پذیری/Accessibility](#a11y)\n- [مجوزدهی/Licensing](#licensing)\n\n\u003ca name=\"git\"\u003e\u003c/a\u003e\n\n## 1. گیت/Git\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/branching.png\" width=\"135\" height=\"135\"\u003e\n\u003c/p\u003e\n\n\u003ca name=\"some-git-rules\"\u003e\u003c/a\u003e\n\n### 1.1 برخی از قوانین Git\n\nمجموعه‌ای از قوانین وجود دارد که باید آن‌ها را به خاطر داشته باشید:\n\n- کار را در برنچ feature انجام دهید\n\n_چرا:_\n\n\u003e این روش باعث می‌شود که تمام کارها به صورت مجزا در یک برنچ اختصاصی انجام شوند، نه در برنچ اصلی. این کار به شما امکان را می‌دهد تا چندین درخواست Pull Request بدون سردرگمی ارسال کنید. همچنین می‌توانید به طور مکرر کد را به‌روزرسانی کنید، بدون اینکه برنچ اصلی را با کد ناپایدار و ناتمام آلوده کنید. [توضیحات بیشتر ...](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow)\n\n- از برنچ `develop` انشعاب بگیرید\n\n_چرا:_\n\n\u003e به این ترتیب، می‌توانید مطمئن شوید که کد برنچ master تقریباً همیشه بدون مشکل build می‌شود و معمولاً می‌توان آن را مستقیماً برای releases استفاده کرد (این کار ممکن است برای برخی پروژه‌ها بیش از حد لازم باشد).\n\n- هرگز مستقیماً به برنچ `develop` یا `master` پوش نکنید. بلکه یک درخواست Pull Request ایجاد کنید.\n\n_چرا:_\n\n\u003e این کار به اعضای تیم اطلاع می‌دهد که یک feature تکمیل شده است. همچنین امکان بررسی آسان کد توسط سایرین را فراهم می‌کند و فضایی برای بحث درباره feature پیشنهادی ایجاد می‌کند.\n\n- برنچ `develop` محلی/local خود را قبل از پوش کردن یک feature، ابتدا بروزرسانی و مورد بازبینی تعاملی (interactive rebase) قرار دهید، سپس درخواست Pull Request ایجاد کنید.\n\n_چرا:_\n\n\u003e ری‌بیس (Rebase) برنچ درخواست‌شده (`master` یا `develop`) را merge می‌کند و کامیت‌هایی که به‌صورت locally انجام داده‌اید را به بالای تاریخچه اعمال می‌کند، بدون اینکه کامیت merge ایجاد کند (در صورتی که تعارضی وجود نداشته باشد). نتیجه آن یک تاریخچه تمیز و مرتب خواهد بود. [توضیحات بیشتر ...](https://www.atlassian.com/git/tutorials/merging-vs-rebasing)\n\n- تعارضات احتمالی را در حین rebase و قبل از ایجاد درخواست Pull Request برطرف کنید.\n- برنچ‌های feature ایجاد شده در local و remote را پس از ادغام حذف کنید.\n\n_چرا:_\n\n\u003e لیست برنچ‌های شما را با برنچ‌های بی‌استفاده درهم می‌آمیزد (شلوغ می‌کند). حذف برنچ‌های feature باعث می‌شود که هر برنچ تنها یک‌بار به برنچ اصلی (`master` یا `develop`) ادغام شود. برنچ‌های feature باید فقط تا زمانی که کار هنوز در حال انجام است وجود داشته باشند.\n\n- قبل از ایجاد درخواست Pull Request، مطمئن شوید که برنچ feature شما با موفقیت build می‌شود و همه testها (شامل بررسی‌های سبک/استایل کد) با موفقیت انجام می‌شود.\n\n_چرا:_\n\n\u003e شما قصد دارید که کد خود را به یک برنچ stable اضافه کنید. اگر testهای برنچ feature شما ناموفق باشند، احتمال زیادی وجود دارد که build برنچ مقصد نیز شکست بخورد. علاوه بر این، قبل از ایجاد درخواست Pull Request، نیاز است که بررسی سبک و استایل کد را انجام شود. این کار باعث بهبود خوانایی کد می‌شود و احتمال ترکیب شدن تغییرات قالب‌بندی با تغییرات واقعی را کاهش می‌دهد.\n\n- [از فایل](./.gitignore) `.gitignore` استفاده کنید.\n\n_چرا:_\n\n\u003e این فایل از قبل دارای لیستی از فایل‌های سیستمی است که نباید همراه با کد شما به مخزن remote ارسال شوند. علاوه بر این، پوشه‌ها و فایل‌های تنظیمات برای بیشتر ویرایشگرهای مورد استفاده و همچنین پوشه‌های dependency رایج را نیز مستثنی می‌کند.\n\n- از برنچ‌های `develop` و `master` محافظت کنید.\n\n_چرا:_\n\n\u003e این کار از برنچ‌های آماده برای production در برابر دریافت تغییرات غیرمنتظره و غیرقابل بازگشت محافظت می‌کند. توضیحات بیشتر ... [GitHub](https://help.github.com/articles/about-protected-branches/), [Bitbucket](https://confluence.atlassian.com/bitbucketserver/using-branch-permissions-776639807.html) and [GitLab](https://docs.gitlab.com/ee/user/project/protected_branches.html)\n\n\u003ca name=\"git-workflow\"\u003e\u003c/a\u003e\n\n### 1.2 گردش‌کار گیت/Git workflow\n\nبه خاطر دلایل ذکرشده در بالا، ما از [Feature-branch-workflow](https://www.atlassian.com/git/tutorials/comparing-workflows#feature-branch-workflow) همراه با [Interactive Rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing#the-golden-rule-of-rebasing) و برخی عناصر [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows#gitflow-workflow) (نام‌گذاری و داشتن یک develop branch). استفاده می‌کنیم. مراحل اصلی به شرح زیر هستند:\n\n- برای یک پروژه جدید، یک مخزن گیت (Git repository) را در پوشه پروژه مقداردهی اولیه کنید. **برای ویژگی‌ها/تغییرات بعدی، این مرحله باید نادیده گرفته شود.**\n\n```sh\ncd \u003cproject directory\u003e\ngit init\n```\n\n- یک شاخه جدید برای توسعه یک feature یا رفع یک bug ایجاد کنید و به آن منتقل شوید.\n\n```sh\ngit checkout -b \u003cbranchname\u003e\n```\n\n- تغییری در آن ایجاد کنید.\n\n```sh\ngit add \u003cfile1\u003e \u003cfile2\u003e ...\ngit commit\n```\n\n_چرا:_\n\n\u003e کامند `git add \u003cfile1\u003e \u003cfile2\u003e ... ` - شما باید فقط فایل‌هایی را اضافه کنید که یک تغییر کوچک و منسجم را تشکیل می‌دهند.\n\n\u003e کامند `git commit` یک ویرایشگر باز می‌کند که به شما اجازه می‌دهد مقادیر subject را از body در کامیت خود از هم جدا کنید.\n\n\u003e در _بخش 1.3_ بیشتر درباره آن بخوانید.\n\n_نکته:_\n\n\u003e می‌توانید به جای آن از دستور `git add -p` استفاده کنید که به شما این امکان را می‌دهد تمام تغییرات اعمال‌شده را یک به یک بررسی کنید و تصمیم بگیرید که آیا آنها را در کامیت وارد کنید یا نه.\n\n- با مخزن remote همگام‌سازی کنید تا تغییراتی که از دست داده‌اید را دریافت کنید.\n\n```sh\ngit checkout develop\ngit pull\n```\n\n_چرا:_\n\n\u003e این کار به شما فرصت می‌دهد که با conflictها در سیستم خود در حین rebasing برخورد کنید، به جای اینکه یک درخواست Pull Request ایجاد کنید که حاوی conflictها باشد.\n\n- برنچ feature خود را با استفاده از interactive rebase با آخرین تغییرات از برنچ develop به‌روزرسانی کنید.\n\n```sh\ngit checkout \u003cbranchname\u003e\ngit rebase -i --autosquash develop\n```\n\n_چرا:_\n\n\u003e می‌توانید از `--autosquash` استفاده کنید تا تمام کامیت‌های خود را به یک کامیت ترکیب کنید. هیچ‌کس نمی‌خواهد برای یک ویژگی در شاخه develop چندین کامیت داشته باشد. [توضیحات بیشتر ...](https://robots.thoughtbot.com/autosquashing-git-commits)\n\n- اگر conflicts ندارید، این مرحله را رد کنید. در غیراینصورت، [آنها را حل کنید](https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/) و rebase را ادامه دهید.\n\n```sh\ngit add \u003cfile1\u003e \u003cfile2\u003e ...\ngit rebase --continue\n```\n\n- برنچ خود را push کنید. rebase تاریخچه را تغییر می‌دهد، بنابراین باید از `-f` برای اجبار تغییرات به برنچ remote استفاده کنید. اگر شخص دیگری روی برنچ شما کار می‌کند، از گزینه کمتر مخرب `--force-with-lease` استفاده کنید.\n\n```sh\ngit push -f\n```\n\n_چرا:_\n\n\u003e وقتی که rebase انجام می‌دهید، تاریخچه برنچ feature خود را تغییر می‌دهید. در نتیجه، گیت `git push` معمولی را رد می‌کند. به جای آن باید از فلگ `-f` یا `--force` استفاده کنید. [توضیحات بیشتر ...](https://developer.atlassian.com/blog/2015/04/force-with-lease/)\n\n- یک درخواست Pull Request ایجاد کنید.\n- درخواست Pull Request توسط یک بررسی کننده پذیرفته، ادغام و بسته خواهد شد.\n- در صورت اتمام کار، برنچ feature محلی/local خود را حذف کنید.\n\n```sh\ngit branch -d \u003cbranchname\u003e\n```\n\nتمام برنچ‌های local را که در مخزن remote وجود ندارند را حذف کنید. (این کار باعث می‌شود که برنچ‌های که دیگر وجود ندارند، از مخزن local حذف شوند، در نتیجه محیط توسعه شما تمیز و مرتب‌ باقی می‌ماند.)\n\n```sh\ngit fetch -p \u0026\u0026 for branch in `git branch -vv --no-color | grep ': gone]' | awk '{print $1}'`; do git branch -D $branch; done\n```\n\n\u003ca name=\"writing-good-commit-messages\"\u003e\u003c/a\u003e\n\n### 1.3 نگارش بهتر متن کامیت‌ها\n\nداشتن یک راهنمای مناسب برای ایجاد کامیت‌ها و پایبندی به آن، کار با گیت و همکاری با دیگران را بسیار آسان‌تر می‌کند. در اینجا چند قانون کلی وجود دارد:([منبع](https://chris.beams.io/posts/git-commit/#seven-rules)):\n\n- موضوع (subject) را از بدنه (body) جدا کنید و بین این دو یک خط خالی قرار دهید.\n\n_چرا:_\n\n\u003e گیت به اندازه کافی هوشمند است که خط اول پیام کامیت شما را به‌عنوان خلاصه تشخیص دهد. در واقع، اگر به‌جای استفاده از git log از git shortlog استفاده کنید، یک لیست طولانی از پیام‌های کامیت خواهید دید که شامل شناسه کامیت و تنها خلاصه پیام است.\n\n- طول خط موضوع (subject) را به ۵۰ کاراکتر محدود کنید و بدنه پیام را در ۷۲ کاراکتر بشکنید.\n\n_چرا:_\n\n\u003e کامیت‌ها تا حد ممکن باید جزئی و متمرکز باشند؛ نیازی به طولانی‌نویسی در آن‌ها نیست. [توضیحات بیشتر ...](https://medium.com/@preslavrachev/what-s-with-the-50-72-rule-8a906f61f09c)\n\n- حرف اول موضوع (subject) را با عبارت بزرگ (Capitalize) شروع کنید.\n- موضوع (subject) را با نقطه تمام نکنید.\n- از [وجه امری](https://en.wikipedia.org/wiki/Imperative_mood) در موضوع (subject) استفاده کنید.\n\n_چرا:_\n\n\u003e به جای نوشتن پیام‌هایی که فقط بیانگر/توصیف‌کننده کاری است که کامیت‌کننده انجام داده، بهتر است این پیام‌ها را به عنوان دستورالعمل‌هایی در نظر بگیرید که بیان می‌کنند پس از اعمال کامیت در مخزن، چه چیزی قرار است انجام شود. (توضیح مترجم: پیام‌های کامیت باید بر نتیجه و هدف تمرکز کنند، نه صرفاً بر عملیات انجام‌شده.) [توضیحات بیشتر ...](https://news.ycombinator.com/item?id=2079612)\n\n- از قسمت بدنه (body) برای توضیح **چه کاری** و **چرا** انجام شده، استفاده کنید، نه **چگونگی** انجام آن.\n\n\u003ca name=\"documentation\"\u003e\u003c/a\u003e\n\n## 2. مستندات\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/documentation.png\" alt=\"Documentation\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- از این [قالب](./README.sample.md) برای فایل `README.md` استفاده کنید؛ اگر بخش‌هایی وجود دارد که پوشش داده نشده‌اند، با خیال راحت آن‌ها را اضافه کنید.\n- برای پروژه‌هایی که بیش از یک مخزن (repository) دارند، لینک به مخازن دیگر را در فایل‌های `README.md` مربوطه قرار دهید..\n- با پیشرفت پروژه، فایل `README.md` را به‌روز نگه دارید.\n- کد خود را کامنت‌گذاری کنید. سعی کنید با هر بخش اصلی کد، به‌وضوح توضیح دهید که قصد دارید چه کاری انجام دهید.\n- اگر درباره کد یا روش مورد استفاده شما در گیت‌هاب یا استک‌اورفلو بحثی باز وجود دارد، لینک آن را در کامنت خود بگنجانید.\n- از کامنت‌ها به‌عنوان توجیهی برای کد ضعیف استفاده نکنید. کد خود را تمیز نگه دارید.\n- از کد تمیز به‌عنوان بهانه‌ای برای عدم کامنت‌گذاری استفاده نکنید.\n- با پیشرفت کد، کامنت‌ها را نیز متناسب به‌روز نگه دارید.\n\n\u003ca name=\"environments\"\u003e\u003c/a\u003e\n\n## 3. متغیرهای محیطی/Environments\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/laptop.png\" alt=\"Environments\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- در صورت نیاز، environmentهای جداگانه‌ای برای `development`، `test` و `production` تعریف کنید.\n\n_چرا:_\n\n\u003e در محیط‌ها (environments) مختلف ممکن است data، tokens، APIs، ports و... متفاوتی نیاز باشند. ممکن است بخواهید یک حالت `development` ایزوله داشته باشید که به APIهای جعلی متصل می‌شود و داده‌های قابل پیش‌بینی برمی‌گرداند، که این کار هم تست‌های خودکار و هم تست‌های دستی را بسیار ساده‌تر می‌کند. یا شاید بخواهید Google Analytics را فقط در محیط `production` فعال کنید و به همین ترتیب.\n\u003e [توضیحات بیشتر ...](https://stackoverflow.com/questions/8332333/node-js-setting-up-environment-specific-configs-to-be-used-with-everyauth)\n\n- پیکربندی‌های مختص هر محیط اجرایی را از متغیرهای محیطی (environment variables) بارگذاری کنید و هرگز آن‌ها را به‌عنوان مقادیر ثابت در کد قرار ندهید. [به این نمونه نگاه کنید](./config.sample.js).\n\n_چرا:_\n\n\u003e در این فایل‌ها ممکن است tokens، passwords و دیگر اطلاعات ارزشمند وجود داشته باشند. پیکربندی/کانفیگ شما باید به‌درستی از بخش‌های داخلی برنامه جدا باشد، به گونه‌ای که کد در هر لحظه ممکن است عمومی شود.\n\n_چگونه:_\n\n\u003e فایل‌های `.env` را برای ذخیره متغیرهای خود استفاده کنید و آن‌ها را به `.gitignore` اضافه کنید تا از مخزن مستثنی شوند. در عوض، یک فایل `.env.example` کامیت کنید که به‌عنوان راهنما برای توسعه‌دهندگان عمل کند. برای محیط production، باید همچنان متغیرهای محیطی را به روش استاندارد تنظیم کنید. [بیشتر بخوانید](https://medium.com/@rafaelvidaurre/managing-environment-variables-in-node-js-2cb45a55195f)\n\n- توصیه می‌شود قبل از شروع برنامه، متغیرهای محیطی را اعتبارسنجی کنید. [این نمونه را مشاهده کنید](./configWithTest.sample.js) که از `joi` برای اعتبارسنجی مقادیر ارائه‌شده استفاده می‌کند.\n\n_چرا:_\n\n\u003e این کار می‌تواند دیگران را از ساعت‌ها مشکل‌یابی/troubleshooting نجات دهد.\n\n\u003e \u003ca name=\"consistent-dev-environments\"\u003e\u003c/a\u003e\n\n### 3.1 ایجاد محیط‌های توسعه‌ی یکپارچه/Consistent dev environments:\n\n- نسخه‌ی Node خود را در بخش `engines` در فایل `package.json` تنظیم کنید..\n\n_چرا:_\n\n\u003e این کار به دیگران اطلاع می‌دهد که پروژه با کدام نسخه‌ی Node کار می‌کند. [توضیحات بیشتر ...](https://docs.npmjs.com/files/package.json#engines)\n\n- همچنین از `nvm` استفاده کنید و یک فایل `.nvmrc` در ریشه‌ی پروژه‌ی خود ایجاد کنید. فراموش نکنید که به آن در مستندات اشاره کنید.\n\n_چرا:_\n\n\u003e هر کسی که از `nvm` استفاده می‌کند، می‌تواند به سادگی با اجرای کامند `nvm use` به نسخه‌ی مناسب Node سوئیچ کند. [توضیحات بیشتر ...](https://github.com/creationix/nvm)\n\n- تنظیم یک اسکریپت `preinstall` که نسخه‌های Node و npm را بررسی کند، ایده‌ی خوبی است.\n\n_چرا:_\n\n\u003e برخی وابستگی‌ها/dependencies ممکن است در صورت نصب توسط نسخه‌های جدیدتر npm با خطا مواجه شوند.\n\n- در صورت امکان از Docker استفاده کنید.\n\n_چرا:_\n\n\u003e این کار می‌تواند یک محیط سازگار در کل فرآیند کاری شما فراهم کند، بدون نیاز به تنظیمات یا وابستگی‌های پیچیده. [توضیحات بیشتر ...](https://hackernoon.com/how-to-dockerize-a-node-js-application-4fbab45a0c19)\n\n- از پکیج‌های محلی/local به‌جای پکیج‌های نصب‌شده به‌صورت گلوبالی/globally استفاده کنید.\n\n_چرا:_\n\n\u003e این کار به شما اجازه می‌دهد پکیج‌های خود را با همکارانتان به اشتراک بگذارید، به جای اینکه انتظار داشته باشید آن‌ها را به‌صورت گلوبالی روی سیستم خود نصب کرده باشند.\n\n\u003ca name=\"consistent-dependencies\"\u003e\u003c/a\u003e\n\n### 3.2 وابستگی‌های یکسان و هماهنگ/Consistent dependencies:\n\n- اطمینان حاصل کنید که اعضای تیم دقیقاً همان وابستگی‌ها (dependencies) را مانند شما دریافت کنند.\n\n_چرا:_\n\n\u003e زیرا می‌خواهید که کد، در هر محیط توسعه‌ای به همان شکل مورد انتظار عمل کند و یکسان باشد. [توضیحات بیشتر ...](https://kostasbariotis.com/consistent-dependencies-across-teams/)\n\n_چگونه:_\n\n\u003e از `package-lock.json` در نسخه 5 از `npm` یا بالاتر، استفاده کنید.\n\n_من npm@5 ندارم:_\n\n\u003e در این صورت می‌توانید از `Yarn` استفاده کنید و اطمینان حاصل کنید که این موضوع را در فایل `README.md`. پس از هر به‌روزرسانی وابستگی‌ها، lock file و `package.json` باید نسخه‌های یکسانی داشته باشند. [توضیحات بیشتر ...](https://yarnpkg.com/en/)\n\n_من اسم `Yarn` را دوست ندارم:_\n\n\u003e متأسفانه انتخاب دیگری ندارید. برای نسخه‌های قدیمی‌تر `npm`, هنگام نصب وابستگی جدید از `—save --save-exact` استفاده کنید و قبل از انتشار پروژه، فایل `npm-shrinkwrap.json` ایجاد کنید. [توضیحات بیشتر ...](https://docs.npmjs.com/files/package-locks)\n\n\u003ca name=\"dependencies\"\u003e\u003c/a\u003e\n\n## 4. وابستگی‌ها/Dependencies\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/modules.png\" alt=\"modules\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- بر روی پکیج‌های فعلی خود را که در حال حاضر در دسترس هستند، پیگیری و نظارت کنید: به عنوان مثال، از دستور `npm ls --depth=0` استفاده کنید. (توضیحات مترجم: با استفاده از دستور `npm ls --depth=0` در محیط خط فرمان، می‌توانید فهرستی از پکیج‌های سطح اول (بدون نمایش وابستگی‌های زیرمجموعه‌ای) را مشاهده کنید. این کار به شما کمک می‌کند تا بدانید چه بسته‌هایی در حال حاضر در پروژه‌تان نصب هستند و از وضعیت آن‌ها مطلع باشید.) [توضیحات بیشتر ...](https://docs.npmjs.com/cli/ls)\n- بررسی کنید آیا هیچ‌یک از پکیج‌های شما بی‌استفاده یا نامربوط (غیرضروری یا غیرکاربردی) شده‌اند: با استفاده از ابزار `depcheck` [توضیحات بیشتر ...](https://www.npmjs.com/package/depcheck)\n\n_چرا:_\n\n\u003e ممکن است یک کتابخانه بی‌استفاده را در کد خود داشته باشید که باعث افزایش حجم نهایی برنامه شود. وابستگی‌های بی‌استفاده را پیدا کرده و حذف کنید.\n\n- قبل از استفاده از یک وابستگی، آمار دانلود آن را بررسی کنید تا ببینید آیا توسط جامعه به‌طور گسترده‌ای استفاده می‌شود یا خیر: با استفاده از ابزار `npm-stat`. [توضیحات بیشتر ...](https://npm-stat.com/)\n\n_چرا:_\n\n\u003e استفاده بیشتر (از پکیج‌ها) معمولاً به معنای داشتن تعداد بیشتری از مشارکت‌کنندگان است که اغلب منجر به نگهداری بهتر می‌شود و همه این‌ها باعث می‌شود که باگ‌ها سریع‌تر کشف و اصلاحات سریع‌تر توسعه داده شوند.\n\n- پیش از استفاده از یک وابستگی، بررسی کنید که آیا آن وابستگی نسخه‌های منظم و پایداری ارائه می‌دهد و تعداد زیادی نگهدارندگان (maintainers) دارد یا نه. به عنوان مثال، می‌توانید از دستور `npm view async` استفاده کنید. [توضیحات بیشتر ...](https://docs.npmjs.com/cli/view)\n\n_چرا:_\n\n\u003e داشتن تعداد زیادی از مشارکت‌کنندگان زمانی مؤثر است که نگهدارندگان بتوانند اصلاحات و تغییرات را به سرعت merge کنند.\n\n- اگر به وابستگی کمتر شناخته شده‌ای (غیرمشهور) نیاز دارید، قبل از استفاده از آن، با تیم خود مشورت کنید.\n- همیشه مطمئن شوید که برنامه شما با آخرین نسخه از وابستگی‌هایش بدون هیچگونه مشکلی/خرابی کار می‌کند: از دستور `npm outdated` استفاده کنید. [توضیحات بیشتر ...](https://docs.npmjs.com/cli/outdated)\n\n_چرا:_\n\n\u003e بروزرسانی‌ وابستگی‌ها (dependencies) گاهی شامل تغییرات مخرب می‌شوند. هر زمان که بروزرسانی‌ها نمایش داده می‌شوند، حتماً release note ها را بررسی کنید. وابستگی‌های (dependencies) خود را یکی‌یکی بروزرسانی کنید، زیرا اگر مشکلی پیش بیاید، عیب‌یابی آن آسان‌تر خواهد بود. از ابزارهای کاربردی مانند موارد زیر استفاده کنید: [npm-check-updates](https://github.com/tjunnone/npm-check-updates).\n\n- بررسی کنید که آیا بسته موردنظر مشکلات امنیتی شناخته‌شده‌ای دارد یا خیر؛ به عنوان مثال، با استفاده از [Snyk](https://snyk.io/test?utm_source=risingstack_blog).\n\n\u003ca name=\"testing\"\u003e\u003c/a\u003e\n\n## 5. تست کردن/Testing\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/testing.png\" alt=\"testing\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- در صورت نیاز، یک environment به نام `test` (برای حالت تست) ایجاد کنید.\n\n_چرا:_\n\n\u003e گاهی تست end to end در حالت `production` ممکن است کافی به نظر برسد، اما در موارد خاص نیاز به محیط تست جداگانه‌ای وجود دارد. مثلاً ممکن است نخواهید اطلاعات تحلیلی در حالت `production` فعال شود و داشبورد افراد را با داده‌های تست آلوده کنید. (توضیحات مترجم: چون داده‌های تستی ممکن است اطلاعات واقعی را تحت تأثیر قرار دهد، مثلا باعث شلوغی و ایجاد داده‌های غیرضروری شوند و یا مانع از درک دقیق اطلاعات واقعی توسط کاربران یا تیم تحلیل شوند.) مثال دیگر این است که ممکن است API شما در حالت تولید محدودیت‌ تعداد درخواست (rate limit) داشته باشد و پس از تعداد مشخصی درخواست، فراخوانی APIها توسط تست را مسدود کند.\n\n- فایل‌های تست خود را در کنار ماژول‌های مورد آزمایش با استفاده از الگوی نام‌گذاری خاصی `*.test.js` یا `*.spec.js` قرار دهید، مانند `moduleName.spec.js`.\n\n_چرا:_\n\n\u003e برای پیدا کردن یک تست واحد، در ساختار پوشه‌ها جستجو و پیمایش نکنید. [توضیحات بیشتر ...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)\n\n- برای جلوگیری از سردرگمی، فایل‌های تست اضافی خود را پر یک پوشه جداگانه قرار دهید.\n\n_چرا:_\n\n\u003e برخی از فایل‌های تست مستقیماً به فایل پیاده‌سازی خاصی مرتبط نیستند. باید این فایل‌ها را در پوشه‌ای قرار دهید که احتمالاً توسط سایر توسعه‌دهندگان به راحتی یافت شود: پوشه `__test__`. این نام `__test__` هم اکنون یک استاندارد است و توسط اکثر فریم‌ورک‌های تست جاوااسکریپت تشخیص داده می‌شود.\n\n- کد قابل تست بنویسید، از اثرات جانبی (side effect) خودداری کنید، اثرات جانبی را جدا کنید، و توابع خالص (pure functions) بنویسید.\n\n_چرا:_\n\n\u003e هر بخش از منطق کسب‌وکار (business logic) باید به صورت مستقل و جداگانه مورد آزمایش و تست قرار گیرد تا مطمئن شوید که هر قسمت به درستی کار می‌کند. باید \"تأثیر عوامل تصادفی یا فرآیندهای غیرقابل‌پیش‌بینی را در کد به حداقل برسانید\" [توضیحات بیشتر ...](https://medium.com/javascript-scene/tdd-the-rite-way-53c9b46f45e3)\n\n\u003e یک تابع خالص (pure function) تابعی است که همیشه برای ورودی یکسان، خروجی یکسانی را باز می‌گرداند. برعکس، یک تابع ناخالص (impure function) تابعی است که ممکن است اثرات جانبی داشته باشد یا برای تولید یک مقدار به شرایط خارجی وابسته باشد، که این امر باعث می‌شود کمتر قابل پیش‌بینی باشد. [توضیحات بیشتر ...](https://hackernoon.com/structure-your-javascript-code-for-testability-9bc93d9c72dc)\n\n- از یک static type checker استفاده کنید\n\n_چرا:_\n\n\u003e گاهی ممکن است به یک Static type checker نیاز داشته باشید. این ابزارها، سطحی از قابلیت اطمینان را برای کد شما به ارمغان می‌آورند. [توضیحات بیشتر ...](https://medium.freecodecamp.org/why-use-static-types-in-javascript-part-1-8382da1e0adb)\n\n- قبل از آنکه درخواست pull request به برنچ `develop` را ارسال کنید، تست‌ها را به‌صورت locally اجرا کنید.\n\n_چرا:_\n\n\u003e قطعاً نمی‌خواهید کسی باشید که باعث شکست فرایند بیلد برنچ آماده‌ی production شده است. تست‌های خود را پس از `rebase` و پیش از ارسال به شاخه feature-branch به مخزن ریموت اجرا کنید.\n\n- تست‌های خود را از جمله دستورالعمل‌های مربوطه در بخش مناسب فایل `README.md` پروژه را مستندسازی کنید.\n\n_چرا:_\n\n\u003e این مستندات مانند یک یادداشت راهنما است که برای توسعه‌دهندگان دیگر، کارشناسان DevOps، یا تیم تضمین کیفیت (QA) و هر کسی که با کد شما کار می‌کند، مفید خواهد بود.\n\n\u003ca name=\"structure-and-naming\"\u003e\u003c/a\u003e\n\n## 6. ساختار و نام‌گذاری/Structure and Naming\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/folder-tree.png\" alt=\"Structure and Naming\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- فایل‌های خود را بر اساس ویژگی‌های محصول / صفحات / کامپوننت‌ها سازمان‌دهی کنید، نه بر اساس نقش‌ها. همچنین فایل‌های تست را در کنار آن‌ها قرار دهید.\n\n**بد**\n\n```\n.\n├── controllers\n|   ├── product.js\n|   └── user.js\n├── models\n|   ├── product.js\n|   └── user.js\n```\n\n**خوب**\n\n```\n.\n├── product\n|   ├── index.js\n|   ├── product.js\n|   └── product.test.js\n├── user\n|   ├── index.js\n|   ├── user.js\n|   └── user.test.js\n```\n\n_چرا:_\n\n\u003e به جای داشتن لیست طولانی از فایل‌ها، ماژول‌های کوچک ایجاد کنید که هر کدام یک مسئولیت خاص را دربرمی‌گیرند، از جمله تست آن‌ها و موارد دیگر. این کار باعث می‌شود دسترسی به فایل‌ها ساده‌تر شده و بتوانید به سرعت و با یک نگاه فایل‌های مورد نظر را پیدا کنید.\n\n- فایل‌های تست اضافی خود را در یک پوشه‌ی جداگانه به نام test قرار دهید تا از سردرگمی جلوگیری شود.\n\n_چرا:_\n\n\u003e این کار برای سایر توسعه‌دهندگان یا کارشناسان DevOps تیم شما موجب صرفه‌جویی در زمان می‌شود.\n\n- از یک پوشه به نام `./config` برای تنظیمات استفاده کنید و فایل‌های پیکربندی جداگانه برای محیط‌ها (environments) مختلف ایجاد نکنید.\n\n_چرا:_\n\n\u003e زمانی که یک فایل کانفیگ را برای اهداف مختلف (مانند پایگاه داده، API و غیره) تجزیه می‌کنید، قرار دادن آن‌ها در پوشه‌ای با نام مشخص مانند `config` منطقی است. فقط به خاطر داشته باشید که برای محیط‌های مختلف فایل‌های جداگانه نسازید، زیرا با افزایش استقرارهای برنامه، نام‌های محیط جدیدی مورد نیاز می‌شود و مدیریت آن پیچیده خواهد شد.\n\n\u003e مقادیر مورد استفاده در فایل‌های کانفیگ باید از طریق متغیرهای محیطی (environment variables) فراهم شوند. [توضیحات بیشتر ...](https://medium.com/@fedorHK/no-config-b3f1171eecd5)\n\n- اسکریپت‌های خود را در یک پوشه به نام `./scripts` قرار دهید. این شامل اسکریپت‌های `bash` و `node` است.\n\n_چرا:_\n\n\u003e احتمالاً به بیش از یک اسکریپت نیاز خواهید داشت، مانند production build, development build, database feeders, database synchronization و غیره.\n\n- خروجی بیلد خود را در یک پوشه به نام `./build` قرار دهید. `build/` را به `.gitignore` اضافه کنید.\n\n_چرا:_\n\n\u003e نام‌گذاری آن به سلیقه شما بستگی دارد، `dist` نیز گزینه خوبی است. اما با تیم خود این نام‌گذاری را هماهنگ کنید. فایل‌هایی که در این پوشه قرار می‌گیرند معمولاً تولید شده‌اند (bundled, compiled, transpiled) یا به این پوشه منتقل شده‌اند. چیزی که می‌توانید تولید کنید، هم‌تیمی‌های شما نیز باید قادر به تولید آن باشند؛ بنابراین نیازی به ارسال آن‌ها به مخزن ریموت نیست، مگر اینکه هدف خاصی داشته باشید.\n\n\u003ca name=\"code-style\"\u003e\u003c/a\u003e\n\n## 7. سبک کدنویسی/Code style\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/code-style.png\" alt=\"Code style\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n\u003ca name=\"code-style-check\"\u003e\u003c/a\u003e\n\n### 7.1 برخی از اصول code style\n\n- برای پروژه‌های جدید از سینتکس جاوااسکریپت مدرن (استیج ۲ و بالاتر) استفاده کنید. برای پروژه‌های قدیمی، با سینتکس موجود سازگار بمانید مگر اینکه قصد به‌روزرسانی آن را داشته باشید.\n\n_چرا:_\n\n\u003e این موضوع به تصمیم شما بستگی دارد. ما از مبدل‌ها (ترنسپایلرها) برای بهره‌گیری از مزایای سینتکس جدید استفاده می‌کنیم. استیج ۲ با تغییرات جزئی احتمالا بخشی از استاندارد خواهد شد.\n\n- اطمینان حاصل کنید که بررسی سبک کدنویسی (code style) به عنوان بخشی از فرآیند build پروژه انجام شود. (تا هماهنگی و استاندارد بودن کدها در تمام مراحل توسعه حفظ شود.)\n\n_چرا:_\n\n\u003e متوقف کردن build برنامه یکی از روش‌های اعمال سبک کدنویسی در کد است. این کار از بی‌توجهی به سبک کدنویسی جلوگیری می‌کند. این روش را برای کد سمت client و server اجرا کنید. [توضیحات بیشتر ...](https://www.robinwieruch.de/react-eslint-webpack-babel/)\n\n- برای اعمال سبک کدنویسی از [ESLint - ابزار بررسی سبک کدنویسی جاوااسکریپت](http://eslint.org/) استفاده کنید.\n\n_چرا:_\n\n\u003e ما `eslint` را ترجیح می‌دهیم، اما شما می‌توانید انتخاب دیگری داشته باشید. این ابزار قوانین بیشتری را پشتیبانی می‌کند، همچنین قابلیت تنظیم و افزودن قوانین سفارشی را دارد.\n\n- ما از کد استایل [Airbnb](https://github.com/airbnb/javascript) برای جاوااسکریپت استفاده می‌کنیم، [بیشتر بخوانید](https://www.gitbook.com/book/duk/airbnb-javascript-guidelines/details). از کد استایلی که پروژه یا تیم شما نیاز دارد استفاده کنید (تا کدهایتان با استانداردهای تعیین‌شده هماهنگ باشند).\n- ما هنگام استفاده از [FlowType](https://flow.org/) از [قوانین بررسی سبک تایپ Flow برای ESLint](https://github.com/gajus/eslint-plugin-flowtype) استفاده می‌کنیم.\n\n_چرا:_\n\n\u003e ابزار Flow سینتکس‌های جدیدی را معرفی می‌کند که نیاز به رعایت سبک کدنویسی خاصی دارند و باید بررسی شوند.\n\n- از فایل `.eslintignore` برای مستثنی کردن فایل‌ها یا پوشه‌ها از بررسی کد استایل استفاده کنید.\n\n_چرا:_\n\n\u003e برای مستثنی کردن چند فایل از بررسی سبک کدنویسی، لازم نیست کدتان را با کامنت‌های `eslint-disable` شلوغ کنید.\n\n- قبل از ارسال یک Pull Request، تمام کامنت‌های `eslint-disable` خود را حذف کنید.\n\n_چرا:_\n\n\u003e طبیعی است که هنگام کار بر روی یک بخش از کد، برای تمرکز بیشتر روی منطق، بررسی سبک را غیرفعال کنید. فقط به خاطر داشته باشید که کامنت‌های `eslint-disable` را حذف کرده و قوانین را رعایت کنید.\n\n- بسته به حجم و اندازه کار، از کامنت‌های `//TODO:` استفاده کنید یا یک تیکت باز کنید.\n\n_چرا:_\n\n\u003e استفاده از کامنت‌های `//TODO:` به شما و همکارانتان کمک می‌کند تا وظایف کوچک مانند بازنویسی یک تابع یا به‌روزرسانی یک توضیح را به خاطر بسپارید. برای وظایف بزرگ‌تر، از فرمت `//TODO(#3456)` استفاده کنید که توسط قوانین lint اعمال می‌شود، که شماره‌ی داخل پرانتز به یک تیکت باز اشاره دارد.\n\n- همیشه کامنت‌ها را به‌روز و مرتبط با تغییرات کد نگه دارید. بخش‌های کامنت‌شده کد را حذف کنید.\n\n_چرا:_\n\n\u003e کد شما باید تا حد ممکن خوانا باشد؛ هر چیزی که حواس را پرت می‌کند، حذف کنید. اگر یک تابع را بازنویسی کردید، تابع قدیمی را فقط کامنت نکنید، بلکه آن را حذف کنید.\n\n- از کامنت‌ها، لاگ‌ها یا نام‌های نامرتبط یا طنزآمیز پرهیز کنید.\n\n_چرا:_\n\n\u003e اگرچه در فرآیند build برنامه آن‌ شوخی‌ها ممکن است (و بهتر است بگویم باید) حذف شود، اما گاهی source code شما به شرکت یا مشتری دیگری منتقل می‌شود که ممکن است آن‌ها چنین شوخی‌هایی را نپسندند.\n\n- نام‌ها را به گونه‌ای انتخاب کنید که قابل جست‌وجو و دارای تفاوت‌های معنادار باشند و از نام‌های کوتاه‌شده و مخفف بپرهیزید. برای توابع، از نام‌های طولانی و توصیفی استفاده کنید. نام تابع باید یک فعل یا عبارت فعلی باشد و هدف آن را به وضوح بیان کند.\n\n_چرا:_\n\n\u003e این کار (استفاده از نام‌های کامل و توصیفی) باعث می‌شود کد خواناتر و درک آن راحت‌تر و ساده‌تر شود.\n\n- توابع خود را در فایل بر اساس «قانون نزولی» (Step-down Rule) سازمان‌دهی کنید؛ به این صورت که توابع سطح بالاتر در بالای فایل و توابع سطح پایین‌تر در زیر آن‌ها قرار گیرند.\n\n_چرا:_\n\n\u003e این کار کد را خواناتر و درک آن بهتر می‌کند\n\n\u003ca name=\"enforcing-code-style-standards\"\u003e\u003c/a\u003e\n\n### 7.2 اعمال استانداردهای سبک کدنویسی\n\n- از فایل [.editorconfig](http://editorconfig.org/) استفاده کنید که به توسعه‌دهندگان کمک می‌کند تا سبک‌های کدنویسی یکسانی را بین ویرایشگرها و IDEهای مختلف پروژه تعریف و حفظ کنند.\n\n_چرا:_\n\n\u003e پروژه EditorConfig شامل یک فرمت فایل برای تعریف سبک‌ و استال‌های کدنویسی است که شامل مجموعه‌ای از افزونه‌ها برای ویرایشگرهای متنی است، که به ویرایشگرها این امکان را می‌دهد تا فرمت فایل را بخوانند و از استایل‌های تعریف‌شده پیروی کنند. فایل‌های EditorConfig خوانا هستند و به‌خوبی با سیستم‌های کنترل نسخه کار می‌کنند.\n\n- ویرایشگر خود را طوری تنظیم کنید که به شما در مورد خطاهای سبک کدنویسی اطلاع دهد. از [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) و [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) همراه با پیکربندی ESLint خود استفاده کنید. [توضیحات بیشتر ...](https://github.com/prettier/eslint-config-prettier#installation)\n- استفاده از Git hooks را مدنظر قرار دهید.\n\n_چرا:_\n\n\u003e استفاده از Git hooks به‌طور قابل‌توجهی بهره‌وری توسعه‌دهندگان را افزایش می‌دهد. با اعمال تغییرات، انجام commit و ارسال (push) به محیط‌های staging یا production، بدون نگرانی از خراب شدن build برنامه، می‌توانید با اطمینان بیشتری کار کنید. [توضیحات بیشتر ...](http://githooks.com/)\n\n- از Prettier همراه با یک precommit hook استفاده کنید.\n\n_چرا:_\n\n\u003e اگرچه `prettier` به‌خودی‌خود قدرتمند است، اجرای دستی آن به‌عنوان یک تسک npm برای قالب‌بندی کد چندان کارآمد نیست. در اینجا `lint-staged` (و `husky`) وارد عمل می‌شوند. درباره پیکربندی `lint-staged` [اینجا](https://github.com/okonet/lint-staged#configuration) و پیکربندی `husky` [اینجا](https://github.com/typicode/husky) بیشتر بخوانید..\n\n\u003ca name=\"logging\"\u003e\u003c/a\u003e\n\n## 8. ثبت وقایع/Logging\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/logging.png\" alt=\"Logging\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n- از استفاده از console.log در سمت کلاینت در محیط production خودداری کنید.\n\n_چرا:_\n\n\u003e حتی اگر فرآیند build برنامه شما می‌تواند (و باید) آن‌ لاگ‌ها را حذف کند، اطمینان حاصل کنید که ابزار بررسی استایل کدنویسی شما درباره‌ی باقی‌مانده‌های console.log هشدار می‌دهد.\n\n- برای تولید لاگ‌های خوانا در محیط production، بهتر است از کتابخانه‌های logging مناسب (مانند [winston](https://github.com/winstonjs/winston) یا [node-bunyan](https://github.com/trentm/node-bunyan)) استفاده کنید.\n\n_چرا:_\n\n\u003e این کار عیب‌یابی را آسان‌تر و دلپذیرتر می‌کند، چون می‌توانید از قابلیت‌هایی مانند رنگ‌بندی، افزودن زمان به لاگ‌ها، ثبت لاگ‌ها در فایل علاوه بر کنسول و حتی ثبت لاگ‌ها در فایل‌هایی که به‌صورت روزانه ایجاد و بایگانی می‌شوند، استفاده کنید. [توضیحات بیشتر ...](https://blog.risingstack.com/node-js-logging-tutorial/)\n\n\u003ca name=\"api\"\u003e\u003c/a\u003e\n\n## 9. ای‌پی‌آی/API\n\n\u003ca name=\"api-design\"\u003e\u003c/a\u003e\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/api.png\" alt=\"API\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n### 9.1 طراحی API\n\n_چرا:_\n\n\u003e هدف این است که رابط‌های RESTfulی طراحی کنیم که منطقی و ساده باشند تا اعضای تیم و مشتریان بتوانند به‌سادگی و به‌صورت یکنواخت از آن‌ها استفاده کنند.\n\n_چرا:_\n\n\u003e نبود هماهنگی و سادگی می‌تواند هزینه‌های یکپارچه‌سازی و نگهداری را به طور چشمگیری افزایش دهد؛ به همین دلیل طراحی `API` در این داکیومنت گنجانده شده است.\n\n- ما عمدتاً از طراحی مبتنی بر منابع (Resource-Oriented Design) پیروی می‌کنیم که سه عنصر اصلی دارد: منابع (Resource)، مجموعه‌ها (Collection) و URLها.\n  - یک منبع شامل داده‌هایی است که می‌تواند به صورت تو در تو (nested) سازمان‌دهی شود و متدهایی برای عملیات روی آن وجود دارد.\n  - گروهی از منابع، یک مجموعه نامیده می‌شود.\n  - آدرس اینترنتی (URL) که مکان آنلاین یک منبع یا مجموعه را مشخص می‌کند.\n\n_چرا:_\n\n\u003e این یک طراحی بسیار شناخته‌شده برای توسعه‌دهندگان است (که اصلی‌ترین مصرف‌کنندگان API هستند). علاوه بر خوانایی و سهولت استفاده، این روش به ما اجازه می‌دهد کتابخانه‌ها و connectorهای عمومی بنویسیم بدون این‌که نیاز به شناخت جزئیات خاص هر API داشته باشیم.\n\n- برای URL‌ها از kebab-case استفاده کنید.\n- برای پارامترهای query string یا فیلدهای منابع از camelCase استفاده کنید.\n- از اسامی جمع به صورت kebab-case برای نام منابع در URLها استفاده کنید.\n- همیشه از اسامی جمع برای نامگذاری URLهایی که به یک مجموعه اشاره دارند استفاده کنید: `/users`.\n\n_چرا:_\n\n\u003e اساساً، این کار خوانایی را بهتر کرده و URLها را هماهنگ نگه می‌دارد. [توضیحات بیشتر ...](https://apigee.com/about/blog/technology/restful-api-design-plural-nouns-and-concrete-names)\n\n- در سورس کد، اسامی جمع را به متغیرها و پراپرتی‌ها با پسوند «List» تبدیل کنید.\n\n_چرا:_:\n\n\u003e استفاده از اسامی جمع در URL مناسب است، اما در سورس کد ممکن است نامحسوس و مستعد خطا باشد.\n\n- همیشه از مفاهیم مفرد استفاده کنید که با یک مجموعه شروع شده و به یک شناسه ختم می‌شوند:\n\n```\n/students/245743\n/airports/kjfk\n```\n\n- از تولید URLهایی مانند زیر اجتناب کنید:\n\n```\nGET /blogs/:blogId/posts/:postId/summary\n```\n\n_چرا:_\n\n\u003e این URL به جای ارجاع به یک منبع (resource)، به یک ویژگی (property) اشاره می‌کند. شما می‌توانید ویژگی مورد نظر را به‌عنوان یک پارامتر در درخواست ارسال کنید تا پاسخ دریافتی مختصرتر و بهینه‌تر باشد.\n\n- افعال را از URLهای منابع خود حذف کنید.\n\n_چرا:_\n\n\u003e زیرا اگر برای هر عملیات resource از یک فعل استفاده کنید، به زودی با لیستی بزرگ از URLها مواجه خواهید شد که الگوی ثابتی ندارند و یادگیری را برای توسعه‌دهندگان دشوار می‌کنند. علاوه بر این، ما از افعال برای چیز دیگری استفاده می‌کنیم.\n\n- از افعال برای موارد غیر منبع (non-resources) استفاده کنید. در این حالت، API شما هیچ منبعی برنمی‌گرداند. در عوض، یک عملیات را اجرا کرده و نتیجه را برمی‌گرداند. این‌ها عملیات CRUD (ایجاد، بازیابی، به‌روزرسانی و حذف) **نیستند**:\n\n```\n/translate?text=Hallo\n```\n\n_چرا:_\n\n\u003e زیرا برای CRUD ما از متدهای HTTP بر روی URLهای `resource` یا `collection` استفاده می‌کنیم. افعالی که درباره آن‌ها صحبت می‌کنیم در واقع کنترلرها `Controllers` هستند. شما معمولاً تعداد زیادی از این‌ها را توسعه نمی‌دهید. [توضیحات بیشتر ...](https://github.com/byrondover/api-guidelines/blob/master/Guidelines.md#controller)\n\n- اگر بدنه درخواست (request body) یا پاسخ (response) از نوع `JSON` است، لطفاً برای نام‌گذاری پراپرتی‌های JSON از `camelCase` پیروی کنید تا یکپارچگی و سازگاری حفظ شود.\n\n_چرا:_\n\n\u003e این یک راهنما و دستورالعمل برای پروژه JavaScript است، که فرض بر این است که زبان برنامه‌نویسی مورد استفاده برای تولید و تجزیه JSON، جاوااسکریپت می‌باشد.\n\n- با وجود اینکه یک منبع (resource) مفهومی یکتا و مفرد است که مشابه با یک نمونه شیء یا رکورد پایگاه داده است، شما نباید از نام جدول (`table_name`) برای نام‌گذاری منبع و از نام ستون (`column_name`) برای پراپرتی‌های منبع استفاده کنید. به عبارت دیگر، نام‌گذاری منابع و پراپرتی‌های آن‌ها نباید مستقیماً از ساختار پایگاه داده مشتق شود؛ بلکه باید بر اساس مفاهیم و نیازهای دامنه‌ی کاربرد طراحی شود تا از وابستگی به جزئیات پیاده‌سازی جلوگیری شود.\n\n_چرا:_\n\n\u003e زیرا هدف شما نمایش منابع است، نه جزئیات ساختار پایگاه داده.\n\n- دوباره تکرار می‌کنم، فقط از اسم‌ها در URL خود هنگام نام‌گذاری منابع استفاده کنید و سعی نکنید عملکرد آن‌ها را توضیح دهید.\n\n_چرا:_\n\n\u003e فقط از اسامی در URLهای منبع استفاده کنید و از نوشتن مواردی مانند `/addNewUser` یا `/updateUser` خودداری کنید. همچنین از ارسال عملیات منابع به‌عنوان پارامتر اجتناب کنید.\n\n- عملکردهای CRUD را با استفاده از متدهای HTTP توضیح دهید:\n\n_چگونه:_\n\n\u003e متد `GET`: برای دریافت از یک resource استفاده می‌شود.\n\n\u003e متد `POST`: برای ایجاد منابع (resources) جدید و زیرمنابع (sub-resources) به کار می‌رود.\n\n\u003e متد `PUT`: برای به‌روزرسانی منابع موجود استفاده می‌شود.\n\n\u003e متد `PATCH`: برای به‌روزرسانی جزئی منابع موجود به کار می‌رود؛ به‌طوری‌که فقط فیلدهای ارائه‌شده را به‌روزرسانی کرده و سایر فیلدها را بدون تغییر باقی می‌گذارد.\n\n\u003e متد `DELETE`: برای حذف منابع موجود استفاده می‌شود.\n\n- برای منابع تو در تو (Nested Resources)، توصیه می‌شود رابطه بین آن‌ها را در ساختار URL منعکس کنید. به‌عنوان مثال، برای نمایش ارتباط بین یک کارمند و شرکت مربوطه، می‌توانید از شناسه‌ها (`id`) در URL استفاده کنید.\n\n_چرا:_\n\n\u003e این روش دسترسی به منابع مرتبط را آسان‌تر می‌کند.\n\n_چگونه:_\n\n\u003e درخواست `GET /schools/2/students` , باید لیست تمام دانش‌آموزان مدرسه با شناسه ۲ را برگرداند.\n\n\u003e درخواست `GET /schools/2/students/31` , باید جزئیات دانش‌آموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، برگرداند.\n\n\u003e درخواست `DELETE /schools/2/students/31` , باید دانش‌آموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، حذف کند.\n\n\u003e درخواست `PUT /schools/2/students/31` , باید اطلاعات دانش‌آموز با شناسه ۳۱ را که متعلق به مدرسه ۲ است، به‌روزرسانی کند.\n\n\u003e درخواست `POST /schools` , باید یک مدرسه جدید ایجاد کرده و جزئیات مدرسه تازه ایجاد شده را برگرداند. از POST بر روی URLهای مجموعه‌ای (Collection) استفاده کنید.\n\n- برای نسخه‌دهی، از یک شماره ترتیبی ساده با پیشوند `v` استفاده کنید (مانند v1، v2) و آن را تا حد امکان در ابتدای URL قرار دهید تا دامنه بالاتری را (برای تاثیرگذاری) داشته باشد:\n\n```\nhttp://api.domain.com/v1/schools/3/students\n```\n\n_چرا:_\n\n\u003e وقتی APIهای شما به‌طور عمومی برای سایر اشخاص ثالث در دسترس هستند، اعمال تغییرات ناسازگار (breaking changes)، می‌تواند باعث اختلال در عملکرد محصولات یا خدماتی شود که از APIهای شما استفاده می‌کنند. استفاده از نسخه‌بندی در URL می‌تواند از بروز چنین مشکلاتی جلوگیری کند. [توضیحات بیشتر ...](https://apigee.com/about/blog/technology/restful-api-design-tips-versioning)\n\n- پیام‌های پاسخ (Response) باید خودتوضیح‌دهنده باشند، به‌طوری‌که گیرنده بتواند به‌راحتی مفهوم آن‌ها را درک کند. یک پیام خطای مناسب ممکن است شبیه به این باشد:\n\n```json\n{\n\t\"code\": 1234,\n\t\"message\": \"Something bad happened\",\n\t\"description\": \"More details\"\n}\n```\n\nیا برای خطاهای اعتبارسنجی:\n\n```json\n{\n\t\"code\": 2314,\n\t\"message\": \"Validation Failed\",\n\t\"errors\": [\n\t\t{\n\t\t\t\"code\": 1233,\n\t\t\t\"field\": \"email\",\n\t\t\t\"message\": \"Invalid email\"\n\t\t},\n\t\t{\n\t\t\t\"code\": 1234,\n\t\t\t\"field\": \"password\",\n\t\t\t\"message\": \"No password provided\"\n\t\t}\n\t]\n}\n```\n\n_چرا:_\n\n\u003e توسعه‌دهندگان در زمان‌های بحرانی که در حال عیب‌یابی و حل مشکلات پس از انتشار برنامه‌هایی که با استفاده از APIهای شما ساخته‌اند و در دست کاربران قرار گرفته‌اند، به خطاهای خوب و خوش‌طراحی‌شده وابسته هستند.\n\n_توجه: پیام‌های استثنا مربوط به امنیت را تا حد ممکن عمومی و ساده نگه دارید. به عنوان مثال، به جای اینکه بنویسید «رمز عبور اشتباه است»، می‌توانید پیام «نام کاربری یا رمز عبور نامعتبر است» را بازگردانید. این کار باعث می‌شود که به‌طور ناخودآگاه به کاربر اطلاع ندهید که نام کاربری درست است و تنها رمز عبور اشتباه است._\n\n- از این کدهای وضعیت (status codes) برای ارسال همراه با پاسخ‌های خود استفاده کنید تا مشخص کنید آیا **همه چیز درست انجام شده است یا خیر**، آیا **کلاینت اشتباهی انجام داده** یا **مشکل از API بوده است**.\n\n      _کدام یک:_\n      \u003e پاسخ `200 OK` نشان‌دهنده موفقیت برای درخواست‌های `GET`, `PUT` یا `POST` است.\n\n      \u003e کد `201 Created` برای زمانی است که یک نمونه جدید ایجاد می‌شود. ایجاد یک نمونه جدید با استفاده از متد `POST` کد وضعیت `201` را برمی‌گرداند.\n\n      \u003e پاسخ `204 No Content` نشان‌دهنده موفقیت است، اما محتوایی برای ارسال در پاسخ وجود ندارد. از آن در زمانی استفاده کنید که عملیات `DELETE` با موفقیت انجام شده است.\n\n      \u003e پاسخ `304 Not Modified` برای به حداقل رساندن انتقال اطلاعات زمانی که گیرنده قبلاً نسخه‌های کش‌شده را دارد، استفاده می‌شود.\n\n      \u003e کد `400 Bad Request` برای زمانی است که درخواست پردازش نشده است، زیرا سرور نمی‌تواند بفهمد که مشتری چه چیزی درخواست کرده است.\n\n      \u003e کد `401 Unauthorized` برای زمانی است که درخواست فاقد اعتبارنامه‌های معتبر است و باید با اعتبارنامه‌های مورد نیاز دوباره ارسال شود.\n\n      \u003e کد `403 Forbidden` به این معنی است که سرور درخواست را فهمیده است، اما از اعطای مجوز خودداری می‌کند.\n\n      \u003e کد `404 Not Found` نشان می‌دهد که منبع درخواستی پیدا نشده است.\n\n      \u003e کد `500 Internal Server Error` نشان می‌دهد که درخواست معتبر است، اما سرور به دلیل برخی شرایط غیرمنتظره نمی‌تواند آن را انجام دهد.\n\n      _چرا:_\n      \u003e بیشتر ارائه‌دهندگان API از تعداد کمی از کدهای وضعیت HTTP استفاده می‌کنند. برای مثال، API سرویس Google GData تنها از ۱۰ کد وضعیت، Netflix از ۹ کد، و Digg تنها از ۸ کد وضعیت استفاده می‌کنند. البته، این پاسخ‌ها معمولاً شامل بدنه‌ای هستند که اطلاعات بیشتری را ارائه می‌دهد. در کل، بیش از ۷۰ کد وضعیت HTTP وجود دارد. اما اکثر توسعه‌دهندگان همه این ۷۰ کد را به خاطر ندارند.بنابراین، اگر شما کدهای وضعیتی را انتخاب کنید که خیلی رایج نیستند، توسعه‌دهندگان مجبور می‌شوند به جای ادامه کار روی برنامه خود، وقتشان را صرف جستجو در ویکی‌پدیا کنند تا متوجه شوند شما چه چیزی را سعی دارید به آن‌ها بگویید. [توضیحات بیشتر ...](https://apigee.com/about/blog/technology/restful-api-design-what-about-errors)\n\n- تعداد کل منابع/دیتا را در پاسخ (response) خود اعلام کنید.\n- پارامترهای `limit` و `offset` را بپذیرید.\n\n- مقدار داده‌ای که یک منبع در پاسخ ارائه می‌دهد نیز باید مورد توجه قرار گیرد. مصرف‌کننده API همیشه به تمام اطلاعات مربوط به یک منبع نیاز ندارد. از پارامتر fields استفاده کنید که لیستی از فیلدها را به صورت جدا شده با کاما دریافت می‌کند تا مشخص کند کدام فیلدها در پاسخ گنجانده شوند:\n\n```\nGET /students?fields=id,name,age,class\n```\n\n- پشتیبانی از صفحه‌بندی (pagination)، فیلتر کردن (filtering) و مرتب‌سازی (sorting) نیازی نیست از ابتدا برای همه منابع (resourceها) فعال باشد. منابعی که این قابلیت را دارند، باید به طور مستند (از طریق Document) مشخص شوند.\n\n\u003ca name=\"api-security\"\u003e\u003c/a\u003e\n\n### 9.2 امنیت ای‌پی‌آی/API security\n\nاین موارد برخی از بهترین روش‌های امنیتی پایه هستند:\n\n- از احراز هویت پایه (Basic Authentication) استفاده نکنید، مگر اینکه از یک اتصال امن (HTTPS) استفاده کنید. توکن‌های احراز هویت نباید در URL منتقل شوند: `GET /users/123?token=asdf....`\n\n_چرا:_\n\n\u003e زیرا توکن یا شناسه کاربری و رمز عبور به صورت متن ساده (clear text) در شبکه ارسال می‌شوند (اگرچه به صورت Base64 کدگذاری شده است، اما Base64 یک کدگذاری برگشت‌پذیر است). بنابراین، روش احراز هویت پایه ایمن نیست. [توضیحات بیشتر ...](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication)\n\n- توکن‌ها باید با استفاده از هدر Authorization در هر درخواست منتقل شوند: `Authorization: Bearer xxxxxx, Extra yyyyy`.\n- کدهای Authorization باید مدت‌زمان کوتاهی معتبر باشند.\n- هرگونه درخواست بدون TLS را رد کنید. به درخواست‌های HTTP (بدون TSL) پاسخ ندهید تا از تبادل داده‌های ناامن جلوگیری شود. اگر پاسخ می‌دهید، از کد وضعیت `403 Forbidden` استفاده کنید.\n- استفاده از نرخ محدودیت (Rate Limiting) را در نظر بگیرید.\n\n_چرا:_\n\n\u003e برای حفاظت از API در برابر تهدیدات بات‌هایی که ممکن است هزاران بار در ساعت API شما را فراخوانی می‌کنند. باید محدودیت نرخ (rate limit) را از همان مراحل اولیه پیاده‌سازی مد نظر قرار دهید.\n\n- تنظیم مناسب هدرهای HTTP می‌تواند به ایمن‌سازی برنامه وب شما کمک کند. [توضیحات بیشتر ...](https://github.com/helmetjs/helmet)\n- API شما باید داده‌های دریافت‌شده را به فرم استانداردشان تبدیل کند یا آن‌ها را رد کند. در صورت وجود داده‌های نادرست یا ناقص، کد وضعیت 400 Bad Request را همراه با جزئیات خطا در پاسخ بازگردانید.\n- تمام داده‌های مبادله‌شده با REST API باید توسط خود API اعتبارسنجی شوند.\n- JSON خود را سریالایز (Serialize) کنید.\n\n_چرا:_\n\n\u003e یکی از نگرانی‌های اصلی کار با JSON، جلوگیری از اجرای کدهای جاوااسکریپت دلخواه از remote در مرورگر است... یا اگر از node.js در سمت سرور استفاده می‌کنید. بسیار مهم و حیاتی است که از یک سریالایزر JSON مناسب استفاده کنید تا داده‌های ورودی کاربر به درستی کدگذاری شوند و از اجرای داده‌های ورودی کاربر در مرورگر جلوگیری شود.\n\n- نوع محتوا (Content-Type) را اعتبارسنجی کنید و بیشتر از `application/*json` (هدر Content-Type) استفاده کنید.\n\n_چرا:_\n\n\u003e به عنوان مثال، پذیرش نوع `application/x-www-form-urlencoded` به مهاجم اجازه می‌دهد یک فرم ایجاد کند و یک درخواست POST ساده ارسال کند. سرور هرگز نباید نوع محتوا (Content-Type) را فرض کند. عدم وجود هدر Content-Type یا وجود یک Content-Type غیرمنتظره باید منجر به رد محتوا توسط سرور با یک پاسخ `4XX` شود.\n\n- پروژه API Security Checklist را بررسی کنید. [توضیحات بیشتر ...](https://github.com/shieldfy/API-Security-Checklist)\n\n\u003ca name=\"api-documentation\"\u003e\u003c/a\u003e\n\n### 9.3 مستندسازی ای‌پی‌آی/API documentation\n\n- بخش `API Reference` را در [README.md template](./README.sample.md) برای API پر کنید.\n- روش‌های احراز هویت API را با یک نمونه کد توضیح دهید.\n- ساختار URL (فقط path بدون root URL) را به همراه نوع درخواست (Method) شرح دهید.\n\nبرای هر Endpoint، موارد زیر را توضیح دهید:\n\n- اگر پارامترهای URL وجود دارند، آن‌ها را مطابق با نام ذکر شده در بخش URL مشخص کنید:\n\n```\nRequired: id=[integer]\nOptional: photo_id=[alphanumeric]\n```\n\n- اگر نوع درخواست POST است، نمونه‌های کاربردی ارائه دهید. قوانین پارامترهای URL در اینجا نیز اعمال می‌شوند. این بخش را به دو دسته اختیاری و الزامی تقسیم کنید.\n- پاسخ موفقیت‌آمیز (Success Response)، کد وضعیت (Status Code) چه باید باشد و آیا داده‌ای در پاسخ بازگردانده می‌شود یا خیر؟ این اطلاعات زمانی مفید است که کاربران نیاز دارند بدانند چه چیزی از پاسخ دریافت خواهند کرد:\n\n```\nCode: 200\nContent: { id : 12 }\n```\n\n- پاسخ خطا (Error Response)، بیشتر endpointها ممکن است به روش‌های مختلفی شکست بخورند. از دسترسی غیرمجاز گرفته تا پارامترهای اشتباه و غیره. تمامی این موارد باید در این بخش لیست شوند. ممکن است تکراری به نظر برسد، اما از ایجاد فرضیات جلوگیری می‌کند. به عنوان مثال:\n\n```json\n{\n\t\"code\": 401,\n\t\"message\": \"Authentication failed\",\n\t\"description\": \"Invalid username or password\"\n}\n```\n\n- از ابزارهای طراحی API استفاده کنید؛ ابزارهای متن‌باز زیادی برای مستندسازی خوب وجود دارند، مانند [API Blueprint](https://apiblueprint.org/) و [Swagger](https://swagger.io/).\n\n\u003ca name=\"a11y\"\u003e\u003c/a\u003e\n\n## 10. دسترس‌پذیری/Accessibility ([a11y](https://www.a11yproject.com/))\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/accessibility.png\" alt=\"Accessibility\" width=\"128\" height=\"128\"\u003e\n\u003c/p\u003e\n\n### 10.1 پیاده‌سازی روش‌های دسترسی‌پذیری\n\nبرای اطمینان از حفظ سطح مشخصی از دسترسی‌پذیری، **از ابتدای پروژه خود** مراحل زیر را انجام دهید:\n\n_چرا:_\n\n\u003e محتوای وب [به‌طور پیش‌فرض دسترسی‌پذیر](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML)است. ما این ویژگی را زمانی به خطر می‌اندازیم که امکانات پیچیده ایجاد می‌کنیم. در نظر گرفتن دسترسی‌پذیری از ابتدا بسیار آسان‌تر از بازپیاده‌سازی این ویژگی‌ها در آینده است تا تأثیر آن را کاهش دهیم.\n\n- با استفاده از ابزارهایی مانند [lighthouse](https://developers.google.com/web/tools/lighthouse#devtools) برای [دسترسی‌پذیری](https://web.dev/lighthouse-accessibility/) یا افزونه [axe DevTools](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)برنامه‌ریزی‌هایی را جهت انجام ممیزی‌های منظم انجام دهید. بر اساس نیازهای پروژه خود، بر روی یک امتیاز حداقلی توافق کنید. امتیازدهی در این ابزارها بر اساس [ارزیابی تأثیر کاربر در axe](https://github.com/dequelabs/axe-core/blob/develop/doc/rule-descriptions.md#wcag-21-level-a--aa-rules) می‌باشد.\n\n\u003e **نکته:** [برخی بررسی‌های مهم](https://web.dev/lighthouse-accessibility/#additional-items-to-manually-check) باید به‌صورت دستی انجام شوند، مانند ترتیب منطقی تب‌ها. ابزارهای فوق این موارد را به عنوان تست‌های دستی یا راهنمایی‌شده در کنار نتایج خودکار فهرست می‌کنند. در axe باید نتایج خودکار خود را ذخیره کنید تا این موارد را مشاهده کنید.\n\n- یک Linter مرتبط با دسترس‌پذیری نصب کنید:\n  - در ری‌اکت: [eslint-plugin-jsx-a11y](https://www.npmjs.com/package/eslint-plugin-jsx-a11y)\n  - در انگولار: [Angular Codelyzer](https://github.com/mgechev/codelyzer)\n  - در ویو: [eslint-plugin-vuejs-accessibility](https://github.com/vue-a11y/eslint-plugin-vuejs-accessibility)\n\n_چرا:_\n\n\u003e یک لینتر به‌طور خودکار بررسی می‌کند که سطح پایه‌ای از دسترسی‌پذیری در پروژه شما رعایت شده است و راه‌اندازی آن نسبتاً آسان است.\n\n- با استفاده از [axe-core](https://www.youtube.com/watch?v=-n5Ul7WPc3Y\u0026list=PLMlWGnpsViOMt24a-Y_dybv68H-kj6Un6\u0026t=1649s) یا ابزارهای مشابه، تست‌های دسترسی‌پذیری را راه‌اندازی و اجرا کنید.\n- اگر از Storybook استفاده می‌کنید، این [راهنما](https://storybook.js.org/blog/accessibility-testing-with-storybook/) را دنبال کنید.\n\n_چرا:_\n\n\u003e گنجاندن بررسی‌های دسترس‌پذیری در تست‌ها به شما کمک می‌کند تا هر تغییری که بر دسترس‌پذیری پروژه و امتیاز ممیزی تأثیر می‌گذارد، شناسایی کنید.\n\n- از یک دیزان سیستم دسترسی‌پذیر مانند [React Spectrum](https://react-spectrum.adobe.com/react-spectrum/) یا [Material Design](https://material.io/design) استفاده کنید.\n\n_چرا:_\n\n\u003e این کامپوننت‌ها به صورت پیش‌فرض از سطح بالایی از دسترس‌پذیری برخوردار هستند.\n\n### 10.2 برخی از قوانین پایه دسترس‌پذیری که باید به پروژه خود اضافه کنید:\n\n- اطمینان حاصل کنید که نام لینک‌ها دسترس‌پذیر هستند. از aria-label برای توصیف لینک‌ها استفاده کنید.\n\n_چرا:_\n\n\u003e لینک‌هایی که غیرقابل دسترس می‌باشند، برای دسترس‌پذیری موانعی ایجاد می‌کنند.\n\n- اطمینان حاصل کنید که لیست‌ها به‌درستی ساختاربندی شده باشند و عناصر لیست به صورت معنایی استفاده شده‌اند.\n\n_چرا:_\n\n\u003e لیست‌ها باید دارای عناصر والد و عناصر فرزند باشند تا معتبر باشند. صفحه‌خوان‌ها (Screen Readers) به کاربران اطلاع می‌دهند که وقتی به یک لیست می‌رسند، لیست شامل چند آیتم است.\n\n- اطمینان حاصل کنید که ترتیب سرفصل‌ها (Heading Order) از نظر معنایی صحیح است.\n\n_چرا:_\n\n\u003e سرفصل‌ها ساختار صفحه را منتقل می‌کنند. هنگامی که به درستی اعمال شوند، پیمایش صفحه آسان‌تر می‌شود.\n\n- اطمینان حاصل کنید که عناصر متنی دارای کنتراست کافی با پس‌زمینه‌ی صفحه هستند.\n\n_چرا:_\n\n\u003e برخی افراد با بینایی کم، کنتراست پایین را تجربه می‌کنند؛ به این معنی که تفاوت زیادی بین مناطق روشن و تاریک وجود ندارد. همه چیز تقریباً با همان میزان روشنایی ظاهر می‌شود، که تشخیص خطوط، حاشیه‌ها، لبه‌ها و جزئیات را دشوار می‌کند. متنی که از نظر روشنایی بسیار نزدیک به پس‌زمینه باشد، ممکن است سخت خوانده شود.\n\n- برای تصاویر، متن جایگزین (Alt Text) ارائه دهید.\n\n_چرا:_\n\n\u003e صفحه‌خوان‌ها نمی‌توانند تصاویر را به کلماتی تبدیل کنند که برای کاربر خوانده شود، حتی اگر تصویر فقط شامل متن باشد. در نتیجه، ضروری است که تصاویر دارای متن جایگزین کوتاه و توصیفی باشند تا کاربران صفحه‌خوان به‌وضوح محتوای تصویر و هدف آن را درک کنند.\n\nقوانین بیشتری درباره دسترس‌پذیری را می‌توانید [اینجا](https://dequeuniversity.com/rules/axe) پیدا کنید.\n\n\u003ca name=\"licensing\"\u003e\u003c/a\u003e\n\n## 11. مجوزدهی/Licensing\n\n\u003cp align=\"right\"\u003e\n  \u003cimg src=\"/images/licensing.png\" alt=\"Licensing\" width=\"135\" height=\"135\"\u003e\n\u003c/p\u003e\n\nاطمینان حاصل کنید که از منابعی استفاده می‌کنید که حق استفاده از آن‌ها را دارید. اگر از کتابخانه‌ها استفاده می‌کنید، به مجوزهای MIT، Apache یا BSD توجه کنید، اما اگر این کتابخانه‌ها را تغییر می‌دهید، حتماً جزئیات مجوز را بررسی کنید. استفاده از تصاویر و ویدئوهای دارای حق کپی‌رایت (Copyrighted) ممکن است مشکلات قانونی ایجاد کند.\n\n---\n\nمنابع:\n[RisingStack Engineering](https://blog.risingstack.com/),\n[Mozilla Developer Network](https://developer.mozilla.org/),\n[Heroku Dev Center](https://devcenter.heroku.com),\n[Airbnb/javascript](https://github.com/airbnb/javascript),\n[Atlassian Git tutorials](https://www.atlassian.com/git/tutorials),\n[Apigee](https://apigee.com/about/blog),\n[Wishtack](https://blog.wishtack.com)\n\nIcons by [icons8](https://icons8.com/)\n","funding_links":[],"categories":["JavaScript","Software Engineering Best Practices","clean code","Learning Resources","Guidelines","Programming Languages","Javascript","Style Guides \u0026 best practices","javascript","前端开发框架及项目","best-practices","前端/博客","Platforms","github-repos","Development"],"sub_categories":["JavaScript","其他_文本生成、文本对话","学习资源","Other"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felsewhencode%2Fproject-guidelines","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felsewhencode%2Fproject-guidelines","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felsewhencode%2Fproject-guidelines/lists"}