<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های شراره شادالو</title>
        <link>https://virgool.io/feed/@sharareshaddev</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 01:18:39</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/3855034/avatar/8sLOpa.jpg?height=120&amp;width=120</url>
            <title>شراره شادالو</title>
            <link>https://virgool.io/@sharareshaddev</link>
        </image>

                    <item>
                <title>درک Closure در React</title>
                <link>https://virgool.io/@sharareshaddev/%D8%AF%D8%B1%DA%A9-closure-%D8%AF%D8%B1-react-h6iqmh206mr0</link>
                <description>اگر مدتی با React کار کرده باشی، احتمالاً با یکی از این موقعیتها روبهرو شدی:state آپدیت میشود، ولی داخل setInterval مقدار قدیمی چاپ میشودیک event handler انگار «در گذشته گیر کرده»یا لاگها با چیزی که روی UI میبینی نمیخوانندو معمولاً جواب این است:«این به خاطر Closure است»ولی Closure در React دقیقاً یعنی چه؟Closure یعنی:یک تابع، متغیرهایی را که موقع ساخته شدنش وجود داشتهاند،حتی بعد از پایان آن scope، در حافظه نگه میدارد.function outer() {
  let count = 0

  return function inner() {
    console.log(count)
  }
}

const fn = outer()
fn() // 0تابع inner هنوز count را میشناسد،با اینکه outer دیگر اجرا نمیشود.این رفتار اسمش Closure است.چرا Closure در React مهم میشود؟چون React اینطوری کار میکند:با هر renderمتغیرها دوباره ساخته میشوند  و توابع دوباره ساخته میشونداما بعضی توابع قدیمی زنده میمانند(مثل setInterval، event handlerها، effectها)و اینجا Closure خودش را نشان میدهد.مثال باگ Closure در Reactfunction Counter() {
  const [count, setCount] = React.useState(0)

  React.useEffect(() =&gt; {
    const id = setInterval&#40;(&#41; =&gt; {
      console.log(&#039;interval sees:&#039;, count)
    }, 1000)

    return () =&gt; clearInterval(id)
  }, [])

  return (
    &lt;button ={() =&gt; setCount(count + 1)}&gt;
      count: {count}
    &lt;/button&gt;
  )
}چه اتفاقی میافتد؟با کلیک، عدد روی صفحه زیاد میشود ✅ولی داخل console، همیشه 0 چاپ میشود ❌چرا این باگ اتفاق میافتد؟useEffect فقط یکبار اجرا شدهتابع داخل setInterval همان موقع ساخته شدهآن تابع، count مربوط به رندر اول را در Closure خودش نگه داشتهبه زبان ساده:این interval فقط «گذشته» را میبیند، نه state فعلی را.Render 1:count = 0interval → count = 0 را ذخیره میکندRender 2:count = 1interval هنوز همان closure قدیمی را داردClosure خودش آپدیت نمیشود؛باید دوباره ساخته شود.راهحل اول: اضافه کردن dependencyuseEffect(() =&gt; {
  const id = setInterval&#40;(&#41; =&gt; {
    console.log(count)
  }, 1000)

  return () =&gt; clearInterval(id)
}, [count])✔ همیشه مقدار جدید را میبیند✖ interval در هر تغییر destroy و create میشودبرای بعضی سناریوها خوب است، برای بعضی نه.راهحل دوم: آپدیت فانکشنی (پیشنهادی)اگر هدف فقط آپدیت state است:setCount(prev =&gt; prev + 1)این روش چرا خوبه؟به Closure وابسته نیستReact مقدار آخر state را تضمین میکندباگهای Closure را دور میزندراهحل سوم: useRef (حرفهای)وقتی میخواهی:effect فقط یکبار اجرا شودولی همیشه به آخرین مقدار دسترسی داشته باشیfunction Counter() {
  const [count, setCount] = React.useState(0)
  const countRef = React.useRef(count)

  React.useEffect(() =&gt; {
    countRef.current = count
  }, [count])

  React.useEffect(() =&gt; {
    const id = setInterval&#40;(&#41; =&gt; {
      console.log(countRef.current)
    }, 1000)

    return () =&gt; clearInterval(id)
  }, [])

  return (
    &lt;button ={() =&gt; setCount(c =&gt; c + 1)}&gt;
      {count}
    &lt;/button&gt;
  )
}اینجا:ref با render عوض نمیشودمقدارش همیشه بهروز استinterval همیشه مقدار جدید را میخوانداین الگو در پروژههای بزرگ خیلی رایج استClosure در event handlerهاconst handleClick = () =&gt; {
  setTimeout&#40;(&#41; =&gt; {
    console.log(value)
  }, 2000)
}اگر value قبل از ۲ ثانیه تغییر کند:مقدار قدیمی چاپ میشوددلیل؟همان Closure.Closure باگ React نیست ویژگی JavaScript استReact فقط باعث میشود بیشتر دیده شودجمعبندی نهاییهر وقت در React دیدی:داده قدیمی استstate درست به نظر نمیرسدلاگها عجیبانداز خودت بپرس:این تابع کی ساخته شده؟چه متغیرهایی را در Closure خودش نگه داشته؟به مقدار جدید نیاز دارم یا مقدار زمان ساخت؟</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Tue, 10 Feb 2026 13:44:52 +0330</pubDate>
            </item>
                    <item>
                <title>اینترنت ملی و مدیریت Dependency در Node.js</title>
                <link>https://virgool.io/@sharareshaddev/%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA-%D9%85%D9%84%DB%8C-%D9%88-%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-dependency-%D8%AF%D8%B1-nodejs-xinvzpjilrtv</link>
                <description>با محدود شدن دسترسی به اینترنت در ایران، یکی از بزرگ‌ترین چالش‌ها برای توسعه‌دهندگان، نصب و مدیریت پکیج‌ها تو پروژه‌های Node.js شده. کاری که قبلاً با یه npm install چند ثانیه طول می‌کشید، الان ممکنه با خطا، زمان طولانی نصب یا Timeout روبه‌رو بشه.پس چطور زنده بمونیم؟استفاده از npm registry و mirror جایگزیناولین قدم ساده و سریع، استفاده از mirror به جای registry اصلی npm هست:npm config set registry https://registry.npmmirror.com
