<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مسیح جهانگیری</title>
        <link>https://virgool.io/feed/@masihjahangiri</link>
        <description>Front-End | Full-Stack Developer</description>
        <language>fa</language>
        <pubDate>2026-06-17 02:45:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/5701/avatar/SufnSC.png?height=120&amp;width=120</url>
            <title>مسیح جهانگیری</title>
            <link>https://virgool.io/@masihjahangiri</link>
        </image>

                    <item>
                <title>از تشخیص کلیک خارج از کامپوننت تا Type Assertions در تایپ‌اسکریپت</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D8%B2-%D8%AA%D8%B4%D8%AE%DB%8C%D8%B5-%DA%A9%D9%84%DB%8C%DA%A9-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA-%D8%AA%D8%A7-type-assertions-%D8%AF%D8%B1-%D8%AA%D8%A7%DB%8C%D9%BE%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-c3c0n1znrykd</link>
                <description>گاهی اوقات پیش میاد که باید بیشتر به Typescript بفهمونید که تایپ متغییرتون چیه و همین‌جوری نمیفهمه و با ارور کامپایلر مواجه می‌شید. اینجاست که Type Assertions به کمک شما میاد و مشکلتون را حل میکنه. Type Assertions از ورژن 1.6 به بعد تایپ‌اسکریپت در دسترسه و می‌‌تونید ازش استفاده کنید.قرار بود با react.js یه کامپوننت طراحی کنم که یک حالت مهم در اون کامپوننت زمانی اتفاق می‌افتاد که خارج از کامپوننت کلیک می‌شد. کلا تشخیص اینکه خارج از کامپوننت کلیک شده یه موضوع پر بحث در react.js هست. برای حل این چالش روش های مختلفی وجود داره حتی یه پکیج پرطرفدار برای آن ساخته شده است. من با یکمی تحقیق فهمیدم که بهترین و سریع‌ترین روش ممکن استفاده از تکنیک فوکوس/بلور است. چون هیچگونه EventListenerای به کامپومننت اضافه نمی‌کنه بالاترین پرفورمنس را به ما می‌ده.مشکل اینجا به وجود اومد که من داخل کامپوننتم از یه تگی استفاده کرده بودم که position آن absolute و اندازه‌ی آن بزرگتر اندازه‌ی تگ پدرش (parent) بود و بخاطر ساز و کار مرورگر (یا باگ) زمانی که روی آن تگ absolute کلیک می‌شد بجای اینکه تگ پدرش focus شود تگ پدرش blur می‌شد. با یکمی سرچ فهمیدم که باید یه فیلتر سر راه  تگ پدر (parent) بزارم تا مشکلش حل شود.اینجا دیگه مشکلم حل شده بود و به راحتی می‌تونستم کلیک کردن خارج از کامپوننت را تشخیص بدم. ولی تایپ‌اسکریپت یه ارور می‌داد که خیلی رو مخ بود:مشکل اینه که تابع event.currentTarget.contains() یه آرگمان می‌پذیره که باید از نوع Node باشه ولی event.relatedTarget که به عنوان ورودی به تابع داده‌ایم تایپش EventTarget است. چون EventTarget  یک تایپ عمومی است و Node یکی از زیر مجموعه های آن است.Basically EventTarget is the most general type, of which Element is a subtype, and HTMLElement is a subtype of that. If you get back a thing from the DOM, we generally have no idea which it is, and you should add a type assertion to &quot;add in&quot; the specific external knowledge that you have about the structure of your particular DOM layout.It&#x27;s possible, for example, that the .target of an event is not an Element (you can add event listeners to XMLHttpRequest, for example, and XMLHttpRequest does not have a getBoundingClientRect method).ولی اینجا مطمئن هستیم که EventTarget  از نوع Element یا همون Node هست. بنابراین باید به صورت صریح به typescript بفهمونیم اینجا EventTarget از نوع Node است.Type assertionsبا استفاده از Type assertions می‌تونیم به تایپ‌اسکریپت به صورت صریح اعلام کنیم که من مطئمنم تایپ متغییر اینه و بهمون ارور نده لطفا. مثل Type Casting در بقیه‌ی زبانهای برنامه‌نویسی با این تفاوت که در run-time هیچ اتفاقی نمی‌افته. سینتکس Type assertions به صورت زیر است:&lt;Type&gt; UnaryExpressionچون سینتکس بالا با JSX (و TSX) تداخل داره می‌تونیم از سینتکس جایگزین زیر استفاده کنیم:UnaryExpression as Typeاگه ما از Type assertions استفاده کنیم و به صورت صریح اعلام کنیم که تایپ event.relatedTarget از نوع Node است کامپوننت نهایی ما به صورت زیر می‌شود و هیچگونه اروری دریافت نمی‌کنیم ?</description>
                <category>مسیح جهانگیری</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Thu, 06 Feb 2020 18:11:21 +0330</pubDate>
            </item>
                    <item>
                <title>کلید موفقیت در بالا بردن پرفورمنس اپ‌های تحت وب</title>
                <link>https://virgool.io/iran-react-community/success-key-enhancing-web-performance-usuhlalwbykq</link>
                <description>یکی از سخت‌ترین کارای دنیا بالا بردن پرفورمنس اپلیکیشن هاست. بخصوص اگه اون اپلیکیشن تحت وب باشه. دلیلش اینه که پرفورمنس یک وب‌اپ شامل 3 قسمت میشه: 1- پرفورمنس بارگذاری 2- پرفورمنس رندرینگ 3- پرفورمنس زمان اجرا.کلید موفقیت در بالا بردن پرفورمنس وب‌اپ‌هادو مورد اول برای سئو بشدت مهمه ولی مورد آخر فقط برای کاربرانتان مهمه چون موتور های جستجوگر نمی‌تونن به درستی مورد آخر را بسنجن. ولی حتی اگه سئو برای وب‌اپ شما اهمیتی نداره، سعی کنید هر سه مورد را رعایت کنید چون هر سه مورد بالا به بهبود UX وب‌اپ شما کمک می‌کنه.پرفورمنس زمان اجرا به اون الگوریتم هایی که استفاده می‌کنید بستگی داره و اگه یکم الگوریتم بدونید و تجربه‌ی برنامه نویسی داشته باشید، معمولا به مشکل بر ‌نمی‌خورید. ولی مشکل اصلی دو مورد اوله، همون دو مورد که روی هم سئو تاثیر داره.اگه بخواییم تو زمینه‌ی پرفورمنس کمال گرا باشیم احتمالا یا نامید می‌شیم یا دیوونه! چون اگه 10 سال هم بخوایید صرفا روی پرفورمنس کار کنید هنوز جای کار هست. هم مقالات و نکات بسیار زیادی تو این زمینه وجود داره و هم پیاده سازی همشون با هم خیلی کار سخت و پیچیده‌ایه.راه حل چیه؟ خیلی ساده‌س: قانون 20 80با انجام دادن 20 درصد کارا 80 درصد پرفورمنس وب‌اپتون را بهبود ببخشید. اون 20 درصد چیه؟کاهش سایز باندل های جاوااسکریپتبله اون 20 درصد &quot;کاهش حجم فایل‌های JS&quot;  است. چرا اینقدر سایز فایل های JS مهم و تاثیر گذاره؟ چون فایل های JS با بقیه فایل‌ها فرق داره و چند جانبه می‌تونه پرفورمنس اپلیکشین شما را تحت تاثیر قرار بده.بزارید یه فایل جاوااسکریپت 170 کیلوبایتی را با یه فایل تصویر 170 کیلوبایتی مقایسه کنیم:مقایسه دو فایل 170 کیلوبایتی js , jpgهمون جوری که تو تصویر بالا می‌بینید 170 کیلوبایت فایل JS حدود 6.4 ثانیه طول می‌کشه تا اجرا بشه ولی فایل JPG حدود 3.4 ثانیه. چون فایل JS اول باید decompress شه و بعد parse بشه و بعد compile بشه و در آخر execute بشه. و این خیلی برای مرورگر هزینه داره.یه چندتا نکته هست که اگه رعایت کنید تا حد خوبی می‌تونید سایز باندل JS را کم کنید.محتویات فایل JS را به غیر فایل JS تبدیل کنیدبا این کار از دو جنبه سود می‌برید یکی اینکه سایز باندل JS کم می‌شه و طبق تصویر بالا پرفورمنس افزایش پیدا می‌کنه و دوم اینکه می‌تونید اون فایل‌هایی که از محتویات JS خارج کردید را داخل مرورگر cache کنید و بازم سرعت لود اپ را افزایش بدید. خوب حالا چه محتویاتی را می‌تونیم از فایل js خارج کنیم؟ دو نمونه‌ی رایج را در زیر می‌تونید ببینید:یکی از کارایی که معمولا فرانت‌اند دولوپرها انجام می‌ن اینه که فایل های SVG را به کامپوننت های جاوااسکریپتی تبدیل می‌کنن که خیلی راحت بتونن property های اونو با css تغییر بدن و راحت بتونن رنگش را با css عوض کنن. اکثر مواقع ما نیاز به این کار نداریم و می‌تونیم از همون فایل SVG استفاده کنیم و property های اونو به صورت static تعریف کنیم. اینجوری حجم باندل js ما بشدت کاهش پیدا می‌کنه.یکی از trend های این روزای فرانت‌اند CSS-in-JS است. چیزی که DX یا developer experience خوبی داره ولی UX خیلی بدی ارائه میده. یعنی خودتو راحت می‌کنی و کاربر را ناراحت. چرا؟ چون اولا تمام CSSها تبدیل به JS می‌شن که خوب طبق حرفایی که بالا زدم خیلی بده و دوم اینکه css‌ها هنگام run-time بر اساس state های موجود ساخته می‌شن که باعث کندی اپ در زمان اجرا میشه. البته چند مورد CSS-in-JS استثنا داریم که css‌ها را از JS اکستراکت کرده و در فایل CSS جدا ذخیره می‌کنن که معروف ترین اون linaria است که توسط یکی از نوابغ دنیای Front-End به نام Satyajit Sahoo خلق شده. علاوه بر linaria برای حل این مشکل می‌تونید از همون روش سنتی  css/sass/less/scss استفاده کنید.و...تکنیک Code Splittingلازم نیست کاربر قسمت هایی از برنامه‌تون که بهش نیاز نداره را دانلود کنه. اگه به componentای نیاز داشت js اونو لود کنید. مثلا اگه کاربر خواست login کنه و  component لوگین شما به صورت یه modal است، هر زمان به اون نیاز داشت اونو براش دانلود کنید.ممکنه براتون سوال پیش که اگه تعداد bundleها زیاد بشه، تعداد request‌ها برای دانلود تمامی bundle‌ها افزایش پیدا می‌کنه و این می‌تونه به سرعت لود سایت صدمه بزنه. این نگرانی زمانی درسته که شما از http1 یا http1.1 استفاده می‌کنید ولی اگه از http2 استفاده می‌کنید اصلا نباید نگرانش باشید و توصیه می‌شه که حتما از http2 استفاده کنید. یه اصطلاحی داریم به نام Aggressive Code Splitting که میگه خیلی بیرحمانه bundle ها را به قسمت های کوچکتری تقسیم کن. حتی یه پلاگین وب‌پک هم به نام AggressiveSplittingPlugin وجود داره که این کار را برای ما براحتی انجام میده.یه پترن خوب به نام Progressive Bootstrapping برای code splitting وجود داره که ایده‌‌ش مال آقای Paul Lewis هست که در قالب این توئیت توضیح دادن که توصیه می‌کنم حتما بخونیدش. اگه دوست داشتید بیشتر راجب code splitting بدونید می‌تونید ویدیو ارائه من در هفتمین دورهمی جامعه ری‌اکت ایران را ببینید. یا اینکه دایکیومنت رسمی وب‌پک را بخونید.</description>
                <category>مسیح جهانگیری</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Tue, 29 Oct 2019 15:54:01 +0330</pubDate>
            </item>
                    <item>
                <title>حل مشکل Tailwind CSS با CSS Modules</title>
                <link>https://virgool.io/@masihjahangiri/tailwind-with-css-modules-sm7soorb0fge</link>
                <description>زمانی که از فریم‌ورک قدرتمند Tailwind CSS استفاده می‌کنید نیازی ندارید که CSS بنویسید چون هر استایلی بخواهید می‌توانید با استفاده از ترکیب کلاس‌های آن ایجاد کنید. ولی گاهی پیش میاد که به دلایلی نیاز دارید از CSS Modules استفاده کنید. مثلا من یک لایبری به پروژه‌ام اضافه کردم که از CSS Modules استفاده کرده بود و من مجبور شدم پشتیبانی از CSS Modules را به کانفیگ وب‌پک خودم اضافه کنم.Tailwind CSS با CSS Modulesمشکل اینجاست که کلاس های tailwind باید در CSS Modules به عنوان global وارد شوند.متاسفانه دایکیومنت Tailwind CSS هیچ اشاره‌ای به CSS Modules نکرده و فرض را بر این گرفته که شما هیچ نیازی به اون نخواهید داشت. من یکمی سرچ کردم تا ببینم کسی قبلا این دو را با هم استفاده کرده یا نه که به این issue برخوردم ولی چیزی دستگیرم نشد.خودم سعی کردم یه کانفیگی براش بنویسم و دیدم همه چیز به خوبی کار می‌کنه، با خودم گفتم اینو به اشتراک بزارم که اگه کسی این دو را همزمان می‌خواد با هم بکار ببره وقتش برای کانفیگ کردن تلف نشه.ایده اینه که من اومدم از دو لودر مجزا برای فایل های css و scssام استفاده کردم، یکی برای css های گلوبال که بصورت .global.css نام‌گذاری میشن و یکی برای css modules ها که با پسوند های معمولی .css و .scss مشخص می‌شن.اینم تیکه‌ی ساده شده از کانفیگ webpackام:کانفیگ وب‌پکو اینم فایل tailwind.global.cssام:فایل css اصلی و گلوبال پروژه</description>
                <category>مسیح جهانگیری</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Fri, 25 Oct 2019 03:02:22 +0330</pubDate>
            </item>
                    <item>
                <title>چگونه یک پکیج جاوا اسکریپت را هم برای node.js و هم برای browser بنویسیم؟</title>
                <link>https://virgool.io/@masihjahangiri/how-to-write-a-javascript-package-for-both-node-and-the-browser-qjeuh7xgoyip</link>
                <description>خیلی وقت ها پیش میاد که میخواییم یه package جی‌اس بنویسم که هم داخل مرورگر کار کنه و هم داخل node.js. برای دولوپر های فصلی (کسایی که به دلیلی مجور شدن به صورت موقت JS کد بزنن) شاید کمی گیج کننده باشه.پکیج ایزومورفیکیه مشکلی وجود داره! پیاده سازی اون ماژولی که می‌خوایید داخل npm منتشر کنید در دو محیط node.js و browser یکمی متفاوته. این وضعیت مکرر پیش میاد و پیاده سازی درست اون برای هر دو محیط یکمی مشکل سازه. بخصوص زمانی که بخوایید حجم bundle تون در مرورگر بهینه باشه و کد های اضافی node.js را نداشته باشه.یه پکیج ساده جاوا اسکریپت بسازیمیه پکیج خیلی کوچیک قراره بسازیم که یه string به عنوان ورودی بگیره و در خروجی کد شده‌ی اونو به صورت کد شده از نوع base64 برگردونه.در مرورگر یه تابع داخلی داریم به اسم btoa که دقیقا همین کار را انجام میده:در node.js ما تابعی با این نام نداریم و باید با استفاده از Buffer بصورت زیر این کار را انجام بدیم:اگه ما اسم پکیج را بزاریم base64-encode-string و در کدمون ازش استفاده کنیم خروجی اینجوریه:حالا ما باید تشخیص بدیم که آیا کدمون در محیط node.js داره اجرا میشه یا browser. هم webpack و هم Browserify یه متغییر گلوبال به نام process.browser تعریف می‌کنن که اگه کد داخل مرورگر اجرا بشه مقدارش true و اگه داخل node.js اجرا بشه مقدارش false هست. بنابراین اینجوری باید پیاده سازی کنیم:حالا ما یه فایل داریم به نام index.js و زمانی که npm push را بزنیم پکیج میره روی npm ولی با این که کد ما به درستی کار می‌کنه یه مشکل پرفورمنسی بزرگ داره. مشکل اینه که این پکیج ما برای مرورگر خیلی سنگینه چون ما از عناصر داخلی node.js مثل process , Buffer استفاده کردیم، هم webpack و هم Browserify آن عناصر را به باندل اضافه میکنن. یعنی باندل شده‌ی این 9 خط کد 24.7 کیلوبایت (درحالت minify شده) حجم دارد.فیلد browser چگونه به ما کمک می‌کندمن یکمی داخل دایکیومنت های Browserify و Webpack گشتم تا ببینم نکته‌ای ترفندی چیزی هست که بشه این مشکل را حل کرد تا این ریپو را کشف کردم. یه فیلد داخل package.json به نام browser اضافه می‌کنیم که آدرس اون ماژولی که قراره در مرورگر اجرا بشه را بهش می‌دیم و باندلر از این طریق زمانی که داره بیلد می‌کنه میفهمه که برای مرورگر باید یه باندل کم حجم درست کنه:بنابراین باید فانکشن‌ها را هم از هم جدا کرد:حالا زمانی که بیلد می‌کنیم حجم کل باندل حدود 511 بایت می‌شود! زمانی که این پکیج یعنی base64-encode-string را به پروژه اضافه می‌کنیم اگه در محیط node.js باشیم نسخه مخصوص آن و اگه داخل مرورگر باشیم نسخه مخصوص مرورگر به درستی اجرا می‌شود.</description>
                <category>مسیح جهانگیری</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Wed, 02 Oct 2019 23:47:48 +0330</pubDate>
            </item>
                    <item>
                <title>نسخه بندی با معنا (Semantic Versioning) در NPM</title>
                <link>https://virgool.io/JavaScript8/%D9%86%D8%B3%D8%AE%D9%87-%D8%A8%D9%86%D8%AF%DB%8C-%D8%A8%D8%A7-%D9%85%D8%B9%D9%86%D8%A7-semantic-versioning-%D8%AF%D8%B1-npm-zfxiwopnshsq</link>
                <description>زمانی که از NPM (مخفف Node Package Manager) استفاده می‌کنید بهتر است نحوی نسخه بندی پکیج هایش و همچنین مفهوم علامت‌های ^ (carets) و ~ (tildes) که قبل از ورژن هر پکیج در فایل package.json نوشته می‌شوند را بدانید.قبل از اینکه مفهوم این علامت ها را بدانیم باید با نحوی نسخه بندی با معنا (Semantic Versioning) در NPM آشنا باشیم.نسخه بندی با معنا (Semantic Versioning) در NPM چیست؟هر نسخه از پکیج های NPM حداقل دارای سه قسمت به نام های Major، Minor و Patch به شرح زیر است:نسخه بندی با معنا (Semantic Versioning) در NPM1. Major (تغییرات بزرگ) :زمانی عدد این قسمت (عدد اول) از نسخه افزایش می‌یابد که در پکیج تغییرات بزرگی رخ داده باشند. منظور از تغییرات بزرگ این است که کد هایی که با نسخه قبلی نوشته شده‌اند دیگر در این نسخه جدید Major سازگار نیستند.مثلا اگر از نسخه 5.3.4 به 6.0.0 آپدیت کنید، کد هایی که بر اساس ورژن 5.3.4 نوشته شده‌اند دیگر در نسخه 6.0.0 سازگار نیستند و اگر آپدیت کنید ممکن است در پروژه‌ی شما اختلالی به وجود آید!دو نکته را باید در نظر بگیرید: الف) این تعریف برای پکیج هایی درست است که اصولی نسخه بندی شده‌اند. ب) ممکن است شما مثلا از 10% پکیج داخل پروژه تون استفاده کرده باشید و با آپدیت major اختلالی در پروژه تون به وجود نیاید و کاملا با پروژه شما سازگار باشد. بنابراین نمی‌شود قطعی گفت ناسازگار می‌شود.2. Minor (تغییرات جزئی) :زمانی عدد این قسمت (عدد دوم) از نسخه افزایش می‌یابد که در پکیج تغییرات جزئی رخ داده باشند. منظور از تغییرات جزئی این است که کد پروژه‌هایی که با نسخه قبلی نوشته شده‌اند در نسخه جدید Minor نیز سازگار‌اند. با این تفاوت که بهبودهایی مثل اضافه شدن ویژگی‌ها و متد‌های جدید، بهبود عملکرد توابع و... در این نسخه جدید ایجاد شده‌ است.3. Patch (وصله ها) :زمانی عدد این قسمت (عدد سوم) از نسخه افزایش می‌یابد که به پکیج وصله‌هایی (Patch) اضافه شده باشند. منظور از وصله یا پچ تغییرات خیلی جزئی مثل برطرف شدن باگ‌های ورژن Minor در کد پکیج است. کد پروژه‌هایی که با نسخه قبلی نوشته شده‌اند در نسخه جدید Patch (همانند Minor) نیز سازگار‌اند.علامت های مشخص کننده‌ی بازه (range) نسخهاین قسمت از نسخه (قبل از اعداد) سه حالت می‌تواند داشته باشد:علامت &quot;^&quot; : به این معنی است که شامل تمام Patch های بعدی است. مثلا اگر قبل از ورژن 1.2.3 از این علامت استفاده کنید شامل تمام ورژن های 1.2.4، 1.2.42، 1.2.6 و... می‌شود. (یعنی فقط عدد سوم می‌تواند بزرگتر مساوی 3 باشد)علامت &quot;~&quot; : به این معنی است که شامل تمام Patch ها و Minor های بعدی است. مثلا اگر قبل از ورژن 2.4.1 از این علامت استفاده کنید شامل تمام ورژن های 2.4.3، 2.5.0، 2.8.9 و... می‌شود. (یعنی عدد دوم می‌تواند بزرگتر مساوی 4 باشد - عدد اول زمانی که عدد دوم برابر 4 است میتواند بزرگتر مساوی 1 باشد و زمانی که عدد دوم بزرگتر از 4 باشد هر عددی را می‌تواند اختیار کند)بدون علامت : به این معنی است که دقیقا باید از ورژن ذکر شده استفاده شود. مثلا اگر قبل از 5.3.54 هیچ علامتی نباشد باید دقیقا از همین ورژن استفاده شود و مجاز به استفاده از ورژن های بعدی نیست.به طور خلاصه:&quot;^1.2.3&quot; : 1.2.x , x&gt;=3&quot;~2.4.1&quot; : 2.x.y , x&gt;=4 , if (x == 4) --&gt; y&gt;=1&quot;5.3.54&quot; : 5.3.54</description>
                <category>مسیح جهانگیری</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Sat, 02 Mar 2019 02:28:54 +0330</pubDate>
            </item>
            </channel>
</rss>