بلاگ تورج خطیبی

ایجاد ماژول‌های جاواسکریپت

June 02, 2018

چند وقت پیش نیاز بود یه ماژول جاواسکریپتی برای تبدیل متن عربی به فارسی بنویسم، که نتیجه‌ش شد arabic-to-persian. ماژول فوق‌العاده ساده‌ایه، ولی چند تا چیز خوب باهاش یاد گرفتم، که چون دوست دارم کامیت‌های ماژول بعدیم مرتب‌تر باشه، باید ترتیب کارها رو برای خودم مستند می‌کردم. پس شد آنچه شد.

دور زدن config ها

در فرآیند توسعه (خواه ماژول، خواه یک اپلیکیشن) ابزارهایی داریم تحت عنوان task runner که برای خودکارسازی کارهای روتین، حوصله‌سربر و از زیردست‌دررو استفاده می‌شن. عموما این تسک‌رانرها با جاواسکریپت نوشته شدند، ولی می‌تونید در هر پروژه‌ای با هر زبان و فریم‌ورکی ازشون استفاده کنید. grunt و gulp نمونه‌ای از این ابزارها هستند. با اومدن node و npm نقش این ابزارها کمتر شد، چرا که خیلی از این کارها رو npm scripts هم برای توسعه‌دهنده‌ها انجام می‌ده. اما این کارهای روتین مثلا یعنی چه کارهایی؟

  • اجرای تست‌ها قبل از هر کامیت
  • تهیه گزارش تست‌ها
  • بررسی و یکپارچه‌سازی استایل کدها قبل از هر کامیت
  • یکپارچه‌سازی عنوان و متن کامیت‌ها
  • ساخت نسخه‌های مختلف برای پلتفرم‌های مختلف
  • بهینه‌سازی نسخه‌ها
  • انتشار نسخه‌ها
  • تهیه مستندات
  • انتشار مستندات
  • تعیین شماره نسخه بعدی نرم‌افزار طبق semver
  • ضمیمه تغییرات هر نسخه به همراه commit مربوطه، issue مربوطه و …
  • و الی ماشالله

etc

خبر بد اینه که باید به task runner بفهمونید چه کارهایی انجام بده و این خودش مستلزم کانفیگ پلاگین‌ها و ابزارهای دیگه‌ایه که اگر نگم انرژی‌ای که ازتون می‌گیره بیشتر از توسعه خود ماژول نیست، کم‌تر هم نیست.

و خبر خوب اینکه typescript-library-starter این کانفیگ‌ها رو براتون انجام داده. من در ادامه پست با این boilerplate کار می‌کنم، تا با هم کانفیگ‌ها رو دور بزنیم، و روی ابزارهای مورد نیازمون تمرکز کنیم. طبیعتا وقتی کاربرد این ابزارها رو یاد بگیرید، دیگه محدود به این boilerplate نخواهید بود و می‌تونید بر حسب نیاز از این ابزارها در پروژه‌های دیگه استفاده بکنید یا نکنید.

سلب مسئولیت: کانفیگ‌ها در جاواسکریپت به سمت تموم شدن میل می‌کنن، ولی تموم نمی‌شن.

اما چرا تایپ‌اسکریپت؟ مگه عنوان پست ایجاد ماژول‌های جاواسکریپت نبود؟ خب این سه تا علت داره:

  • اول اینکه خدعه کردم.

  • دوم اینکه بنده از این جاواسکریپت خیلی بدم میاد.

  • و در آخر اینکه خب تایپ‌اسکریپت همون جاواسکریپت سروسامون‌یافته‌تر هست. منتها به خاطر استاتیک‌تایپ بودنش IDE ها می‌تونن با نمایش پیشنهادها و نوع پارامترهای مجاز، در روند توسعه کمک‌تون کنند، که خود این مسئله منجر به کاهش خطاها در زمان اجرا، ساختار منطقی‌تر، کدهای خواناتر و نگهداری ساده‌تر میشه. جدای از تمام برتری‌های فنی، برنامه‌نویسی با تایپ‌اسکریپت لذت‌بخش‌تر هم هست. پس اگر یک هفته برای یادگیری تایپ‌اسکریپت کنار بذارید، به خودتون، سایر مشارکت‌کننده‌ها، توسعه‌دهنده‌هایی که از کتابخا‌نه‌تون استفاده می‌کنند، و جامعه بشریت کمک بزرگی کردید.