یا فقط برای یک نصب خاص:npm install --registry=https://registry.npmmirror.com
تو خیلی از مواقع، همین تغییر کوچک کافی هست تا دوباره کارمون راه بیفته.Docker:اگه پروژه‌ت Dockerized باشه، خیلی از مشکلات از قبل حل شدن:استفاده از Docker Hub mirrorساخت imageهایی که dependencyها از قبل داخلش نصب شدهبیلد گرفتن در CI/CD خارج از ایران و فقط pull کردن image نهاییتو این حالت، Docker دیگه فقط یه ابزار نیست، یه استراتژی بقاست.مدیریت CacheCache یکی از مهم‌ترین ابزارهاست. به زبون ساده، cache یعنی ذخیره‌سازی محلی پکیج‌ها و artifactها تا دفعه بعد نیازی به دانلود دوباره نباشه.چند نوع cache مهم داریم:Npm Cache: با دستور --prefer-offline می‌تونیم حتی بدون اینترنت پکیج‌ها رو نصب کنیم:npm install --prefer-offline
Yarn Cache: مثل npm، پکیج‌ها رو تو حافظه محلی نگه می‌داره و سرعت نصب رو بالا می‌بره.Pnpm Store: پکیج‌ها رو به صورت اشتراکی ذخیره می‌کنه و چند پروژه می‌تونن ازش استفاده کنن.Cache در Nexus یا Repository Managerهای دیگه: پکیج‌ها یه بار دانلود می‌شن و کل تیم بدون اینترنت بهشون دسترسی داره.Registry داخلی؛ مخصوص تیم‌هابرای تیم‌ها و پروژه‌های سازمانی، بهترین کار راه‌اندازی یه registry داخلی هست:VerdaccioNexusArtifactoryاین روش وابستگی مستقیم به اینترنت خارجی رو حذف می‌کنه و مدیریت پکیج‌ها رو ساده‌تر و قابل پیش‌بینی‌تر می‌کنه.Nexus چیه و چطور کار می‌کنه؟Nexus یه repository manager حرفه‌ایه که مخصوص تیم‌ها و شرکت‌های بزرگ طراحی شده تا کنترل کامل روی پکیج‌ها و وابستگی‌ها داشته باشن.چند قابلیت مهم Nexus:نگهداری انواع پکیج‌ها:Java: Maven, GradleNode.js: npmPython: PyPIDocker: Docker imagesو حتی Ruby، NuGet و غیرهMirror و Cache: پکیج‌ها یه بار دانلود می‌شن و دفعه بعد از Nexus داخلی میاد، بدون نیاز به اینترنت خارجی.امنیت و کنترل دسترسی: می‌تونی مشخص کنی چه کسی به چه پکیجی دسترسی داشته باشه و قبل از استفاده، نسخه‌ها بررسی بشن.برای Node.js کافیه registry داخلی رو تنظیم کنیم:npm set registry http://nexus.local:8081/repository/npm-proxy/
npm install
حتی می‌تونیم پکیج‌های داخلی خودمون رو تو Nexus منتشر کنیم و همه تیم ازش استفاده کنه.به طور خلاصه، Nexus یه راهکار حرفه‌ایه که کار مدیریت dependencyها و artifactها رو ساده، امن و قابل پیش‌بینی می‌کنه، مخصوصاً وقتی اینترنت خارجی دسترسی نداریم.جمع‌بندیبا ترکیب چند روش ساده، می‌تونیم جریان توسعه رو حتی تو شرایط محدودیت اینترنت ادامه بدیم:mirrorهای جایگزینDockercacheهای محلی و مرکزیregistry داخلیبا این استراتژی‌ها، پروژه‌ها می‌تونن بدون وقفه و با اطمینان پیش برن.</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Sun, 08 Feb 2026 21:27:38 +0330</pubDate>
            </item>
                    <item>
                <title>وقتی اینترنت ملی شده به جای ریکپچا گوگل از چی استفاده کنیم ؟ (راه حل موقت)</title>
                <link>https://virgool.io/@sharareshaddev/%D9%88%D9%82%D8%AA%DB%8C-%D8%A7%DB%8C%D9%86%D8%AA%D8%B1%D9%86%D8%AA-%D9%85%D9%84%DB%8C-%D8%B4%D8%AF%D9%87-%D8%A8%D9%87-%D8%AC%D8%A7%DB%8C-%D8%B1%DB%8C%DA%A9%D9%BE%DA%86%D8%A7-%DA%AF%D9%88%DA%AF%D9%84-%D8%A7%D8%B2-%DA%86%DB%8C-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-%D8%B1%D8%A7%D9%87-%D8%AD%D9%84-%D9%85%D9%88%D9%82%D8%AA-uz33koex2fed</link>
                <description>طراحی یک Human Verification داخلی بدون سرویس خارجیدر بسیاری از پروژهها، برای  تشخیص انسان از ربات از  reCAPTCHA استفاده میکنیم اگر از ورژن ۳ گوگل استفاده کرده باشین متوجه میشین که ریکپچا به صورت بصری به کاربر دیگه نمایش داده نمیشه و در پشت صحنه بروزر میاد با استفاده از توکنی که میسازه و به بکند ارسال میکنه انسان بودنشو به کد ما اثبات میکنه . فعلا با توجه به وضعیت ایران و ملی شدن اینترنت دیگه دسترسی به سرویس های خارجی نداریم یا اگرم داریم یه روز وصله یه روز قطع در این مقاله میخوام دربارهی تجربهی طراحی یک Human Verification  صحبت کنم؛راهحلی که نه به Google وابسته است، نه Cloudflare، نه هیچ سرویس خارجی دیگر — و در عین حال UX کاربر مشکلی ایجاد نمیکند. ولی بدونید راه حل موقت است و همچنین برای فرم های حساس بهتره اسفاده نکنین . همچنین هدف این کد سمت فرانت این هستش که از سابمیت شدن فرم ها توسط ربات ها جلوگیری شه برای امنیت بیشتر به سراغ ریت لیمیت برید .تغییر زاویه نگاه: از Challenge به Behaviorبهجای اینکه از کاربر بخواهیم چیزی را حل کند ،میتوانیم بررسی کنیم چطور رفتار میکند.انسانها:زمان میبرنداسکرول میکنندلمس میکنندفوکوس میگیرندتعامل دارندباتها (حداقل بخش بزرگی از آنها):سریعاندبدون تعاملبدون فوکوسو اغلب headlessایدهی اصلی همینجا شکل گرفت:جمعآوری سیگنالهای رفتاری در فرانتاند و تصمیمگیری در بکاند.Human Token چیست؟فرانتاند یک توکن میسازد که در واقع خلاصهای از رفتار کاربر است.این توکن هیچ تصمیمی نمیگیرد؛ فقط اطلاعات خام را منتقل میکند.محتوای واقعی توکن (قبل از encode شدن):{
  &quot;action&quot;: &quot;submit-contact&quot;,
  &quot;d&quot;: 2400,
  &quot;i&quot;: 6,
  &quot;k&quot;: 2,
  &quot;f&quot;: 1
}d → مدت حضور کاربر در صفحهi → تعداد تعامل (touch / scroll / click)k → تعداد تایپ (اختیاری)f → فوکوس صفحهaction → جلوگیری از reuse توکناین آبجکت فقط Base64 میشود و همراه فرم به بکاند ارسال میشود.سازگاری با موبایل در طراحی اولیه ممکن است باید بدونیم موبایل ماوس ندارد و از تاچ استفاده میشه.به همین دلیل، بهجای «حرکت ماوس» مفهوم کلیتری تعریف شد:Interaction Countکه شامل:touchscrollclickfocusمیشود.به این شکل، منطق تشخیص کاملاً device-agnostic باقی میماند.نقش Honeypot (کوچک ولی حیاتی)در کنار توکن رفتاری، یک فیلد مخفی هم داریم:&lt;input name=&quot;company&quot; style=&quot;display:none&quot; /&gt;کاربر واقعی آن را نمیبیندباتها معمولاً پرش میکننداگر پر باشد، درخواست بدون هیچ بررسی دیگری رد میشودHuman Token دقیقاً چه نقشی دارد؟Human Token در این سیستم:نه «اثبات انسان بودن» استنه «مجوز امنیتی»بلکه:یک گزارش فشرده از رفتار کاربر استمثل این که فرانتاند به بکاند بگوید:«کاربر ۲.۴ ثانیه اینجا بوده، اسکرول کرده، تعامل داشته و صفحه فوکوس داشته.»پیادهسازی فرانتاند با Reactconst token = await executeHumanCheck(&quot;submit-form&quot;);import { useEffect, useRef } from &quot;react&quot;;

export function useHumanVerification() {
  const startedAt = useRef(Date.now());
  const interactions = useRef(0);
  const keyPresses = useRef(0);
  const focused = useRef(false);

  useEffect(() =&gt; {
    const inc = () =&gt; interactions.current++;

    window.addEventListener(&quot;mousemove&quot;, inc);
    window.addEventListener(&quot;touchstart&quot;, inc);
    window.addEventListener(&quot;touchmove&quot;, inc);
    window.addEventListener(&quot;scroll&quot;, inc);
    window.addEventListener(&quot;click&quot;, inc);

    window.addEventListener(&quot;keydown&quot;, () =&gt; {
      keyPresses.current++;
    });

    window.addEventListener(&quot;focus&quot;, () =&gt; {
      focused.current = true;
    });

    return () =&gt; {
      window.removeEventListener(&quot;mousemove&quot;, inc);
      window.removeEventListener(&quot;touchstart&quot;, inc);
      window.removeEventListener(&quot;touchmove&quot;, inc);
      window.removeEventListener(&quot;scroll&quot;, inc);
      window.removeEventListener(&quot;click&quot;, inc);
    };
  }, []);

  const executeHumanCheck = async (action: string): Promise&lt;string&gt; =&gt; {
    const payload = {
      action,
      d: Date.now() - startedAt.current,
      i: interactions.current,
      k: keyPresses.current,
      f: focused.current ? 1 : 0,
      t: Date.now(),
    };

    return btoa(JSON.stringify(payload));
  };

  return { executeHumanCheck };
}استفاده از Hook در فرم Reactfunction ContactForm() {
  const { executeHumanCheck } = useHumanVerification();

  const handleSubmit = async (e: React.FormEvent) =&gt; {
    e.preventDefault();

    const token = await executeHumanCheck(&quot;submit-contact&quot;);

    await fetch(&quot;/api/contact&quot;, {
      method: &quot;POST&quot;,
      headers: { &quot;Content-Type&quot;: &quot;application/json&quot; },
      body: JSON.stringify({
        name: &quot;Ali&quot;,
        message: &quot;Hello&quot;,
        token,
        company: &quot;&quot; // honeypot
      }),
    });
  };

  return (
    &lt;form ={handleSubmit}&gt;
      &lt;input name=&quot;company&quot; style={{ display: &quot;none&quot; }} /&gt;
      &lt;input name=&quot;name&quot; /&gt;
      &lt;button type=&quot;submit&quot;&gt;Send&lt;/button&gt;
    &lt;/form&gt;
  );
}الگوریتم تصمیمگیری بکاندHoneypot را بررسی کنToken را decode کنساختار را validate کنthresholdها را بررسی کنaction را match کننمونه کد بکاند (Node / Express)function verifyHumanToken(
  token: string,
  expectedAction: string
): boolean {
  try {
    const decoded = Buffer.from(token, &quot;base64&quot;).toString();
    const data = JSON.parse(decoded);

    if (data.action !== expectedAction) return false;
    if (data.d &lt; 1200) return false;      // خیلی سریع
    if (data.i &lt; 3) return false;         // بدون تعامل
    if (!data.f) return false;            // بدون فوکوس

    return true;
  } catch {
    return false;
  }
}استفاده در APIapp.post(&quot;/api/contact&quot;, (req, res) =&gt; {
  const { token, company } = req.body;

  if (company) {
    return res.status(403).send(&quot;Bot detected&quot;);
  }

  const isHuman = verifyHumanToken(token, &quot;submit-contact&quot;);

  if (!isHuman) {
    return res.status(403).send(&quot;Bot detected&quot;);
  }

  res.send({ success: true });
});جمعبندی این بخشHuman Token فقط گزارش رفتار استفرانتاند فقط جمعآوریکننده استبکاند تنها مرجع تصمیم استسیستم بدون CAPTCHA و بدون سرویس خارجی کار میکند</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Wed, 21 Jan 2026 15:53:56 +0330</pubDate>
            </item>
                    <item>
                <title>Frontend Deployment, Revisited (Part 1 — Build &amp; Docker)</title>
                <link>https://virgool.io/@sharareshaddev/frontend-deployment-revisited-part-1-%E2%80%94-build-docker-qkjal0b6eg2j</link>
                <description>در فرانت‌اند، تمرکز اغلب روی کد، کامپوننت و فریم‌ورک‌ هاست، اما مسیر واقعی پروژه از نوشتن کد تا اجرا شدن در دست کاربر بسیار گسترده‌تره. این مجموعه نشون می‌ده که تصمیم‌های فنی در مراحل build، deploy، runtime و observability چطور روی پرفورمنس، پایداری و هزینه‌ی نگه‌داری سیستم اثر می‌گذارن. هدف این چهار بخش، دادن دیدی end-to-end است؛ در قسمت اول، تمرکز روی Build و Docker است و یاد می‌گیریم چگونه مرحله‌ی build را قابل پیش‌بینی و قابل اعتماد کنیم تا پایه‌ی معماری پروژه محکم شود.(Part 1 — Build &amp; Docker)سال‌هاست که در فرانت‌اند درباره‌ی Performance، معماری و تجربه‌ی کاربری صحبت می‌کنیم،اما یک لایه‌ی مهم معمولاً دست‌کم گرفته می‌شه: فرآیندی که کد را به خروجی قابل اجرا تبدیل می‌کند.فرانت‌اند، برخلاف تصور رایج، صرفاً مجموعه‌ای از کامپوننت‌ها یا stateها نیست.سیستمیه که در نهایت باید build بشه، منتقل بشه و اجرا بشه.نقطه‌ی شروع تمام این زنجیره، build هستش ...در این مرحله، دپندنسی ها ریزالو می‌شن، کد به خروجی قابل اجرا تبدیل می‌شه و بسیاری از تصمیم‌های معماری عملاً غیرقابل بازگشت می‌شن.بعد از این مرحله:فریم‌ورک صرفاً یک جزئیات پیاده‌سازیهرفتار runtime تابع خروجی تولیدشده استو هر تفاوتی در build، می‌تونه به تفاوت در رفتار نهایی منجر بشهبه همین دلیل، build یک مرحله‌ی اجرایی ساده نیست؛بلکه بخشی از معماری سیستم محسوب می‌شه.یکی از مسائل نادیده گرفته‌شده در پروژه‌ها این است که build اغلب وابسته به محیط یا همون environment افراد مختلف است؛ نسخه‌ی Node، سیستم‌عامل یا حتی تنظیمات جزئی package manager می‌تواند باعث شود یک سورس‌کد واحد در شرایط مختلف خروجی‌های متفاوت تولید کند. در چنین شرایطی، صحبت از ثبات، قابلیت پیش‌بینی یا حتی دیباگ مؤثر عملاً بی‌معنا می‌شود.Docker دقیقاً چه مسئله‌ای رو حل می‌کنه؟جواب : کنترل فرآیند و تکرارپذیریDocker در فرانت‌اند وظیفه‌اش کنترل محیط build است.با Docker می‌تونیم:محیط build را ثابت کنیمنسخه‌ی runtime و وابستگی‌ها را تثبیت کنیمخروجی قابل اعتماد تولید کنیم، مستقل از ماشین یا شخص اجراکنندهیک مثال واقعی:پروژه React شما روی سیستم local بدون مشکل build می‌شه، اما در CI یا staging شکست می‌خوره. مشکل معمولاً تفاوت محیط‌هاست. Docker این تفاوت را حذف می‌کنه و خروجی یکسان تولید می‌کنه.فرض کنید پروژه‌ای با React داریم. ساختار پروژه:my-app/
 ├─ src/
 │   ├─ App.jsx
 │   └─ components/
 ├─ package.json
 └─ Dockerfile
