<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های آرمان عاشوری</title>
        <link>https://virgool.io/feed/@ashoori.arman74</link>
        <description>برنامه نویس دون پایه :)</description>
        <language>fa</language>
        <pubDate>2026-06-16 10:50:38</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/9076/avatar/68xdBx.jpg?height=120&amp;width=120</url>
            <title>آرمان عاشوری</title>
            <link>https://virgool.io/@ashoori.arman74</link>
        </image>

                    <item>
                <title>نصب سریع‌تر پکیج‌های NPM توسط دستور NPM CI</title>
                <link>https://virgool.io/@ashoori.arman74/%D9%86%D8%B5%D8%A8-%D8%B3%D8%B1%DB%8C%D8%B9-%D8%AA%D8%B1-%D9%BE%DA%A9%DB%8C%D8%AC-%D9%87%D8%A7%DB%8C-npm-%D8%AA%D9%88%D8%B3%D8%B7-%D8%AF%D8%B3%D8%AA%D9%88%D8%B1-npm-ci-okc6a2mxi6il</link>
                <description>وقتی داریم از NodeJs برای توسعه اپلیکیشن‌هامون استفاده می‌کنیم، معمولا باید کلی وابستگی (Dependency) رو توسط NPM، نصب و یا (حذف و دوباره نصب) کنیم. حالا بسته به اینکه تعداد وابستگی‌های پروژمون چقدره، این فرآیند میتونه کند و انتظار براش خسته کننده باشه. توی این یادداشت نگاهی به npm ci و مزایای اون نسبت به npm install میندازیم و کمی هم در مورد اهمیت وجودی فایل package-lock.json صحبت می‌کنیم.وقتی میخوایم یک پکیج خاص رو نصب کنیم معمولا این دستور رو استفاده می‌کنیم:npm install highcharts --saveوقتی این دستور رو اجرا می‌کنیم، NPM میاد highcharts رو به فایل package.json اضافه می‌کنه (اگه از قبل موجود نباشه) و بعد پکیجش رو توی دایرکتوری node_modules نصب می‌کنه.وقتی از npm استفاده می‌کنیم، یه فایل به نام package-lock.json هم توی پروژه به صورت اتوماتیک ایجاد می‌شه. که این فایل تمام وابستگی‌هایی که نصب کردیم و وابستگی‌های غیر مستقیم رو ردیابی (Track) می‌کنه.در واقع این فایل تضمین میکنه که هر وقت npm install بزنیم، نسخه پکیج‌ها دقیق همونی خواهند بود که ما قبلا نصب کرده بودیم و تغییری نمیکنن. قبل از اینکه بخوام وارد بحث اصلی بشم، اول بیاید اهمیت فایل pakcage-lock.json رو بررسی کنیم.اهمیت فایل pakcage-lock.jsonواسه اینکه بهتر متوجه بشید فرض کنید این فایل package.json رو ایجاد کردیم:{
  &amp;quotname&amp;quot: &amp;quottest&amp;quot,
  &amp;quotversion&amp;quot: &amp;quot1.0.0&amp;quot,
  ...
  &amp;quotdevDependencies&amp;quot: {
    &amp;quothighcharts&amp;quot: &amp;quot9.0.0&amp;quot
  }
}و هنوز فایل package-lock.json وجود نداره. وقتی دستور npm install رو بزنیم فایل package-lock.json هم اتوماتیک ایجاد میشه و محتوای زیر هم داخلش قرار می‌گیره:&amp;quothighcharts&amp;quot: {     
    &amp;quotversion&amp;quot: &amp;quot9.0.0&amp;quot   حالا فرض کنید این دوتا فایل رو کپی کردیم و توی یک دایرکتوری دیگه قرار دادیم، و یک تغییر کوچک هم تو نسخه پکیج ایجاد کردیم و اولش از ( ^ ) استفاده کردیم: یعنی &quot;9.0.0^&quot;.( اگه معنی ^ یا ‍‍~ رو توی نسخه پکیج‌ها نمی‌دونید این لینک رو مطالعه کنید.)اصل داستان اینجاست :) الان اگه فایل pakcage-lock.json وجود نداشته باشه وقتی دستور npm install رو بزنیم، فایل package.json تغییر میکنه و نسخه 9.1.0 رو به جای 9.0.0 نصب می‌کنه{   
   &amp;quotname&amp;quot: &amp;quottest&amp;quot,
   &amp;quotversion&amp;quot: &amp;quot1.0.0&amp;quot,
   ...   
   &amp;quotdevDependencies&amp;quot: {
     &amp;quothighcharts&amp;quot: &amp;quot^9.1.0&amp;quot
   }
}اما اگه pakcage-lock.json وجود داشت، NPM لیست پکیج‌هارو از اون میخوند و دقیقا همون نسخه 9.0.0 رو نصب می‌کرد. اینجاست که اهمیت این فایل مشخص میشه :)خب حالا بریم سراغ بحث اصلیمون.خیلی وقتا پیش میاد که ما مجبور میشیم به دلایلی node_modules رو حذف و تمام پکیج هارو مجددا نصب کنیم. که معمولا دستور زیر رو استفاده می‌کنیم:rm -rf node_modules &amp;&amp; npm installاین دستور کار می‌کنه اما دستور زیر خیلی بهتره. npm ci چرا ؟ دستور npm ci میاد به صورت خودکار node_modules رو حذف می‌کنه و تمام نیازمندی‌های پروژه رو دوباره نصب می‌کنه.این دستور معمولا سریع‌تر از npm install عمل می‌کنه. چون مستقیم می‌ره فایل package-lock.json رو میخونه و از روی اون تمام پکیج‌هارو نصب می‌کنه که باعث میشه سرعت نصب بالاتر بره.مثالی از تفاوت سرعت نصب دو دستور npm ci و npm install:// example repo: https://github.com/vmware/clarity/tree/master/packages/core