راه‌اندازی پروژه

  • اول به اینجا برید و یه مخزن جدید بسازید. بهتره نام مخزن بصورت kebab-case.js باشه.

  • دستورهای زیر رو به ترتیب اجرا کنید، و وقتی ازتون نام پروژه پرسیده شد، پسوند js رو وارد نکنید:

git clone https://github.com/alexjoverm/typescript-library-starter.git YOUR_REPOSITORY
cd YOUR_REPOSITORY
npm install
git remote set-url origin https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git
  • الان می‌تونید اولین کامیت خودتون رو ثبت کنید. ولی با یه راه باحال‌تر اینکار رو انجام بدید:
git add .
npm run commit

سوال اول مربوط به نوع تغییرات هست.

سوال دوم از شما می‌خواد مشخص کنید که این تغییرات مرتبط با کدوم فرآیند، پلتفرم، وابستگی،‌ کامپوننت یا … پروژه‌ست.

سوال سوم و چهارم به ترتیب شرح خلاصه و مفصل تغییرات شماست.

سوال پنجم مربوط به breaking change های پروژه‌ست. تغییراتی که در این کامیت منجر به ناسازگاری با نسخه‌های قبلی شده‌اند رو شرح بدید. اما اگر backward compatible بود جوابش رو ندید.

و در سوال آخر اگر این کامیت برای بستن issue خاصی ثبت می‌شه شماره issue مربوطه رو با فرمت مثلا #64 ذکر کنید.

حالا ببینید محتوای کامیت تولید شده چی هست:

git log

از این به بعد کامیت‌های شما و بقیه مشارکت‌کننده‌ها استایل مشترکی خواهند داشت. و شاید باورتون نشه، ولی این کمترین کاری هست که commitizen داره براتون انجام می‌ده. با وظیفه مهم‌ترش وقتی آشنا می‌شید، که semantic-release آماده به کار شده باشه. پس اندکی صبر، اون قسمتش نزدیکست.

  • semantic-release کامیت‌های منتشرنشده پروژه شما رو می‌خونه، طبق مقادیری که ‍‍commitizen به کمک conventional-changelog به متن این کامیت‌ها اضافه کرده، تغییرات major و manor و patch رو تشخیص می‌ده، گزارش تغییرات نسخه جدید رو آماده می‌کنه، و در آخر نتیجه رو نشونتون می‌ده.

    این بود وظیفه مهم‌تر commitizen.

setup

از اونجایی که برای استفاده از semantic-release و انتشار مستندات باید آدرس مخزن پروژه تعریف شده باشه، فایل package.json رو باز کنید و در قسمت git.url آدرس https://github.com/YOUR_USERNAME/YOUR_REPOSITORY.git رو وارد کنید.

اگر از ویندوز استفاده می‌کنید، قبل از دستورهای بعدی این دستور رو اجرا کنید: (من امکان تست این مورد رو نداشتم و صرفا چون در مستندات ذکر شده بود، این رو اضافه کردم)

npm install --global --production windows-build-tools

دستورات زیر رو به ترتیب اجرا کنید (حتی شما یونیکسی عزیز)، و وقتی ازتون پرسید travis.yml رو ایجاد کنه یا نه، NO رو انتخاب کنید، چون زحمت کانفیگ این فایل از قبل کشیده شده.

npm run semantic-release-prepare
npm install -g semantic-release-cli
semantic-release-cli setup

با دستور اول دو تا git hook جدید به لیست اسکریپت‌های package.json اضافه می‌شن. prepush که قبل از هر پوش صحت build و پوشش تست‌ها و استایل کدها رو بررسی می‌کنه تا ضمانت کنه تغییرات شما منجر به fail شدن فرآیند ساخت نمی‌شه، و commitmsg که به شما اجازه اجرای git commit رو نمی‌ده و به جاش npm run commit رو بهتون پیشنهاد می‌ده.

  • Travis CI ابزاری برای خودکارسازی فرآیندهای تست، ساخت و انتشار پروژه هست. برای فعال‌سازی CI پروژه اینجا برید و سوییچ مخزن‌تون رو روشن کنید.

    بعد به اینجا برید و یک توکن جدید ایجاد کنید. دقت کنید که در قسمت Select scopes حتما repo و مشتقاتش انتخاب شده باشند. این توکن دیگه به شما نشون داده نمی‌شه، پس در حفظ و نگهداری توکن کوشا باشید و اون رو در جایی امن نگه‌داری کنید. طبیعتا این جای امن داخل پروژه نخواهد بود.

    برای فعالسازی semantic-release به یه توکن npm هم نیاز دارید. اگر هنوز عضو سایت npm نیستید از اینجا می‌تونید ثبت‌نام کنید. بعد دستور زیر رو اجرا کنید و برای توکن ایجاد شده، همون مواردی که برای توکن گیت‌هاب اشاره کردم رو عینا رعایت کنید.