یک Dockerfile ساده‌ی multi-stage می‌تونه این شکلی باشه:# Stage 1: Build
FROM node:20 AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Serve
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]توضیح کوتاه:مرحله اول، کد ما رو build می‌کنه و تمام وابستگی‌ها رو resolve می‌کنهمرحله دوم، خروجی static build شده رو داخل Nginx می‌ذاره تا سرو بشهاین یعنی تمام تصمیم‌های Build ما، از محیط گرفته تا وابستگی‌ها(دپندنسی ها)، قابل پیش‌بینی و یکسان باقی می‌مونن.فلوچارت فرآیند Build با Docker[Developer Code] 
      │
      ▼
[Install Dependencies] ---&gt; (Resolve Node Modules)
      │
      ▼
[Run Build Scripts] ---&gt; (Transpile + Bundle + Minify)
      │
      ▼
[Output: Static Files] 
      │
      ▼
[Docker Multi-Stage] 
      │
      ▼
[Stage 1: Build Environment] --&gt; Compile Code
      │
      ▼
[Stage 2: Runtime Environment] --&gt; Serve Static Files
      │
      ▼
[CI/CD / Staging / Production] --&gt; Consistent &amp; Reliable Output
این فلوچارت نشان می‌ده که فرانت‌اند از اولین خط کد تا خروجی پایدار روی سرور، نیازمند مرحله‌ی build کنترل‌شده است و Docker وظیفه‌ی تضمین این ثبات را داره.Multi-Stage Build در فرانت‌اندوقتی پروژه‌ی فرانت‌اند شما رشد می‌کنه، حجم وابستگی‌ها و فایل‌ها به سرعت زیاد می‌شه.اگر همه‌ی ابزارها، کامپایلرها و وابستگی‌های توسعه در خروجی نهایی باقی بمونن،نتیجه: bundle بزرگ، اجرای سنگین و حتی ریسک‌های امنیتی بوجود میان.اینجاست که Multi-Stage Build وارد بازی می‌شه.ایده‌ی ساده اما قدرتمندش اینه:مراحل مختلف build را در کانتینرهای جداگانه اجرا کنیم و فقط خروجی مورد نیاز برای اجرا (runtime) را به مرحله‌ی نهایی منتقل کنیم.به عبارت دیگر:Stage 1: محیط کامل توسعه و buildStage 2: محیط سبک runtime که فقط فایل‌های نهایی رو سرو می‌کنهاین کار باعث می‌شه خروجی کوچک، سبک، و قابل اعتماد باشه، و وابستگی‌های غیرضروری وارد سرور یا CDN نشه.فرض کنید پروژه React داریم. Dockerfile معمولاً این شکلیه:# Stage 1: Build
FROM node:20 AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Serve
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD [&quot;nginx&quot;, &quot;-g&quot;, &quot;daemon off;&quot;]توضیح مراحل:Stage 1 — Buildمحیط Node کامل استتمام وابستگی‌ها نصب می‌شوندکد transpile و bundle می‌شودخروجی نهایی در /app/build قرار می‌گیردStage 2 — Serveمحیط سبک Nginxفقط فایل‌های static (HTML, JS, CSS) از Stage 1 منتقل می‌شونداپلیکیشن قابل اجرا روی سرور می‌شودمزیت: فقط چیزی که نیاز داریم به محیط runtime می‌آید و حجم کانتینر کاهش می‌یابدفلوچارت Multi-Stage Build[Developer Code + Dependencies] 
          │
          ▼
[Stage 1: Build Container]
   - Install dependencies
   - Compile code
   - Bundle &amp; minify
          │
          ▼
[Build Output /app/build]
          │
          ▼
[Stage 2: Runtime Container]
   - Lightweight environment (Nginx)
   - Copy only build output
          │
          ▼
[Serve Static Files] --&gt; Consistent &amp; Optimized Deliveryچرا این مهمه؟حجم کانتینر runtime کاهش پیدا می‌کنهامنیت بالاتر، چون ابزارهای build وارد سرور نمی‌شنقابلیت پیش‌بینی و تکرارپذیری افزایش پیدا می‌کنهآماده‌سازی برای CI/CD ساده‌تر می‌شهجمع‌بندیBuild تنها مرحله‌ی آماده‌سازی خروجی نیست؛ ستون معماری فرانت‌اند استDocker ابزاری برای تثبیت تصمیم‌های فنی و قابل اعتماد کردن خروجی استMulti-stage build نشان‌دهنده‌ی تفکر معماری و تفکیک مسئولیت‌هاستدر Part 2، سراغ deploy و CDN می‌ریم و یاد می‌گیریم چگونه خروجی build شده را بهینه، سریع و مطمئن در دسترس کاربران قرار دهیم.دوست داشتین تو لینکدین با من در ارتباط باشین :)</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Sat, 10 Jan 2026 12:42:17 +0330</pubDate>
            </item>
                    <item>
                <title>Thinking in Frontend Architecture</title>
                <link>https://virgool.io/@sharareshaddev/thinking-in-frontend-architecture-x0ni6h0qtcds</link>
                <description>ممکنه هر پروژهای که دیده باشین، ساختار فولدرها، نحوه مدیریت State و جریان دادههاش کاملاً متفاوت باشه. این طبیعی است، چون روشها و معماریها متفاوته و هر تیم یه سبک خودش رو داره. اما چیزی که همه پروژههای موفق مشترک دارن اینه که یک اسکلت و اصول معماری مشخص دارن. بدون این اسکلت، حتی بهترین کدها هم با کوچکترین تغییر یا فشار، دچار آشفتگی میشوند و نگهداریشون سخت میشه.جلوتر میخوام به صورت حرفهای معماریها رو توضیح بدم و بگم هر کدوم کجا به درد میخوره تا وقتی پروژه بعدیتون رو شروع میکنین، راحتتر تصمیم بگیرین کدوم روش بهترینه.بدون معماری، پروژهها مثل ساختمان بدون اسکلت میشوند: ظاهراً خوب، اما با اولین فشار فرو میریزند.Layered ArchitectureLayered Architecture یکی از قدیمیترین و کلاسیکترین معماریهاست و ایده اصلی آن تقسیم پروژه به لایههای مسئولیت مشخص است. هر لایه فقط با لایه پایینتر خود ارتباط دارد و مسئولیتش مشخص است.مزایا:این معماری بسیار ساده و قابل فهم است، به ویژه برای تیمهای کوچک یا پروژههای تازه. جداسازی واضح Presentation Layer، Business Logic Layer و Data/API Layer باعث میشود که توسعه و تست هر لایه مستقل انجام شود. برای مثال میتوان Business Logic را بدون رندر UI تست کرد و API Layer را بدون توجه به سایر لایهها تغییر داد. این ساختار پایهای محکم برای شروع پروژهها فراهم میکند و دید روشن درباره جریان دادهها و مسئولیتها ارائه میدهد.محدودیتها:با رشد پروژه، لایهها میتوانند بزرگ و پیچیده شوند و مدیریت وابستگیها بین آنها چالشبرانگیز شود. اگر قوانین مرزبندی رعایت نشود، تغییرات در یک لایه ممکن است اثرات غیرمنتظرهای روی لایههای دیگر داشته باشد. بنابراین، معماری لایهای به تنهایی برای پروژههای بزرگ یا چند تیمی کافی نیست و معمولاً با Feature-based یا Domain-oriented ترکیب میشود.این مثال رو ببنید:// Data/API Layer