npm install - 42.116s

npm ci - 24.629sاگه دستور npm ci تفاوتی توی لیست نیازمندی‌های موجود توی فایل package-lock.json و package.json پیدا کنه، خطا میده. که این خوبه. باز چرا؟وقتی دستور npm install  رو میزنیم فایل package-lock.json  هم بروزرسانی می‌شه حتی اگه تفاوتی تو نسخه پکیج‌ها وجود داشته باشه :(اما وقتی دستور npm ci رو بزنیم دیگه خیالمون راحته که همیشه دقیقا همون نسخه‌هایی نصب میشن که قبلا نصب کرده بودیم.امیدوارم این یادداشت هم براتون مفید بوده باشه. خیلی خوشحال میشم اگه ابهام یا اشکالی وجود داره برام کامنت کنید که اصلاح کنم.</description>
                <category>آرمان عاشوری</category>
                <author>آرمان عاشوری</author>
                <pubDate>Wed, 12 May 2021 13:54:03 +0430</pubDate>
            </item>
                    <item>
                <title>چگونه در انگولار نتیجه درخواست HTTP را Cache کنیم؟</title>
                <link>https://virgool.io/angular-iran/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%AF%D8%B1-%D8%A7%D9%86%DA%AF%D9%88%D9%84%D8%A7%D8%B1-%D9%86%D8%AA%DB%8C%D8%AC%D9%87-%D8%AF%D8%B1%D8%AE%D9%88%D8%A7%D8%B3%D8%AA-http-%D8%B1%D8%A7-cache-%DA%A9%D9%86%DB%8C%D9%85-r2cjenou5uab</link>
                <description>توی اکثر اپلیکیشن های تک صفحه‌ای (SPA) ما میخوایم مطمئن باشیم که داده‌هایی که از سرور دریافت می‌کنیم، کاملا به‌روز باشن. بنابراین معمولا به دفعات مورد نیاز اونارو از سرور درخواست می‌کنیم که گاهی نیاز به انجام تکرار درخواست‌ها نیست. توی این یادداشت یه راه‌حل خوب واسه جلوگیری از تکرار درخواست‌های http و cache کردن اونها ارائه میشه:)همونطور که گفته شد، داده‌هایی وجود دارن که احتمالش کمه موقع تعامل کاربر با برنامه شما تغییر کنن.به عنوان مثال، فرض کنید یه لیستی از کشورها رو میخواید توی یک dropdown داشته باشید. این لیست می‌تونه فقط یکبار از سرور دریافت بشه و برای تمام استفاده‌های بعدی از این لیست، از داده‌هایی که ذخیره (Cache) شدن استفاده بشه.یه مثال رایج واسه ارسال درخواست http:حالت معمول درخواست httpتوی کد قبلی هربار که ما متد getData رو صدا بزنیم، یک observable دریافت می‌کنیم، و با subscribe کردن به اون، مجددا یک درخواست HTTP دیگه ارسال می‌کنیم. که این رفتار توی مثالی که زده شد، اصلا خوب نیست!!!یک راه برای جلوگیری از این اتفاق اینه که بیایم از Subject ها یا به طور خاص از ReplySubject استفاده کنیم. که این روش هم یکم پیچیده میشه و هم روش استانداردی نیست!!راه بهترش، استفاده از متد ShareReplay هست!عملکرد متد shareReplayکاری که متد ShareReplay انجام میده اینه که آخرین مقداری که منتشر (Emit) شده رو ذخیره می‌کنه و اون مقدار رو با همه‌ی Subscriber های جدید به اشتراک میذاره. یعنی دقیقا همون چیزی که ما بهش نیاز داشتیم.برای استفاده از این متد هم کافیه از تابع Pipe استفاده کنیم و توی اون از متد (1)shareReplay استفاده کنیم. به همین راحتی!استفاده از shareReplay در عملتوی نمونه‌ای که اینجا قراردادم، می‌تونید این موضوع رو بهتر مشاهده کنید. و اگه کنسول و network رو بررسی کنید میبینید که تنها یکبار درخواست Http ارسال میشه و برای تمام دفعات بعدی که متد getData رو subscribe کنیم از cache استفاده میشه!هروقت هم نیاز بود که مجددا داده‌ها از سرور دریافت بشن، کافیه متد clearCache رو صدا بزنید.امیدوارم این یادداشت کوتاه براتون مفید بوده باشه :) https://stackblitz.com/edit/ng-http-caching-hlynxr?file=src%2Fapp%2Fapp.service.ts </description>
                <category>آرمان عاشوری</category>
                <author>آرمان عاشوری</author>
                <pubDate>Wed, 12 May 2021 10:38:29 +0430</pubDate>
            </item>
                    <item>
                <title>چگونه در انگولار، روی اولین اینپوتی که خطا داره فوکوس کنیم؟</title>
                <link>https://virgool.io/@ashoori.arman74/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%AF%D8%B1-%D8%A7%D9%86%DA%AF%D9%88%D9%84%D8%A7%D8%B1-%D8%B1%D9%88%DB%8C-%D8%A7%D9%88%D9%84%DB%8C%D9%86-%D8%A7%DB%8C%D9%86%D9%BE%D9%88%D8%AA%DB%8C-%DA%A9%D9%87-%D8%AE%D8%B7%D8%A7-%D8%AF%D8%A7%D8%B1%D9%87-%D9%81%D9%88%DA%A9%D9%88%D8%B3-%DA%A9%D9%86%DB%8C%D9%85-pkgfkprpezlh</link>
                <description>هنگام کار با ورودی های مورد نیاز توی یک فرم، گاهی اوقات ممکنه کاربر فراموش کنه که یک ورودی مورد نیاز فرم رو پُر کنه، و وقتی روی دکمه‌ی ثبت نهایی فرم کلیک میکنه، هیچ اتفاقی نمیوفته. این میتونه برای کاربر کمی گیج‌کننده باشه که برای ادامه، باید چیکار کنه!!به کمک فرم‌های انگولار، ما میتونیم به کاربر کمک کنیم تا وقتی فرم رو میخواد ثبت کنه، روی اولین اینپوتی که خطا داره فوکوس کنیم تا سریعتر بتونه به کارش ادامه بده.form.component.htmlform.component.tsما داریم از AngularReactiveForms برای ایجاد فرم و سرویس FormBuilder برای منطق فرممون استفاده می‌کنیم.برای اضافه کردن منطق فوکوس روی اولین اینپوتی که خطا داره، هنگامی که کاربر فرم رو میخواد سابمیت کنه، یک دایرکتیو ایزوله ( IsolatedDirective) می‌سازیم.اسم این دایرکتیو رو میذاریم (focusInvalidInput).وقتی این دایرکتیو رو بذاریم رو فرممون، منتظر میمونه تا کاربر فرم رو سابمیت کنه و وقتی  رویداد (Event) سابمیت رخ داد، میفهمه که باید در صورت وجود خطا، روی اولین اینپوتی که خطا داره فوکوس کنه. ( چه باهوش! )focus-invalid-input.directive.tsبرای اینکه دایرکتیو ما تشخیص بده که کِی رویداد سابمیت رخ داده، می‌تونیم از HostListener@ استفاده کنیم تا متد مد نظر خودمون (onFormSubmit) رو همون موقع اجرا کنیم.وقتی ما یه رویداد داریم، می‌تونیم چک کنیم ببینیم شامل یک ورودی نامعتبر هست یا نه.یک راه آسون واسه اینکار اینه که چک کنیم آیا المنتی وجود داره که شامل سلکتور .ng-invalid باشه یا نه.( تو فرم‌های انگولاری هر اینپوتی که خطا داشته باشه، انگولار بهش کلاس ng-invalidرو میده ).برای بررسی تمپلیت (Template) فرممون، می‌تونیم سرویس ElementRef رو به دایرکتیومون تزریق (Inject) کنیم و با استفاده از اون به HTML فرم دسترسی داشته باشیم.به وسیله این کد (this.el.nativeElement.querySelector(&#x27;.ng-invalid&#x27;))میتونیم اولین اینپوتی که کلاس ng-invalid رو داره پیدا کنیم ( اگه همشو میخواید باید از querySelectorAll استفاده کنید) و روش فوکوس کنیم. نکته: اگه دارید از اینپوت های متریال استفاده می‌کنید، باید این سلکتور رو بذارید: input.ng-invalidبعد از اینکه این دایرکتیو رو ساختیم، حالا باید سلکتور اون رو به فرممون اضافه کنیم تا جوری که میخوایم، رفتار کنه. form.component.htmlاگه میخواید این رفتار رو به صورت عمومی تو تمام فرم‌های اپلیکیشن انگولاریتون داشته باشید، می‌تونید سلکتور دایرکتیو رو از [focusInvalidInput] به form تغییر بدید.برای مشاهده دمو به این لینک مراجعه کنید.امیدوارم از این یادداشت خوشتون اومده باشه :)</description>
                <category>آرمان عاشوری</category>
                <author>آرمان عاشوری</author>
                <pubDate>Mon, 22 Feb 2021 14:07:03 +0330</pubDate>
            </item>
            </channel>
</rss>