npm token create

بعد به آدرس https://travis-ci.org/YOUR_USERNAME/YOUR_REPOSITORY/settings برید و در قسمت Environment Variables مقدار توکن گیت‌هاب رو با عنوان GH_TOKEN به لیست متغیرها اضافه کنید. همین کار رو مجددا برای توکن npm و این‌بار با عنوان NPM_TOKEN تکرار کنید. حواستون باشه سوییچ ‍‍‍Display value in build log در هر دو مورد خاموش باشه، چرا که درغیراینصورت اون حفظ و نگه‌داری‌ای که بهش اشاره شد به طور کامل نقض می‌شه.

از این به بعد با هربار push و pull request، تراویس وظایفی که در travis.yml تعریف شده رو براتون انجام می‌ده، کارهایی مثل تست و به‌روزرسانی coverage و مستندات پروژه. اگر نیاز بود وظایف دیگه‌ای هم به این لیست اضافه شه، به مستندات تراویس مراجعه کنید.

برای اینکه نتیجه آخرین اجرای CI هم همیشه در معرض دید باشه، بهتره که برچسب build رو به README.md پروژه اضافه کنید:

# PROJECT_NAME

[![Build Status](https://travis-ci.org/YOUR_USERNAME/YOUR_REPOSITORY.svg?branch=master)](https://travis-ci.org/YOUR_USERNAME/YOUR_REPOSITORY)
  • coveralls هم ابزاری برای رصد کردن کیفیت کلی پروژه هست، و برای پروژه‌های متن‌باز رایگانه. اگر هنوز عضو سایتش نیستید، از اینجا می‌تونید ثبت‌نام کنید.

    برای فعال‌سازی coverage پروژه اینجا برید و سوییچ مخزن نگهدارنده پروژه رو روشن کنید.

    و در آخر به برچسب build که در قدم قبلی به README.md اضافه کردید، برچسب coverage رو هم اضافه کنید:

[![Coverage Status](https://coveralls.io/repos/github/YOUR_USERNAME/YOUR_REPOSITORY/badge.svg?branch=master)](https://coveralls.io/github/YOUR_USERNAME/YOUR_REPOSITORY?branch=master)
  • اگر به ویژگی‌های فانکشنال مثل Promise در کتابخانه‌تون نیاز داشتید، می‌تونید از polyfill هایی مثل core-js استفاده کنید. برای نصب دستور زیر رو اجرا کنید:
npm i -D core-js

و برای استفاده بالای entry script (فایلی که برنامه از اون شروع می‌شه) کتابخانه، polyfill های مورد نیازتون رو import کنید:

import "core-js/fn/array/find"
import "core-js/fn/string/includes"
import "core-js/fn/promise"

چند تا نکته

  • به آدرس https://YOUR_USERNAME.github.io/YOUR_REPOSITORY برید و از دیدن مستنداتی که typedoc براتون ایجاد کرده لذت ببرید.

  • اگر کتابخانه شما وابسته به ماژولی از نوع peerDependeny (ماژولی که لازم نیست در خروجی نهایی import بشه) بود، فایل rollup.config.js رو باز کنید و نام اون ماژول رو به آرایه external اضافه کنید.

  • تا می‌تونید از نصب وابستگی‌های پروژه به صورت global پرهیز کنید، و کامندهای مرتبط با هر ماژول رو به npm scripts اضافه کنید، اینجوری مشارکت برای سایر توسعه‌دهنده‌ها راحت‌تر می‌شه.

انتشار کتابخانه

npm publish

publish


Kyle Mathews

تورج خطیبی هستم، توسعه‌دهنده نرم‌افزار، مشتاق به یادگیری استانداردها، ناچار به یادگیری ابزارها، و متنفر از یادگیری تنظیمات.