export async function fetchProducts() {
  const res = await fetch(&#039;/api/products&#039;);
  return await res.json();
}

// Business Logic Layer
import { useState, useEffect } from &#039;react&#039;;
export function useProductList() {
  const [products, setProducts] = useState([]);
  useEffect(() =&gt; { fetchProducts().then(setProducts); }, []);
  return products;
}

// Presentation Layer
function ProductList() {
  const products = useProductList();
  return &lt;ul&gt;{products.map(p =&gt; &lt;li key={p.id}&gt;{p.name}&lt;/li&gt;)}&lt;/ul&gt;;
}
Component-based ArchitectureComponent-based Architecture پایه فریمورکهای مدرن مثل React، Vue و Svelte است.ایده اصلی این است که برنامه را به کامپوننتهای کوچک، مستقل و قابل استفاده مجدد تقسیم کنیم.مزایا:این معماری باعث میشود که بخشهای مختلف UI ماژولار و دوبارهاستفاده پذیر باشند. یک Button یا Modal میتواند در چندین صفحه بدون تغییر مجدد استفاده شود، که هم سرعت توسعه را بالا میبرد و هم خطاها را کاهش میدهد. علاوه بر این، تیمها میتوانند روی کامپوننتهای مختلف به صورت موازی کار کنند و وابستگی بین توسعهدهندگان کمتر شود.محدودیتها:با وجود مزایا، صرفاً استفاده از کامپوننتها کافی نیست. بدون مدیریت دقیق State و وابستگیها، پروژه به سرعت پیچیده و شکننده میشود. تغییر یک کامپوننت کوچک میتواند باعث بروز باگ در بخشهای دیگر شود، به ویژه اگر کامپوننتها بدون مرزهای مشخص به State یا API مشترک دسترسی داشته باشند.مثال:یک کامپوننت Button که UI + logic خودش را دارد، اما نباید مستقیم با API یا state global تعامل کند.Atomic Design / UI-driven ArchitectureAtomic Design بر پایه سلسلهمراتب UI است:Atoms → Molecules → Organisms → Templates → Pages.هدف اصلی این معماری استانداردسازی UI و افزایش قابلیت reuse است.مزایا:توسعه سریع UI، دوبارهاستفاده آسان از عناصر کوچک و داشتن استاندارد مشخص در طراحی، مزایای اصلی این رویکرد هستند. تیمها میتوانند سریعاً بخشهای مختلف UI را ایجاد و با سایر بخشها ترکیب کنند.محدودیتها:این معماری فقط بر UI تمرکز دارد و به مسائل بیزنسی یا State Management نمیپردازد. پروژه ممکن است از نظر ظاهری مرتب باشد اما اگر Featureها یا Domains به درستی مدیریت نشوند، maintainability پایین خواهد بود.Feature-based Structure چیست؟Feature-based Structure یعنی پروژه را بر اساس ویژگیها (Features) یا قابلیتهای کوچک قابل تحویل تقسیم کنیم، نه بر اساس نوع فایل یا صفحه.هر Feature شامل همه چیزهایی است که آن قابلیت نیاز دارد: UI، منطق، state و ارتباط با API.هدف این است که اضافه کردن یا تغییر یک ویژگی، کمترین تأثیر را روی سایر بخشها داشته باشد.مثال عملی:فرض کن اپلیکیشن فروشگاهی داریم، Feature-based Structure میتواند اینطور باشد:/features/login
  ├── ui/          ← کامپوننتهای فرم لاگین
  ├── model/       ← منطق و validation مربوط به login
  ├── api/         ← تماس با سرور برای login
  └── index.ts     ← export یکپارچه feature

/features/product-list
  ├── ui/
  ├── model/
  ├── api/
  └── index.ts
Domain-oriented Structure چیست؟Domain-oriented Structure یعنی ساختار پروژه را بر اساس حوزههای کاری (Domain) یا قابلیتهای بیزنسی اصلی تقسیم کنیم، نه صرفاً نوع فایل یا صفحه.هر دامنه کاری، مجموعهای از featureها، منطق بیزنسی و دادههای مرتبط را در خودش نگه میدارد.این کار باعث میشود تیمها بتوانند روی یک دامنه مستقل کار کنند، وابستگیها محدود شوند و تغییرات بیزنسی راحتتر اعمال شود.مثال عملی:فرض کن یک اپلیکیشن فروشگاهی داریم:/domains/auth
  ├── features/login/
  ├── features/register/
  ├── api/
  └── model/

/domains/product
  ├── features/listing/
  ├── features/detail/
  ├── api/
  └── model/

/domains/cart
  ├── features/cart-view/
  ├── features/checkout/
  ├── api/
  └── model/
Module-based / Package-oriented Architectureچی هست؟در معماری Module-based، پروژه به ماژول‌های کاملاً مستقل تقسیم می‌شود که می‌توانند به صورت جداگانه توسعه، تست و حتی deploy شوند. هر ماژول شامل همه چیزهایی است که برای عملکرد خودش نیاز دارد: UI، منطق بیزنسی، State و API.این رویکرد شبیه Feature-based Architecture است، اما با تمرکز روی استقلال کامل ماژول‌ها و قابلیت انتشار یا استفاده مجدد در پروژه‌های دیگر (مثلاً npm package یا Micro-Frontend).فرض کنید یک اپلیکیشن فروشگاهی داریم:/modules/auth
  ├── features/login/
  ├── features/register/
  ├── api/
  └── package.json

/modules/product
  ├── features/listing/
  ├── features/detail/
  ├── api/
  └── package.jsonهر ماژول می‌تواند جداگانه build و deploy شود.ماژول auth می‌تواند در پروژه‌های دیگر هم استفاده شود، بدون اینکه به product وابسته باشد.State و logic هر ماژول در خودش نگه داشته می‌شود و وابستگی بین ماژول‌ها محدود می‌شود.مزایااستقلال کامل ماژول‌ها: تیم‌ها می‌توانند بدون وابستگی به بخش‌های دیگر روی ماژول خودشان کار کنند.Reusability: ماژول‌ها می‌توانند در پروژه‌های دیگر یا در Micro-Frontend دوباره استفاده شوند.Deploy مستقل: اگر هر ماژول به صورت package مدیریت شود، امکان به‌روزرسانی و release مستقل فراهم است.Scalability: پروژه‌های بزرگ و چند تیمی با این رویکرد راحت‌تر مقیاس‌پذیر می‌شوند.محدودیت‌هاOverhead بیشتر: نیاز به تنظیمات build، versioning و dependency management برای هر ماژول وجود دارد.Coordination بین ماژول‌ها: باید قوانین واضحی برای تعامل بین ماژول‌ها داشته باشید، در غیر این صورت پروژه پیچیده و غیرقابل نگهداری می‌شود.Initial complexity: برای پروژه‌های کوچک، این معماری ممکن است اضافه و پیچیده باشد.Micro-Frontend ArchitectureMicro-Frontend یعنی پروژه فرانت‌اند را به چند اپلیکیشن مستقل کوچک تقسیم کنیم که هر کدام به تنهایی build، deploy و run می‌شوند.این معماری مشابه Microservices در بک‌اند است، اما برای فرانت‌اند.ایده اصلی این است که تیم‌ها کاملاً مستقل کار کنند و پروژه بزرگ و چندتیمی راحت‌تر مقیاس‌پذیر شود.مثال :/microfrontends/auth-app
  ├── login-feature/
  ├── register-feature/
  └── package.json

/microfrontends/product-app
  ├── listing-feature/
  ├── detail-feature/
  └── package.json

/microfrontends/cart-app
  ├── cart-view-feature/
  ├── checkout-feature/
  └── package.jsonمزایاتیم‌ها مستقل توسعه می‌دهند: هر تیم می‌تواند اپ خودش را بدون نگرانی از بخش‌های دیگر توسعه دهد.Deploy مستقل: امکان انتشار feature یا بخش جدید بدون تاثیر روی کل پروژه.مقیاس‌پذیری بالا: مناسب پروژه‌های بزرگ با چندین تیم و چند دامنه کاری.محدودیت‌هاپیچیدگی بالای runtime: برای مدیریت routing، state و استایل‌ها بین Micro-Frontendها نیاز به معماری دقیق داریم.Build و deploy پیچیده: هر اپ باید pipeline و versioning جداگانه داشته باشد.وابستگی‌ها باید مدیریت شوند: داده و state مشترک بین Micro-Frontendها نیاز به تعریف clear boundary دارد. نکته :Micro-Frontend زمانی ارزش واقعی دارد که پروژه بسیار بزرگ، چند تیمی و دارای چند دامنه کاری باشد. برای پروژه‌های کوچک یا متوسط، complexity و overhead آن معمولاً توجیه ندارد.معماری برای آینده و عملکرد (Performance as Architecture)وقتی درباره Performance صحبت میکنیم، معمولاً ذهنها مستقیم به optimizationهای بعدی مثل minify کردن فایلها یا استفاده از CDN میرود. اما Performance بخشی از معماری است و تصمیماتی که در سطح ساختار پروژه گرفته میشود، میتواند تاثیر بزرگی روی سرعت و کارایی داشته باشد.معماری حرفهای روی مواردی مثل Critical Rendering Path، Bundle Size، Lazy Loading و Cache Boundary اثر میگذارد. این یعنی Performance فقط یک مرحله بعد از توسعه نیست، بلکه باید از لحظه طراحی ساختار پروژه مد نظر باشد.مثال عملی:جداسازی Featureها و Lazy Loading:وقتی هر Feature مستقل باشد و فقط وقتی لازم است بارگذاری شود، زمان Initial Load کاهش پیدا میکند و کاربران سریعتر به محتوا دسترسی دارند.تعریف مرزهای واضح برای Cache:وقتی boundary برای Cache مشخص شود، مرورگر و شبکه میتوانند از memory و bandwidth بهینه استفاده کنند، بدون اینکه دادههای قدیمی یا غیرضروری دوباره دانلود شوند.به عبارت دیگر، یک معماری حرفهای نه تنها ساختار و maintainability پروژه را تضمین میکند، بلکه Performance را هم از همان ابتدا در هسته پروژه قرار میدهد.جمعبندیهیچ معماری کامل نیست؛ معمولاً ترکیب معماریها بهترین نتیجه را میدهد:پروژه کوچک → Feature-based + Component-basedپروژه بزرگ → Domain-oriented + Feature-based + Component-basedپروژه چند تیمی → Micro-Frontend + Domain-oriented + Layered💡 نکته حرفهای: قبل از نوشتن اولین خط کد، از خودتان بپرسید:این منطق کجا باید باشد؟وابستگیها چگونه محدود شوند؟تغییرات بیزنسی آینده چه تأثیری خواهند داشت؟دوست داشتین تو لینکدین با من در ارتباط باشین :)</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Tue, 06 Jan 2026 12:30:33 +0330</pubDate>
            </item>
                    <item>
                <title>درک ساختار CI/CD برای فرانت‌اند ها</title>
                <link>https://virgool.io/@sharareshaddev/%D8%AF%D8%B1%DA%A9-%D8%B3%D8%A7%D8%AE%D8%AA%D8%A7%D8%B1-cicd-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%81%D8%B1%D8%A7%D9%86%D8%AA-%D8%A7%D9%86%D8%AF-%D9%87%D8%A7-nkoqwetxf2fk</link>
                <description>اگر بخواهیم واقع‌بین باشیم، خیلی وقت‌ها وقتی صحبت از CI/CD می‌شود، ذهن ما به سرعت به سمت DevOps یا ابزارهای پیچیده می‌رود. اما برای یک فرانت‌اند سنیور، مفهوم اصلی CI/CD چندان پیچیده نیست؛ مهم این است که بدانیم چرا و چگونه می‌تواند روند توسعه و تحویل پروژه را ساده کند.CI و CD چیست؟CI (Continuous Integration) یعنی یکپارچه‌سازی مداوم. هر بار که تغییراتی در کد ایجاد می‌کنیم، این تغییرات باید با نسخه‌ی اصلی پروژه ترکیب شوند و مطمئن شویم که چیزی شکسته نشده است. برای فرانت‌اند، این معمولاً شامل:کامپایل کردن کد (مثلاً TypeScript → JavaScript)اجرای تست‌ها (واحد، یکپارچه و بعضاً end-to-end)بررسی linting و استانداردهای کدنویسیCD (Continuous Delivery / Deployment) یعنی تحویل یا انتشار مداوم. بعد از CI، هدف این است که نسخه‌ی قابل استفاده‌ای از اپلیکیشن آماده باشد. دو نوع اصلی داریم:Continuous Delivery: کد آماده‌ی انتشار است، اما انتشار نهایی نیاز به تایید دارد.Continuous Deployment: کد بدون دخالت دستی، مستقیماً به محیط تولید منتشر می‌شود.چرا CI/CD برای فرانت‌اند مهم است؟شاید برای یک تیم کوچک، CI/CD به نظر اضافه بار بیاید. اما با کمی تجربه می‌فهمیم که وقتی پروژه بزرگ‌تر می‌شود و چندین نفر همزمان روی بخش‌های مختلف کار می‌کنند، CI/CD باعث می‌شود:خطاها سریع‌تر کشف شوند.استقرار به محیط‌های staging و production امن‌تر و قابل پیش‌بینی‌تر شود.زمان صرف شده برای رفع باگ‌های ناشی از ادغام کد کاهش یابد.فرایند انتشار بدون استرس و قابل تکرار باشد.ساختار معمول یک pipeline فرانت‌اندبرای یک پروژه‌ی فرانت‌اند، pipeline معمولاً شامل مراحل زیر است:Pull &amp; Install Dependenciesهر تغییر جدید با git pull دریافت می‌شود و dependencies با npm install یا yarn install به‌روز می‌شوند.Linting &amp; Code Qualityابزارهایی مثل ESLint و Prettier بررسی می‌کنند که کد مطابق استاندارد تیم باشد. این مرحله معمولاً خطاهای رایج را قبل از تست و بیلد می‌گیرد.Unit &amp; Integration Testsتست‌های واحد (Unit) و یکپارچه (Integration) اجرا می‌شوند. برای React/Vue/Svelte، معمولاً از Jest یا Testing Library استفاده می‌کنیم.Buildکد Transpile و Bundle می‌شود (مثلاً با Vite، Webpack یا Parcel).هدف این مرحله این است که نسخه‌ی نهایی آماده‌ی اجرا باشد و مطمئن شویم که هیچ error یا warning حیاتی در زمان build وجود ندارد.E2E Tests (اختیاری اما توصیه‌شده)اگر پروژه پیچیده است، تست‌های End-to-End با Cypress یا Playwright اجرا می‌شوند تا رفتار اپلیکیشن در مرورگر واقعی شبیه‌سازی شود.Deployبسته به استراتژی تیم:Staging: برای آزمایش تیم داخلیProduction: نسخه‌ی نهایی که کاربران دریافت می‌کنندابزارهایی مثل Netlify, Vercel, AWS Amplify یا GitHub Actions برای انتشار خودکار مناسب هستند.مثال واقعی: CI/CD برای یک پروژه Reactفرض کنیم می‌خواهیم وقتی یک Pull Request ساخته شد یا کدی به main branch فرستاده شد، خودکار تست، بیلد و deploy انجام شود. اینجا یک pipeline ساده با GitHub Actions طراحی می‌کنیم.۱. ساخت فایل workflowدر پروژه، یک فولدر ایجاد می‌کنیم:.github/workflows/ci-cd.ymlمحتوا فایل :name: Frontend CI/CD

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  build-and-test:
    runs-on: ubuntu-latest

    steps:
      # 1. کلون کردن کد
      - name: Checkout code
        uses: actions/checkout@v3

      # 2. نصب Node.js
      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 20

      # 3. نصب dependencies
      - name: Install dependencies
        run: npm ci

      # 4. بررسی lint
      - name: Lint
        run: npm run lint

      # 5. اجرای تست‌ها
      - name: Run tests
        run: npm test -- --watchAll=false

      # 6. بیلد پروژه
      - name: Build
        run: npm run build

  deploy:
    needs: build-and-test
    runs-on: ubuntu-latest
    if: github.ref == &#039;refs/heads/main&#039;

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Setup Node
        uses: actions/setup-node@v3
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Build
        run: npm run build

      # 7. Deploy به Vercel (مثال)
      - name: Deploy to Vercel
        uses: amondnet/vercel-action@v20
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-args: &#039;--prod&#039;
          working-directory: .۲. توضیح مراحل واقعیمرحله ۱: Checkout codeکد پروژه از GitHub کلون می‌شود تا CI/CD روی آخرین نسخه اجرا شود.مرحله ۲: Setup NodeNode.js نصب می‌شود تا environment آماده باشد. مهم است که نسخه Node هماهنگ با پروژه باشد.مرحله ۳: Install dependenciesnpm ci dependencies را دقیقاً مطابق package-lock.json نصب می‌کند تا نسخه‌ها ثابت و قابل پیش‌بینی باشند.مرحله ۴: Lintکد توسط ESLint بررسی می‌شود. این مرحله کمک می‌کند اشتباهات رایج و ناسازگاری با استاندارد تیم سریع پیدا شود.مرحله ۵: Run testsتست‌های واحد و integration اجرا می‌شوند. اگر هر تستی fail شود، pipeline متوقف می‌شود و کد به main branch merge نمی‌شود.مرحله ۶: Buildکد Transpile و Bundle می‌شود (مثلاً با Vite). این مرحله نشان می‌دهد که اپلیکیشن آماده deploy است.مرحله ۷: Deployنسخه‌ی build شده به Vercel (یا Netlify، S3، هر سرویس دلخواه) منتشر می‌شود. با if: github.ref == &#039;refs/heads/main&#039; مطمئن می‌شویم فقط تغییرات main deploy شوند.۳. نکات مهمتقسیم jobsتست و بیلد در یک jobdeploy در job جداگانه که فقط بعد از موفقیت job قبلی اجرا می‌شود (needs: build-and-test)Secrets و Environment VariablesTokenهای deploy (مثل Vercel یا Netlify) را هرگز مستقیم داخل repo نریزیم. از GitHub Secrets استفاده می‌کنیم.Pull Request Checksبا این pipeline، هر PR قبل از merge تست و lint می‌شود. این یعنی main همیشه سالم و deployable باقی می‌ماند.Rollback آسانسرویس‌هایی مثل Vercel یا Netlify نسخه‌های قبلی را نگه می‌دارند. اگر deploy جدید مشکل داشت، می‌توان سریع rollback کرد.VisibilityGitHub Actions تمام logs را ذخیره می‌کند. می‌توانیم جزئیات خطاها را بررسی کنیم بدون اینکه دسترسی مستقیم به سرور داشته باشیم.جمع‌بندیCI/CD برای فرانت‌اند نه یک ابزار پیچیده، بلکه یک چارچوب برای اطمینان از کیفیت و سرعت توسعه است. هدف این است که هر تغییر، درست منتشر شودامیدوارم مفید باشه :)</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Mon, 05 Jan 2026 11:33:50 +0330</pubDate>
            </item>
                    <item>
                <title>React Compiler در React 19</title>
                <link>https://virgool.io/@sharareshaddev/react-compiler-%D8%AF%D8%B1-react-19-usxuhrt9psfl</link>
                <description>بازتعریف Performance در لایهی کامپایلPerformance در React سالهاست که به مجموعهای از تصمیمهای دستی وابسته بوده ؛تصمیمهایی مثل اینکه کجا memoization لازم است، چه زمانی باید identityها را پایدار نگه داشت و کدام render «واقعاً» هزینهبر است.ابزارهایی مثل useMemo، useCallback و React.memo به ما کمک کردند این کنترل را تا حدی به دست بگیریم،اما همزمان یک واقعیت را هم پررنگتر کردند:Performance در React بیش از حد به قضاوت انسانی وابسته شد.وابستگی به dependency arrayها، تشخیص renderهای غیرضروری و پیشبینی رفتار runtime،در پروژههای واقعی بهمرور به منبع پیچیدگی، خطای پنهان و کدهای fragile تبدیل شدند؛کدی که کار میکند، اما بهسختی قابل تحلیل و نگهداری است.React Compiler که بهصورت رسمی در React 19 معرفی شده،تلاش میکند این مدل ذهنی را تغییر دهد ولی نه با اضافه کردن API جدید،بلکه با انتقال بخش بزرگی از تصمیمهای Performanceز runtime و دست developer به مرحلهی compile-time.Performance تصمیم Runtime نیستPerformance یه ویژگی تصادفی نیست که موقع اجرا «ببینیم چی میشه».Performance نتیجهی تحلیل ساختاری کده.و این دقیقاً جاییه که React Compiler وارد میشه.React Compiler دقیقاً چی رو تغییر میده؟React Compiler (که قبلاً با اسم React Forget شناخته میشد)یک تغییر ذهنی مهم میاره:Performance از «الگوی کدنویسی» به «نتیجهی کامپایل» تبدیل میشه.بهجای اینکه Developer بگه:«اینجا memo کن»Compiler میگه:«من کدت رو تحلیل میکنم و خودم تصمیم میگیرم.»React Compiler چه کاری انجام میدهد؟در مرحلهی build:dependencyهای واقعی رو استاتیک تحلیل میکنهrenderهای غیرضروری رو تشخیص میدهexpressionها و componentها رو auto-memoize میکنهبدون تغییر رفتار runtime اپبیاین مثال ببینیم :قبل (React ≤ 18)const handleClick = useCallback(() =&gt; {
  submit(formData)
}, [formData])
بعد (React 19 + Compiler)function Form({ formData }) {
  const handleClick = () =&gt; {
    submit(formData)
  }
}
یا این یکی : قبل:const filteredUsers = useMemo(() =&gt; {
  return users.filter(u =&gt; u.isActive)
}, [users])
این کد خیلی تمیز به نظر میاد.اما واقعیت؟هر تغییری در reference users → recomputedependency به data structure، نه به intentاگر جای تولید users تغییر کنه، این memo بیارزش میشهاینجا Performance به دانش انسانی از upstream data وابستهست.بعد با React Compilerfunction ActiveUsers({ users }) {
  const filteredUsers = users.filter(u =&gt; u.isActive)
}
React Compiler:تشخیص میده این محاسبه pureـهفقط زمانی recompute میکنه که واقعاً لازم باشهبدون dependency array شکننده📌 نتیجه:Performance بدون قفل شدن معماری به referenceهایه مثال دیگه :) Prop drilling + memoهای زنجیرهایconst Header = React.memo(({  }) =&gt; {
  ...
})

const App = () =&gt; {
  const  = useCallback((q) =&gt; {
    search(q)
  }, [])

  return &lt;Header ={} /&gt;
}

مشکل اینجا چیه؟Parent مجبور به memo برای child شدهAPI کامپوننتها با Performance گره خوردهrefactor ساده → احتمال break شدن memoاین یعنی:Performance به interface کامپوننت نشت کردهبعد با React Compilerfunction Header({  }) {
  ...
}

function App() {
  const  = (q) =&gt; {
    search(q)
  }

  return &lt;Header ={} /&gt;
}
Compiler:تشخیص میده onSearch stableـهre-render غیرضروری رو حذف میکنهبدون اینکه API کامپوننت آلوده بشه📌 معماری تمیز میمونه، Performance هم حفظ میشه.آیا useMemo و useCallback منقرض میشن؟نه.ولی از «default behavior» به «exception» تبدیل میشن.مواردی که هنوز لازمن:تعامل با libهایی که به reference حساسنoptimizationهای بسیار خاصboundaryهای مشخص (مثلاً context providerها)همین دیگه امیدوارم مفید باشه براتون :) اینم لینک https://react.dev/learn/react-compiler/introduction برای مطالعه بیشتر  سوالی داشتین بپرسین تو کامنت ها </description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Sun, 04 Jan 2026 21:07:52 +0330</pubDate>
            </item>
                    <item>
                <title>AI Agents: چطوری ازشون بهینه استفاده کنیم؟</title>
                <link>https://virgool.io/@sharareshaddev/ai-agents-%DA%86%D8%B7%D9%88%D8%B1%DB%8C-%D8%A7%D8%B2%D8%B4%D9%88%D9%86-%D8%A8%D9%87%DB%8C%D9%86%D9%87-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-cerc4ayzvlnh</link>
                <description>چند وقتیه همه‌جا صحبت از AI Agentهاست.ولی واقعیت اینه که خیلی وقت‌ها چیزی که ساخته می‌شه،یا یه پرامپت بزرگه یا یه اسکریپت پیچیده که اسم Agent روش گذاشتن.قبل از اینکه سراغ اتومات‌سازی بریم، باید بدونیم Agent واقعاً چیه و چطور باید ازش استفاده کنیم.AI Agent دقیقاً چیه؟AI Agent یک سیستم هدف‌محوره که:فقط پاسخ نمی‌دهتصمیم می‌گیرهچند مرحله جلو می‌رهنتیجه رو ارزیابی می‌کنهو مسیرش رو اصلاح می‌کنهبه‌صورت خلاصه:Model + Goal + Memory + Tools + Control Loop = Agentمدل فکر می‌کنه،Agent فکر می‌کنه و عمل می‌کنه.چرا خیلی از Agentها شکست می‌خورن؟تجربه نشون داده مشکل معمولاً یکی از ایناست:هدف مبهمقوانین (Rules) نامشخصآزادی بیش از حدنبود معیار ارزیابیاستفاده‌ی اشتباه از ابزارهاAgent بدون محدودیت،مثل کد بدون معماریه.اصل اول: هدف باید قابل سنجش باشهپرامپت بد :Improve frontend performance.پرامپت خوب:Reduce initial load time and identify top 3 performance bottlenecks in a React SPA.Agent باید بدونه:کی موفق شده؟کی باید متوقف بشه؟اصل دوم: Rules مهم‌تر از Prompt هستناینجا جاییه که اکثر افراد اشتباه می‌کنن.Rules = خطوط قرمز Agentمثال Rule برای Frontend AgentRules:

- Do not suggest premature optimization

- Prefer architectural fixes over micro-optimizations

- Always explain impact before suggesting code changes

- Avoid adding new dependencies unless justified
اصل سوم: Control Loop شفافAgent خوب باید این چرخه رو داشته باشه:1️⃣ Analyze2️⃣ Decide3️⃣ Act4️⃣ Evaluate5️⃣ Adjustو مهم‌تر:بدونه کی باید متوقف بشهمثال :If no high-impact issues are found, stop and report.اصل چهارم: ابزار کمتر، تصمیم بهتردادن ابزار زیاد به Agent همیشه خوب نیست.بد:دسترسی به همه فایل‌هااجرای کدتغییر مستقیم سورسخوب:Read-only analysisپیشنهاد به‌جای اجراخروجی قابل review توسط انسانAgent نباید جای تصمیم نهایی رو بگیره.اصل پنجم: Human-in-the-loopبهترین Agentها:تصمیم می‌دننه تصمیم نهاییمثلاً:Architecture Review → پیشنهادPerformance Audit → اولویت‌بندیCode Review → هشدارتصمیم نهایی همیشه با انسانه.نمونه ساختار یک Agent بهینهRole: Frontend Architecture Agent

Goal:
Detect architectural and performance risks in a React SPA.

Rules:
- No code modification
- Focus on system-level issues
- Rank findings by technical impact

Process:
1. Analyze project structure
2. Identify architectural smells
3. Evaluate performance implications
4. Generate actionable recommendations
5. Stop
جمع‌بندیAgent خوب:با Rule کنترل می‌شهبا هدف مشخص شروع می‌کنهبا معیار مشخص تموم می‌شهAI Agent قرار نیست جای ما فکر کنه؛قراره تصمیم‌های بد رو زودتر لو بده.همون‌طور که:Clean Code بدون معماری خطرناکهAgent بدون Rule هم خطرناکهمنابع پیشنهادی برای مطالعه بیشترOpenAI — Best Practices for Building AgentsAnthropic — Constitutional AI &amp; Agent SafetyLangChain Documentation — Agent Design PatternsGoogle DeepMind — Planning and Reasoning in LLM-based AgentsMicrosoft — Autonomous Agents Architecture</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Sat, 03 Jan 2026 18:06:15 +0330</pubDate>
            </item>
                    <item>
                <title>Prompt Engineering Best Practices</title>
                <link>https://virgool.io/@sharareshaddev/prompt-engineering-best-practices-lslnidosh86j</link>
                <description>الان دیگه همه می‌دونیم AI ابزاریه که می‌تونه کارهای تخصصی رو سریع‌تر و بهتر انجام بده.ولی اگه ندونی چطور ازش سؤال درست بپرسی،نه‌تنها کمکی نمی‌کنه،بلکه وقتت رو هم می‌گیره تو بدترین سناریو یه پروژه کثیف تحویلت میدهPrompt Engineering یعنی چی؟پرامپت در واقع دستور ورودی به مدل‌های LLM مثل GPT یا Claude هست که می‌گه چه خروجی‌ای بدی. کیفیت پرامپت دقیقاً کیفیت پاسخ رو تعیین می‌کنه. تفاوت بین خروجی سطحی و خروجی عمیق، از پرامپت شروع می‌شه.برای اینکه خروجی AI واقعاً ارزش داشته باشه، این چهار بخش رو در پرامپتت رعایت کن:Role (نقش):از مدل بخواه در قالب یک نقش حرفه‌ای پاسخ بده.مثال: «در نقش یک معمار نرم‌افزار Frontend…» You are a Senior Frontend Architect with 8+ years of experience in large-scale SPA projects.Task (وظیفه):بگو دقیقاً چه کاری باید انجام بشه.مثال: «…معیارهای قابل‌سنجش Performance در SPA رو لیست کن.» List measurable performance metrics for a modern SPA.Context (زمینه):اطلاعات زمینه‌ای بدین تا مدل بفهمه چه اطلاعاتی بده.مثال: «…برای پروژه React با TanStack Query.» The project is built with React, Vite, and TanStack Query, and serves high-traffic users.Output (قالب خروجی):قالب دقیق خروجی رو مشخص کن:«…۵ مورد، هر کدوم با مثال و کد نمونه.»Provide 5 items For each item, include:- explanation- real-world example- code snippet (if applicable)تکنیک‌های تخصصی۱.Zero-Shot vs Few-ShotZero-shot: مستقیم‌ترین دستور رو به مدل می‌دی (برای کارهای ساده) مثل:Explain browser caching in simple terms.Few-shot: اول چند مثال می‌دی تا مدل قالب رو یاد بگیره.Example Input:Question: What is SSR?Answer: Short explanation + pros/consNow answer:What is client-side caching?۲. Chain-of-Thought (CoT)به مدل بگو «مرحله‌به‌مرحله فکر کن» تا پاسخ‌های تحلیلی‌تر بده.Explain step by step how caching affects performance in a React SPA.
Show your reasoning before the final conclusion.این باعث می‌شه منطق پشت جواب رو ببینی، نه فقط نتیجه رو.۳.Role / Persona Promptingیک «نقش» به مدل بدین تا سبک و لحن خروجی تخصصی بشه.Act as a Staff Frontend Engineer reviewing the architecture of a performance-critical web application.۴.Prompt Chainingکارهای پیچیده رو یکجا نریز سر مدل.Step 1: Propose a high-level architecture.
Step 2: Identify performance bottlenecks.
Step 3: Suggest optimizations.
Step 4: Provide final recommendations.Meta-Prompting: وقتی AI رو وادار می‌کنی بهتر فکر کنهاینجا بازی جدی می‌شه.به‌جای اینکه فقط سؤال بپرسی،از خود مدل بخواه پرامپت رو بهبود بده.Here is my prompt:[PASTE PROMPT]Rewrite it to produce more precise and actionable answers for a senior frontend audience.یاGenerate 3 improved versions of this prompt, each optimized for:1) architectural depth2) performance analysis3) practical implementationاینجا AI داره به‌عنوان Prompt Reviewer کار می‌کنه، نه فقط پاسخ‌دهنده.Prompt Auto-Optimization: آینده‌ی استفاده حرفه‌ای از AIالان داریم وارد جایی می‌شیم که:پرامپت‌ها نسخه‌بندی می‌شنخروجی‌ها ارزیابی می‌شنو پرامپت به‌صورت تکرارشونده بهتر می‌شهEvaluate your previous answer.Identify weaknesses.Refine the prompt and generate an improved response.اگه شما هم چیزی میدونید تو کامنت ها اضافه کنین :)https://www.digitalocean.com/resources/articles/prompt-engineering-best-practices?utm_source=chatgpt.com</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Fri, 02 Jan 2026 16:41:39 +0330</pubDate>
            </item>
                    <item>
                <title>Performance با Caching — Part 2</title>
                <link>https://virgool.io/@sharareshaddev/performance-%D8%A8%D8%A7-caching-%E2%80%94-part-2-dbghjviqczqd</link>
                <description>Load Strategy، Expiration و تصمیم‌هایی که دیر گرفته می‌شندر Part 1 درباره‌ی خودِ caching حرف زدیم و دیدیم ابزارهایی مثل TanStack Query چطور runtime caching رو برای ما هندل می‌کنن.اما تو پروژه‌های واقعی، مشکل معمولاً این نیست که cache نداریم؛مشکل اینه که نمی‌دونیم چی رو، کی و تا چه زمانی cache کنیم.اینجاست که load strategy و expiration وارد بازی می‌شن.Performance فقط «چقدر سریع» نیست، «کی چی لود می‌شه» استیکی از اشتباه‌های رایج اینه که همه‌چیز رو با هم لود می‌کنیم،بعد سعی می‌کنیم با cache یا memoization اوضاع رو بهتر کنیم.در حالی که ترتیب درست معمولاً اینه:اول تصمیم بگیریم چی واقعاً بحرانیهبعد مشخص کنیم چی می‌تونه دیرتر بیادو در نهایت، برای هرکدوم استراتژی cache تعریف کنیمLazy-loading: وقتی واقعاً لازم نیست الان بیادLazy-loading یعنی:چیزی رو لود نکن، مگر اینکه کاربر واقعاً بهش نیاز داشته باشه.مثلاً:یک tab ثانویهیک modal سنگینیک صفحه‌ی تنظیمات که شاید ۱۰٪ کاربران ببینندر SPAها، lazy-loading اگر با cache ترکیب نشه، تبدیل می‌شه به:«هر بار دیر لود می‌شه»اما وقتی درست استفاده بشه:بار اول lazy-loadدفعات بعد از cacheو این دقیقاً جاییه که ابزارهایی مثل TanStack Query به ما کمک مکنه.Preload: وقتی می‌دونی قراره لازم بشهPreload یعنی:«می‌دونم کاربر به‌زودی اینو می‌خواد، بذار زودتر بیارمش»مثال‌های رایج:دیتای صفحه‌ی بعد از کلیکاطلاعاتی که بعد از login بلافاصله استفاده می‌شنrouteهایی که احتمال ورود بهشون بالاستدر این حالت:preload بدون cache = مصرف بی‌دلیل شبکهpreload + cache = تجربه‌ی خیلی نرمCache Expiration: مهم‌ترین بخشی که معمولاً نادیده گرفته می‌شهیکی از خطرناک‌ترین حالت‌ها:cache درست کار می‌کنه، ولی داده‌ها قدیمی‌اناینجاست که مفهوم stale مهم می‌شه.در TanStack Query:داده می‌تونه cache باشهولی stale باشهو در background آپدیت بشهمثال ساده:useQuery([&#039;products&#039;], fetchProducts, {
  staleTime: 5 * 60 * 1000
})یعنی:تا ۵ دقیقه داده «قابل اعتماد» حساب می‌شهبعد از اون:داده سریع از cache نمایش داده می‌شهولی fetch جدید در پس‌زمینه انجام می‌شهاین یعنی:UX سریعبدون نمایش دیتای خیلی قدیمیبدون blocking UIInvalidation: وقتی تغییر اتفاق می‌افتهبعضی داده‌ها رو نمی‌شه فقط با زمان کنترل کرد.مثلاً:بعد از submit فرمبعد از update پروفایلبعد از تغییر وضعیت یک entityاینجا cache باید آگاهانه invalidate بشهqueryClient.invalidateQueries([&#039;user&#039;])این یعنی:«می‌دونم چیزی تغییر کرده، برو دوباره fetch کن»و این تفاوت بزرگیه بین:cache تصادفیcache معماری‌شدهجمع‌بندی Part 2Performance فقط به cache داشتن نیستLoad strategy (lazy vs preload) به اندازه‌ی cache مهمهCache بدون expiration = بدهی فنیابزارها مشکل رو حل نمی‌کنن، تصمیم‌های درست حل می‌کنناگر از اول بدونی چی قراره کی استفاده بشه،caching خودش تبدیل می‌شه به یک مزیت معماری، نه یک patch..</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Fri, 02 Jan 2026 15:48:05 +0330</pubDate>
            </item>
                    <item>
                <title>Performance با Caching — Part 1</title>
                <link>https://virgool.io/@sharareshaddev/performance-%D8%A8%D8%A7-caching-%E2%80%94-part-1-iancvjjgnnpu</link>
                <description>در Frontend فقط به کاهش حجم باندل یا بهینه‌سازی CSS و JS خلاصه نمی‌شه.یکی از مهم‌ترین عوامل تجربه سریع و روان کاربر، Caching هست.اما اکثر تیم‌ها وقتی از caching حرف می‌زنن، فقط به فکر localStorage یا چند header HTTP هستن جلوتر براتون توضیح میدم دقیقا چجوری میشه پرفورمنسو بهترش کرد و از سمتی یه ابزار خفن هم داریم که به شما خیلی کمک خواهد کرد.هدف این پارت: کشف دقیق caching، انواعش و چگونگی تاثیرش روی Performance.Caching چیه؟Caching یعنی ذخیره‌ی موقت داده یا منابع به گونه‌ای که دفعه بعد نیاز به بارگذاری مجدد نداشته باشه.داده‌ها دوباره fetch نمی‌شنکاربر تجربه سریع‌تری خواهد داشتفشار روی سرور و شبکه کم می‌شهدر Frontend، چند سطح caching داریم: Runtime، Build-time و Persistent (LocalStorage / IndexedDB).نکته کلیدی: انتخاب استراتژی مناسب caching، تاثیر مستقیم روی Performance و معماری پروژه دارد.Runtime cachingداده‌هایی که تو حافظه برنامه نگه‌داشته می‌شنمثال: Map یا state محلی برای جلوگیری از fetch تکراریمزیت: سریع‌ترین دسترسی، بدون درخواست شبکهBuild-time cachingداده‌ها یا assetهایی که هنگام build تولید می‌شن و تغییر نمی‌کننمثال: CSS، JS bundle، تصاویر بهینه‌شدهمزیت: کاهش load روی سرور و مرورگرPersistent caching (LocalStorage / IndexedDB)داده‌ها روی مرورگر ذخیره می‌شن و بین سشن‌ها باقی می‌موننمزیت: کاهش fetchهای بعدی و تجربه کاربر سریع‌ترچرا Caching مهمه؟کاهش تعداد request ها → کاهش زمان بارگذاریکاهش فشار روی سرور و شبکه → مقیاس‌پذیری بهترافزایش سرعت perceived load → تجربه کاربر بهترارتباط مستقیم با معماری → اگر درست تعریف نشه، بعداً تغییرش پرهزینه می‌شهتجربه واقعی: پروژه‌ای داشتم که تمام داده‌های API بدون cache بارگذاری می‌شد.نتیجه: حتی با کد بهینه، هر بار که کاربر صفحه را رفرش می‌کرد، 2–3 ثانیه اضافی load اضافه می‌شد.بعد از پیاده‌سازی runtime + persistent caching، TTI از 4.5s به 1.8s رسید.مثال (Runtime Caching) const cache = new Map();

async function fetchUserData(userId) {

  if (cache.has(userId)) {

    return cache.get(userId); // استفاده از داده کش‌شده

  }

  const response = await fetch/api/users/${userId});

  const data = await response.json();

  cache.set(userId, data); // ذخیره در cache

  return data;مزیت: دفعه بعد که همون کاربر فراخوانی می‌شه، request به شبکه نمی‌رهتاثیر: کاهش latency و تجربه سریع‌تر کاربرابزار خفن: TanStack Queryحالا یک ابزار فوق‌العاده داریم که تمام کارهای caching runtime را برای ما ساده می‌کنه:ذخیره‌سازی داده‌ها به صورت خودکارRefresh و invalidation هوشمندBackground fetching برای تجربه کاربری سریعمی‌تونید ببینید پشت پرده چجوری کار می‌کنه و پیشنهاد می‌کنم حتماً استفاده‌اش کنید.مثال ۱ — Query سادهimport { useQuery } from &#039;@tanstack/react-query&#039;;

function fetchUser(userId) {
  return fetch(`/api/users/${userId}`).then(res =&gt; res.json());
}

export function User({ userId }) {
  const { data, isLoading } = useQuery([&#039;user&#039;, userId], () =&gt; fetchUser(userId), {
    staleTime: 1000 * 60 * 5, // 5 دقیقه cache
  });

  if (isLoading) return &lt;div&gt;Loading...&lt;/div&gt;;
  return &lt;div&gt;{data.name}&lt;/div&gt;;
}
دفعه بعد که همین userId فراخوانی بشه، داده از cache گرفته می‌شه و request اضافی نمی‌ره.مثال ۲ — استفاده از Cache با Invalidatonconst queryClient = useQueryClient();

function updateUser(userId, newData) {
  return fetch(`/api/users/${userId}`, {
    method: &#039;POST&#039;,
    body: JSON.stringify(newData),
  }).then(() =&gt; {
    queryClient.invalidateQueries([&#039;user&#039;, userId]); // داده قدیمی refresh می‌شه
  });
}
جمع‌بندیCaching یعنی ذخیره موقت داده یا منابع برای بارگذاری سریع‌ترPerformance واقعی از تصمیمات درست در caching و معماری حاصل می‌شهابزارهایی مثل TanStack Query می‌تونن همه این اصول را برای ما ساده و عملی کننددر Part 2 قراره ببینیم چطور Lazy-loading، Preload و Cache Expiration رو در پروژه واقعی مدیریت کنیم تا Performance واقعاً بهینه بشه.با من همراه باشین :)</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Fri, 02 Jan 2026 12:21:14 +0330</pubDate>
            </item>
                    <item>
                <title>بهینه‌سازی بارگذاری صفحه با Critical CSS در SPAها</title>
                <link>https://virgool.io/@sharareshaddev/%D8%A8%D9%87%DB%8C%D9%86%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D8%A8%D8%A7%D8%B1%DA%AF%D8%B0%D8%A7%D8%B1%DB%8C-%D8%B5%D9%81%D8%AD%D9%87-%D8%A8%D8%A7-critical-css-%D8%AF%D8%B1-spa%D9%87%D8%A7-ztzubvubgqnh</link>
                <description>یکی از چالش‌های اصلی در SPAها، مدیریت منابع CSS است، به‌ویژه زمانی که فایل‌های CSS سنگین باشند و در سرعت بارگذاری صفحه تأثیر بگذارند.راه‌حل؟ Critical CSS!حالا چی هست؟مجموعه‌ای از استایل‌ها اشاره داره که برای رندر اولیه صفحه ضروریه و باید به محض لود شدن صفحه، بارگذاری شوند تا تجربه کاربری بهتر و زمان لود صفحه سریع‌تری فراهم شود.در SPAها، جایی که تنها بخش‌هایی از صفحه به‌طور داینامیک بارگذاری و رندر می‌شوند، می‌توان از این تکنیک برای حداقل کردن بارگذاری فایل‌های CSS استفاده کرد و تنها استایل‌های ضروری برای نمایش سریع‌تر صفحه را بارگذاری کرد.چرا مهمه؟بهبود زمان LCP (Largest Contentful Paint): بارگذاری سریع CSS ضروری، باعث می‌شود که محتوا سریع‌تر نمایش داده شود.کاهش زمان TTI (Time to Interactive): با بارگذاری CSS ضروری به محض بارگذاری صفحه، می‌توانید صفحه را سریع‌تر به حالت تعاملی درآورید.کاهش رندر غیرضروری: بدون Critical CSS، مرورگر مجبور است تمام CSS را بارگذاری کند، حتی آن‌هایی که در رندر اولیه صفحه ضروری نیستند. این باعث کندی بیشتر می‌شود.چطور Critical CSS را در SPAها پیاده‌سازی کنیم؟تحلیل صفحه: ابتدا باید CSS حیاتی که برای رندر بخش‌های ابتدایی صفحه نیاز است را شناسایی کنید. ابزارهایی مانند Critical و PurgeCSS می‌توانند به شناسایی این CSS کمک کنند.ایجاد فایل‌های Critical CSS: بعد از شناسایی، می‌توانیم فقط بخش‌های ضروری CSS را به‌صورت inline در &lt;head&gt; صفحه قرار دهیم تا فوراً لود شوند.&lt;style&gt;/* Critical CSS: Only the essential styles */.header { ... }.button { ... }&lt;/style&gt;لیزی لود برای باقی CSS: برای سایر استایل‌ها که برای رندر اولیه صفحه ضروری نیستند، می‌توانیم از lazy loading استفاده کنیم و آن‌ها را پس از بارگذاری اولین محتوای صفحه لود کنیم.const link = document.createElement(&#039;link&#039;);link.rel = &#039;stylesheet&#039;;link.href = &#039;styles/non-critical.css&#039;;document.head.appendChild(link);استفاده از ابزارهای اتوماتیک: ابزارهایی مانند Webpack، Vite یا Parcel می‌توانند به‌صورت خودکار فایل‌های CSS ضروری را استخراج کرده و تنها آن‌ها را به صفحه اضافه کنند.مزایای استفاده از Critical CSS در SPAها:بهبود زمان بارگذاری: فقط CSS مورد نیاز برای رندر اولین بخش‌های صفحه بارگذاری می‌شود.بهینه‌سازی تجربه کاربری: از آنجایی که بخش‌های حیاتی صفحه سریع‌تر بارگذاری می‌شوند، کاربر زودتر می‌تواند تعاملات با صفحه را آغاز کند.کاهش درخواست‌ها: از ارسال CSS‌های اضافی و بی‌فایده جلوگیری می‌کند که به کاهش حجم فایل‌های دانلودی کمک می‌کند.نتیجه‌گیریاستفاده از Critical CSS در SPAها به بهینه‌سازی بارگذاری صفحه و بهبود عملکرد کمک شایانی می‌کند. به این ترتیب، کاربران تجربه سریع‌تر و روان‌تری خواهند داشت و SEO و رتبه‌بندی سایت شما بهبود خواهد یافت.#WebPerformance #CSS #SPA #CriticalCSS #Frontend #WebDev #PerformanceOptimization</description>
                <category>شراره شادالو</category>
                <author>شراره شادالو</author>
                <pubDate>Wed, 28 May 2025 11:57:00 +0330</pubDate>
            </item>
            </channel>
</rss>