چه زمانی باید اولویت بارگذاری را مشخص کنیم؟ 🤔
لود تنبل (loading="lazy") بسیار کاربردی است: با بهتعویقانداختن بارگذاری تصاویری که هنوز در دید کاربر نیستند، هم در مصرف ترافیک صرفهجویی میکند و هم سرعت بارگذاری صفحه را افزایش میدهد.
اما اگر برای تصاویر حیاتی اولویت مشخص نکنید، مرورگر خودش درباره ترتیب بارگذاری تصمیم میگیرد — و این تصمیم همیشه با اهداف شما همراستا نیست. ☹️ در نتیجه ممکن است تصویر اصلی یا هدر دیرتر از حد لازم لود شود؛ این موضوع LCP را تضعیف میکند و حس «کند بودن» صفحه را به کاربر منتقل میکند. اگر ابعاد تصویر هم از قبل مشخص نشده باشند، حتی میتواند به CLS منجر شود.
🧩 چه کار باید کرد؟
✔️ برای تصاویر غیرحیاتی — با خیال راحت از loading="lazy" استفاده کنید. هم ترافیک را کاهش میدهد و هم به UX آسیبی نمیزند.
✔️ برای تصاویر حیاتی در اسکرین اول — فقط به loading="lazy" تکیه نکنید:
✨ یا loading="lazy" را حذف کنید،
✨ یا اولویت را صراحتاً مشخص کنید (fetchpriority="high")،
✨ یا منبع را پیشبارگذاری کنید (<link rel="preload" as="image" href="…">).
✔️ همیشه width و height را مشخص کنید یا از aspect-ratio استفاده کنید — این کار جلوی CLS را میگیرد.
✔️ از srcset و sizes (و فرمتهای مدرن مثل WebP و AVIF) استفاده کنید — تا مرورگر بتواند بهترین فایل را متناسب با دستگاه انتخاب کند.
✔️ LCP را در شرایط واقعی بررسی کنید — تستهای لوکال همیشه رفتار واقعی در ذکر را بازتاب نمیدهند.
🧩 مثال:
🧩 چند اشتباه رایج:
⏺️ اعمال loading="lazy" روی همه تصاویر بدون استثنا — و از دست دادن کنترل روی LCP؛
⏺️ تکیه صرف بر fetchpriority و فراموشکردن preload و فرمتهای تطبیقی؛
⏺️ پیشبارگذاری تعداد زیادی منبع — که میتواند کل فرایند بارگذاری را بدتر کند.
در نهایت، لود تنبل را باید بهصورت گزینشی استفاده کرد. برای تصاویر اسکرین اول، اولویت را صریحاً مشخص کنید (با preload یا fetchpriority) یا اصلاً آنها را تنبل لود نکنید؛ برای بقیه تصاویر، با خیال راحت از لود تنبل استفاده کنید. به این شکل هم در مصرف ترافیک صرفهجویی میکنید و هم تجربهای سریع و قابلپیشبینی به کاربر میدهید. 👍
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
لود تنبل (loading="lazy") بسیار کاربردی است: با بهتعویقانداختن بارگذاری تصاویری که هنوز در دید کاربر نیستند، هم در مصرف ترافیک صرفهجویی میکند و هم سرعت بارگذاری صفحه را افزایش میدهد.
اما اگر برای تصاویر حیاتی اولویت مشخص نکنید، مرورگر خودش درباره ترتیب بارگذاری تصمیم میگیرد — و این تصمیم همیشه با اهداف شما همراستا نیست. ☹️ در نتیجه ممکن است تصویر اصلی یا هدر دیرتر از حد لازم لود شود؛ این موضوع LCP را تضعیف میکند و حس «کند بودن» صفحه را به کاربر منتقل میکند. اگر ابعاد تصویر هم از قبل مشخص نشده باشند، حتی میتواند به CLS منجر شود.
🧩 چه کار باید کرد؟
✔️ برای تصاویر غیرحیاتی — با خیال راحت از loading="lazy" استفاده کنید. هم ترافیک را کاهش میدهد و هم به UX آسیبی نمیزند.
✔️ برای تصاویر حیاتی در اسکرین اول — فقط به loading="lazy" تکیه نکنید:
✨ یا loading="lazy" را حذف کنید،
✨ یا اولویت را صراحتاً مشخص کنید (fetchpriority="high")،
✨ یا منبع را پیشبارگذاری کنید (<link rel="preload" as="image" href="…">).
✔️ همیشه width و height را مشخص کنید یا از aspect-ratio استفاده کنید — این کار جلوی CLS را میگیرد.
✔️ از srcset و sizes (و فرمتهای مدرن مثل WebP و AVIF) استفاده کنید — تا مرورگر بتواند بهترین فایل را متناسب با دستگاه انتخاب کند.
✔️ LCP را در شرایط واقعی بررسی کنید — تستهای لوکال همیشه رفتار واقعی در ذکر را بازتاب نمیدهند.
🧩 مثال:
<!-- تصویر مهم -->
<link rel="preload" as="image" href="/image.jpg">
<img src="/image.jpg" width="1200" height="600" fetchpriority="high" alt="...">
<!-- تصویر غیرحیاتی -->
<img src="/thumb.jpg" loading="lazy" width="400" height="300" alt="...">
🧩 چند اشتباه رایج:
⏺️ اعمال loading="lazy" روی همه تصاویر بدون استثنا — و از دست دادن کنترل روی LCP؛
⏺️ تکیه صرف بر fetchpriority و فراموشکردن preload و فرمتهای تطبیقی؛
⏺️ پیشبارگذاری تعداد زیادی منبع — که میتواند کل فرایند بارگذاری را بدتر کند.
در نهایت، لود تنبل را باید بهصورت گزینشی استفاده کرد. برای تصاویر اسکرین اول، اولویت را صریحاً مشخص کنید (با preload یا fetchpriority) یا اصلاً آنها را تنبل لود نکنید؛ برای بقیه تصاویر، با خیال راحت از لود تنبل استفاده کنید. به این شکل هم در مصرف ترافیک صرفهجویی میکنید و هم تجربهای سریع و قابلپیشبینی به کاربر میدهید. 👍
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
❤2👍1
پردازش ترکیبهای کلیدی 🧑💻
از ترکیبهای کلیدی برای کارهای رایج استفاده میشود: ذخیره دادهها، جابهجایی بین صفحات، یا افزایش سرعت کار. در JavaScript پیادهسازی این موضوع نسبتاً ساده است، به شرطی که بدانیم رویدادهای صفحهکلید چگونه کار میکنند.
کمی تئوری
✔️ ترکیب کلید در واقع یک رویداد واحد keydown است که داخل آن بررسی میکنیم:
⏺️ کدام کلید فشرده شده است؛
⏺️ آیا کلیدهای کمکی (Ctrl، Shift، Alt، Meta) نگه داشته شدهاند یا نه؛
✔️ در مرورگر رویداد جداگانهای با نام «Ctrl+S» وجود ندارد — همهچیز با شرطگذاری انجام میشود.
ویژگیهای مهم رویداد
✔️ event.key — کاراکتر یا نام کلید (مثل
✔️ event.code — کلید فیزیکی روی کیبورد (مثل
✔️ event.ctrlKey، event.shiftKey، event.altKey، event.metaKey — کلیدهای کمکی.
مثال ساده: Ctrl + S
به چه نکاتی باید توجه کرد؟
✨ هنگام تایپ در input و textarea، هاتکیها را رهگیری نکنید؛
✨ در macOS معمولاً بهجای Ctrl از Meta (کلید Cmd) استفاده میشود؛
✨ نگهداشتن یک کلید باعث تکرار چندباره رویداد keydown میشود؛
✨ برای هاتکیها بهتر است از event.code استفاده کنید تا به چیدمان کیبورد وابسته نباشید.
و در نهایت، در استفاده از هاتکیهای سراسری زیادهروی نکنید — آنها باید مکمل رابط کاربری باشند، نه جایگزین آن. 😁
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
از ترکیبهای کلیدی برای کارهای رایج استفاده میشود: ذخیره دادهها، جابهجایی بین صفحات، یا افزایش سرعت کار. در JavaScript پیادهسازی این موضوع نسبتاً ساده است، به شرطی که بدانیم رویدادهای صفحهکلید چگونه کار میکنند.
کمی تئوری
✔️ ترکیب کلید در واقع یک رویداد واحد keydown است که داخل آن بررسی میکنیم:
⏺️ کدام کلید فشرده شده است؛
⏺️ آیا کلیدهای کمکی (Ctrl، Shift، Alt، Meta) نگه داشته شدهاند یا نه؛
✔️ در مرورگر رویداد جداگانهای با نام «Ctrl+S» وجود ندارد — همهچیز با شرطگذاری انجام میشود.
ویژگیهای مهم رویداد
✔️ event.key — کاراکتر یا نام کلید (مثل
"a" یا "Enter")؛✔️ event.code — کلید فیزیکی روی کیبورد (مثل
"KeyA" یا "Enter")؛✔️ event.ctrlKey، event.shiftKey، event.altKey، event.metaKey — کلیدهای کمکی.
مثال ساده: Ctrl + S
document.addEventListener('keydown', (event) => {
if (event.ctrlKey && event.code === 'KeyS') {
event.preventDefault(); // در صورت نیاز، رفتار پیشفرض را لغو میکنیم
// منطق موردنظر ما
}
});به چه نکاتی باید توجه کرد؟
✨ هنگام تایپ در input و textarea، هاتکیها را رهگیری نکنید؛
✨ در macOS معمولاً بهجای Ctrl از Meta (کلید Cmd) استفاده میشود؛
✨ نگهداشتن یک کلید باعث تکرار چندباره رویداد keydown میشود؛
✨ برای هاتکیها بهتر است از event.code استفاده کنید تا به چیدمان کیبورد وابسته نباشید.
و در نهایت، در استفاده از هاتکیهای سراسری زیادهروی نکنید — آنها باید مکمل رابط کاربری باشند، نه جایگزین آن. 😁
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
سادهترین روش برای غیرفعال کردن چندین عنصر فرم
میتوانیم ویژگی «غیرفعال» را روی عنصر <fieldset> قرار دهیم تا بهطور خودکار تمامی عناصر فرم تو در تو غیرفعال شوند.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
میتوانیم ویژگی «غیرفعال» را روی عنصر <fieldset> قرار دهیم تا بهطور خودکار تمامی عناصر فرم تو در تو غیرفعال شوند.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
تشخیص زمانی که کاربر بین تبهای مرورگر جابهجا میشود و تغییر favicon
این ترفند را میتوان با استفاده از Page Visibility API پیادهسازی کرد.
Page Visibility API یک رابط برنامهنویسی مرورگر است که قابل مشاهده بودن صفحه را بررسی میکند. این API کمک میکند تا تشخیص دهیم آیا صفحهی جاری پنهان یا کوچک شده است و از این طریق امکان کنترل رفتار صفحه و مدیریت استفاده از منابع فراهم میشود.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
این ترفند را میتوان با استفاده از Page Visibility API پیادهسازی کرد.
Page Visibility API یک رابط برنامهنویسی مرورگر است که قابل مشاهده بودن صفحه را بررسی میکند. این API کمک میکند تا تشخیص دهیم آیا صفحهی جاری پنهان یا کوچک شده است و از این طریق امکان کنترل رفتار صفحه و مدیریت استفاده از منابع فراهم میشود.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
نود و نه درصد توسعهدهندگان از این ترفند در Chrome DevTools خبر ندارند 🤯
میتوانید تم تاریک را روی هر سایتی فعال کنید، حتی اگر آن سایت خود تم تاریک نداشته باشد. برای این کار، DevTools را باز کرده، روی آیکون قلممو کلیک کنید و گزینهی Automatic Dark Mode را انتخاب نمایید.
این روش برای زمانی که در حال طراحی تم تاریک برای وبسایت خود هستید ایدهآل است — شما فوراً پیشنمایشی از رابط کاربری تقریباً نود درصدی دریافت میکنید.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
میتوانید تم تاریک را روی هر سایتی فعال کنید، حتی اگر آن سایت خود تم تاریک نداشته باشد. برای این کار، DevTools را باز کرده، روی آیکون قلممو کلیک کنید و گزینهی Automatic Dark Mode را انتخاب نمایید.
این روش برای زمانی که در حال طراحی تم تاریک برای وبسایت خود هستید ایدهآل است — شما فوراً پیشنمایشی از رابط کاربری تقریباً نود درصدی دریافت میکنید.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
❤3
This media is not supported in your browser
VIEW IN TELEGRAM
نکتهای درباره Chrome DevTools: بررسی سبکهای placeholder
بهطور پیشفرض، Chrome DevTools سبکهای ::placeholder را هنگام بازرسی عناصر نمایش نمیدهد.
میتوان با فعال کردن تنظیم Show user agent shadow DOM، shadow DOM مرورگر را که برای عناصر داخلی مختلف مانند <input>، <progress>، <video> و غیره ایجاد میشود، مشاهده کرد.
با بررسی این عناصر shadow DOM که توسط user agent ایجاد شدهاند، میتوان سبکهای placeholder، نوار لغزندهی ورودیهای نوع range و موارد مشابه را مشاهده و ویرایش کرد.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
بهطور پیشفرض، Chrome DevTools سبکهای ::placeholder را هنگام بازرسی عناصر نمایش نمیدهد.
میتوان با فعال کردن تنظیم Show user agent shadow DOM، shadow DOM مرورگر را که برای عناصر داخلی مختلف مانند <input>، <progress>، <video> و غیره ایجاد میشود، مشاهده کرد.
با بررسی این عناصر shadow DOM که توسط user agent ایجاد شدهاند، میتوان سبکهای placeholder، نوار لغزندهی ورودیهای نوع range و موارد مشابه را مشاهده و ویرایش کرد.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
پژوهشگران ۳۷ هزار رزومهٔ جعلی از فارغالتحصیلان را ارسال کردند و بررسی کردند که چه کسانی بیشتر به مصاحبه دعوت میشوند [+لینک].
در این رزومهها همهچیز بهصورت تصادفی تغییر داده شده بود: رشتهٔ تحصیلی، دورههای کارآموزی، تحصیل در خارج از کشور و مهارتهای کامپیوتری. نتایج جالبی که بهطور غیرمنتظره جواب داد:
— کارآموزیهایی که بر توسعهٔ مهارتهای نرم (Soft Skills) تمرکز دارند؛ آن هم حتی در درخواست برای موقعیتهای شغلی تحلیلی(فقط بلد بودن کافی نیست شرکتها به این هم توجه میکنند که آیا طرف «مهارتهای انسانی» دارد یا نه) .
— تحصیل در خارج از کشور، همانطور که انتظار میرفت، شانس پیدا کردن سریع اولین شغل را افزایش میدهد.
— ترکیب برنامهنویسی + تحلیل دادهها یک امتیاز خیلی بزرگ برای دریافت تماس مجدد (دعوت به مصاحبه) ایجاد میکند. در حالی که هرکدام از این مهارتها بهتنهایی چنین اثری ندارند.
#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
در این رزومهها همهچیز بهصورت تصادفی تغییر داده شده بود: رشتهٔ تحصیلی، دورههای کارآموزی، تحصیل در خارج از کشور و مهارتهای کامپیوتری. نتایج جالبی که بهطور غیرمنتظره جواب داد:
— کارآموزیهایی که بر توسعهٔ مهارتهای نرم (Soft Skills) تمرکز دارند؛ آن هم حتی در درخواست برای موقعیتهای شغلی تحلیلی(فقط بلد بودن کافی نیست شرکتها به این هم توجه میکنند که آیا طرف «مهارتهای انسانی» دارد یا نه) .
— تحصیل در خارج از کشور، همانطور که انتظار میرفت، شانس پیدا کردن سریع اولین شغل را افزایش میدهد.
— ترکیب برنامهنویسی + تحلیل دادهها یک امتیاز خیلی بزرگ برای دریافت تماس مجدد (دعوت به مصاحبه) ایجاد میکند. در حالی که هرکدام از این مهارتها بهتنهایی چنین اثری ندارند.
#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
Ssrn
Unbundling the Effects of College on First-Job Search: Returns to Majors, Minors, and Extracurriculars
We analyze the initial job-market matching of new US college graduates with a largescale audit study conducted during 2016 and 2017, in which 36,880 resumes of
ترجمهٔ روان به فارسی:
فرض کنید در CSS یک گرید ۵×۵ دارید. داخل این گرید عناصری با اندازههای مختلف قرار گرفتهاند، اما به موقعیتهای مشخصی ثابت نشدهاند.
در چنین حالتی، استفاده از حالت `dense` برای ویژگی `grid-auto-flow` باعث میشود خانههای خالیای که توسط عناصر قبلی ایجاد شدهاند، پر شوند. به این شکل، عناصر بعدی که اندازهشان اجازه میدهد، به این فضاهای خالی منتقل میشوند.
این قابلیت مثلاً برای گالری تصاویر بسیار مفید است؛ جایی که عناصر (تصاویر) اندازههای تصادفی و متفاوتی دارند.
نمونه کد:
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
فرض کنید در CSS یک گرید ۵×۵ دارید. داخل این گرید عناصری با اندازههای مختلف قرار گرفتهاند، اما به موقعیتهای مشخصی ثابت نشدهاند.
در چنین حالتی، استفاده از حالت `dense` برای ویژگی `grid-auto-flow` باعث میشود خانههای خالیای که توسط عناصر قبلی ایجاد شدهاند، پر شوند. به این شکل، عناصر بعدی که اندازهشان اجازه میدهد، به این فضاهای خالی منتقل میشوند.
این قابلیت مثلاً برای گالری تصاویر بسیار مفید است؛ جایی که عناصر (تصاویر) اندازههای تصادفی و متفاوتی دارند.
نمونه کد:
.grid {
grid-template-rows: repeat(5, 10rem);
grid-template-columns: repeat(5, 10rem);
}
.item-2 {
grid-row-end: span 2;
grid-column-end: span 2;
}#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👏1
نکتهٔ CSS: سلکتور اتریبیوت بدون حساسیت به حروف بزرگ و کوچک
در CSS میتوانیم با اضافه کردن حرف i به سلکتور اتریبیوت، کاری کنیم که انتخاب عناصر نسبت به حروف بزرگ و کوچک حساس نباشد.
یعنی فرقی نمیکند مقدار اتریبیوت با حروف بزرگ نوشته شده باشد یا کوچک؛ در هر صورت انتخاب میشود.
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
در CSS میتوانیم با اضافه کردن حرف i به سلکتور اتریبیوت، کاری کنیم که انتخاب عناصر نسبت به حروف بزرگ و کوچک حساس نباشد.
یعنی فرقی نمیکند مقدار اتریبیوت با حروف بزرگ نوشته شده باشد یا کوچک؛ در هر صورت انتخاب میشود.
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍4
آیا میدانستید دکمهٔ ارسال فرم میتواند خارج از خود فرم قرار بگیرد؟
در بیشتر مواقع، دکمهٔ ارسال را داخل تگ <form> قرار میدهیم و این کار کاملاً درست است.
اما گاهی بهدلیل محدودیتهای چیدمان (layout) یا دلایل دیگر، منطقیتر است که دکمهٔ ارسال بیرون از تگ <form> قرار داده شود.
در این حالت میتوانیم بهسادگی با استفاده از ویژگیهای form و id دکمه را به فرم موردنظر متصل کنیم.
به همین روش، در صورت نیاز میتوان سایر عناصر کنترلی مثل textarea، checkbox و موارد مشابه را هم به یک فرم خاص مرتبط کرد، حتی اگر خارج از آن فرم قرار داشته باشند.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
در بیشتر مواقع، دکمهٔ ارسال را داخل تگ <form> قرار میدهیم و این کار کاملاً درست است.
اما گاهی بهدلیل محدودیتهای چیدمان (layout) یا دلایل دیگر، منطقیتر است که دکمهٔ ارسال بیرون از تگ <form> قرار داده شود.
در این حالت میتوانیم بهسادگی با استفاده از ویژگیهای form و id دکمه را به فرم موردنظر متصل کنیم.
به همین روش، در صورت نیاز میتوان سایر عناصر کنترلی مثل textarea، checkbox و موارد مشابه را هم به یک فرم خاص مرتبط کرد، حتی اگر خارج از آن فرم قرار داشته باشند.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍3❤1👌1
این ۴ خط را به فایل `.vscode/settings.json` اضافه کنید تا تجربهٔ توسعهتان بلافاصله راحتتر و خواناتر شود.
با این تنظیمات، نام تبها در VS Code واضحتر نمایش داده میشود (مثلاً مشخص میشود هر
نتیجه:
وقتی چندین فایل
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
با این تنظیمات، نام تبها در VS Code واضحتر نمایش داده میشود (مثلاً مشخص میشود هر
page یا layout مربوط به کدام پوشه است):{
"workbench.editor.customLabels.patterns": {
"**/app/**/{page,layout,index}.{ts,tsx}": "(${dirname})/${filename}.${extname}",
"**/index.{ts,tsx}": "${dirname}/index.${extname}"
}
}نتیجه:
وقتی چندین فایل
page.tsx یا layout.tsx باز دارید، دیگر همه شبیه هم دیده نمیشوند و سریعتر متوجه میشوید هر فایل به کدام مسیر یا بخش پروژه تعلق دارد.#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
غولِ دوستداشتنی ما: TypeScript به محبوبترین زبان برنامهنویسی در GitHub تبدیل شد 🥳
و اگر JavaScript و TypeScript را با هم حساب کنیم، اختلاف با بقیه زبانها واقعاً چشمگیر میشود.
گزارش کامل GitHub برای سال ۲۰۲۵:
https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/
#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
و اگر JavaScript و TypeScript را با هم حساب کنیم، اختلاف با بقیه زبانها واقعاً چشمگیر میشود.
گزارش کامل GitHub برای سال ۲۰۲۵:
https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/
#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
❤2
در اینترنت به یک ابزار تحلیل CSS جالب برخوردم که میتواند هر وبسایتی را بررسی کند. این سرویس قادر است میزان و مقایسهٔ ویژگی اختصاصیبودن سلکتورها را محاسبه کند، پالت رنگی، سایهها، حاشیهها، متغیرهای CSS و چیدمانهای گرید را نمایش دهد. حتی تلاش میکند پیشنهاد دهد که آیا مهاجرت به کلاسهای اتمیک منطقی است یا خیر.
صادقانه بگویم، برای پیدا کردن ناهنجاریها در یک سایت، ابزار بسیار کارآمدی است؛ از اندازههای اعشاری و متغیرهای غیرمنتظره گرفته تا فونتهای پیشبینینشده. حتی میتوان نگاهی به کدنویسی رقبا انداخت و ایرادهای نهچندان ایدئال آنها را دید و کمی هم حس رضایت شخصی را تقویت کرد. امکان مقایسهٔ دو نسخهٔ متفاوت از یک سایت نیز فراهم است.
🔗https://cssstats.com/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
صادقانه بگویم، برای پیدا کردن ناهنجاریها در یک سایت، ابزار بسیار کارآمدی است؛ از اندازههای اعشاری و متغیرهای غیرمنتظره گرفته تا فونتهای پیشبینینشده. حتی میتوان نگاهی به کدنویسی رقبا انداخت و ایرادهای نهچندان ایدئال آنها را دید و کمی هم حس رضایت شخصی را تقویت کرد. امکان مقایسهٔ دو نسخهٔ متفاوت از یک سایت نیز فراهم است.
🔗https://cssstats.com/
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
❤1
فشردهسازی میتواند حجم فایل یک SVG را بدون کاهش کیفیت بصری آن کاهش دهد. برای این کار میتوانید از ابزارهای آنلاین مختلفی مانند SVGOMG یا iLoveIMG استفاده کنید که فرایند فشردهسازی را ساده میکنند. کافی است فایل SVG خود را در این ابزارها بارگذاری کنید و تنظیمات فشردهسازی دلخواه را اعمال نمایید. سپس میتوانید آن را بهعنوان یک فایل جدید ذخیره و دانلود کنید. حتماً فایل را با نامی متفاوت ذخیره کنید تا نسخهٔ فشردهشده را از نسخهٔ اصلی تشخیص دهید (هرچند نسخهٔ فشردهشده باید حجم کمتری داشته باشد).
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
بدون robots.txt — بدون حضور در نتایج Google
موضوعی غیرمنتظره. Alan Smith یک مورد جالب را به اشتراک میگذارد: در مقطعی، ترافیک ارگانیک سایت از گوگل به صفر رسید. دلیل احتمالی این اتفاق آن بوده که سایت فاقد فایل robots.txt بوده است — فایلی در ریشهٔ سایت که باید به رباتها اعلام کند کدام بخشها قابل خزش هستند و کدام بخشها نیستند.
بررسیهای بعدی نشان داده که حتی در مستندات پشتیبانی نیز یک ویدیوی کامل دربارهٔ این نکته وجود دارد.
صادقانه بگویم، من هرگز با چنین موردی مواجه نشدهام، چون در همهٔ پروژههای شخصیام فایل robots.txt بهصورت خودکار از پروژهٔ قبلی کپی میشود. بااینحال، جالب است که اگر گوگلبات مجوز صریحی برای گشتوگذار در سایت دریافت نکند، خودسرانه عمل نمیکند و واقعاً وارد سایت نمیشود. منطقی است — اما در عین حال شگفتآور.
🔗https://www.alanwsmith.com/en/37/wa/jz/s1/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
موضوعی غیرمنتظره. Alan Smith یک مورد جالب را به اشتراک میگذارد: در مقطعی، ترافیک ارگانیک سایت از گوگل به صفر رسید. دلیل احتمالی این اتفاق آن بوده که سایت فاقد فایل robots.txt بوده است — فایلی در ریشهٔ سایت که باید به رباتها اعلام کند کدام بخشها قابل خزش هستند و کدام بخشها نیستند.
بررسیهای بعدی نشان داده که حتی در مستندات پشتیبانی نیز یک ویدیوی کامل دربارهٔ این نکته وجود دارد.
صادقانه بگویم، من هرگز با چنین موردی مواجه نشدهام، چون در همهٔ پروژههای شخصیام فایل robots.txt بهصورت خودکار از پروژهٔ قبلی کپی میشود. بااینحال، جالب است که اگر گوگلبات مجوز صریحی برای گشتوگذار در سایت دریافت نکند، خودسرانه عمل نمیکند و واقعاً وارد سایت نمیشود. منطقی است — اما در عین حال شگفتآور.
🔗https://www.alanwsmith.com/en/37/wa/jz/s1/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
Data Loaders در Vue Router
دیتا لودرها کار با دادههای ناهمگام (مثل واکشی API) را در Vue Router ساده و یکپارچه میکنند. با آنها میتوانید به شکل مؤثر دادهها را قبل از رندر کامپوننت آماده کنید و همزمان از کتابخانههایی مثل Pinia Colada یا Apollo بهره ببرید.
لودر بهطور خودکار هنگام تغییر مسیر اجرا میشود و دادهها قبل از رندر کامپوننت آماده هستند. همچنین میتوانید همان لودر را در چند کامپوننت دوباره استفاده کنید و دادهها بهصورت اشتراکی مدیریت شوند.
🔗https://uvr.esm.is/data-loaders/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
دیتا لودرها کار با دادههای ناهمگام (مثل واکشی API) را در Vue Router ساده و یکپارچه میکنند. با آنها میتوانید به شکل مؤثر دادهها را قبل از رندر کامپوننت آماده کنید و همزمان از کتابخانههایی مثل Pinia Colada یا Apollo بهره ببرید.
// src/pages/users/[id].vue
<script lang="ts">
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic'
import { getUserById } from '../api'
export const useUserData = defineBasicLoader('/users/[id]', async (route) => {
return getUserById(route.params.id)
})
</script>
لودر بهطور خودکار هنگام تغییر مسیر اجرا میشود و دادهها قبل از رندر کامپوننت آماده هستند. همچنین میتوانید همان لودر را در چند کامپوننت دوباره استفاده کنید و دادهها بهصورت اشتراکی مدیریت شوند.
🔗https://uvr.esm.is/data-loaders/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🧐 چرا نباید منطق کسبوکار را در کامپوننتهای UI نوشت
اغلب یک الگوی تکراری را میبینم: یک کامپوننت کوچک با چند شرط ساده که پس از چند قابلیت کوچک به موجودی عظیم تبدیل میشود 🤯 — هم رابط را نمایش میدهد، هم تصمیم میگیرد، هم با API ارتباط برقرار میکند و کمی «جادو» هم انجام میدهد. در نتیجه، بهجای یک UI تمیز، مجموعهای از منطق پنهان خواهیم داشت که نگهداری آن بعداً بسیار دشوار است.
---
🧩 چگونه این اتفاق میافتد؟
در ابتدا همه چیز منطقی به نظر میرسد: زمانبندی محدود، فیتچر کوچک — سادهتر است که پردازش را مستقیم در کامپوننت قرار دهیم. سپس «بعداً بیرون میکشیم» هیچگاه اتفاق نمیافتد و کامپوننت رشد میکند:
➖ فراخوانی API و تبدیل پاسخها
➖ تصمیمگیری درباره گامهای فرایند
➖ شامل شاخههای قوانین کسبوکار
➖ منبعی برای کپیپیست هنگام استفاده مجدد
---
🧩 مشکل چیست؟
☑️ ادغام نقشها — کامپوننت باید رابط را نمایش دهد، نه مدیریت فرایند را. وقتی UI شروع به «تفکر» میکند، سیستم بسیار شکننده میشود.
☑️ از بین رفتن قابلیت استفاده مجدد — نیاز به همان منطق در جای دیگر باعث کپیپیست، ناهماهنگی و باگها میشود.
☑️ ریسک تغییرات — تغییر نمایش، فرایند را خراب میکند؛ تغییر قانون، UI را بهطور غیرمنتظره میشکند.
☑️ پیچیدگی تست
---
🧩 چرا با این حال منطق را در کامپوننتها مینویسند؟
⏺️ سریعتر در شروع پروژه
⏺️ «برای یک قابلیت کوچک» بهنظر میرسد نیازی به جداکردن نیست
⏺️ تیم خسته است یا استاندارد معماری وجود ندارد
اما معمولاً همان «قابلیت کوچک» رشد میکند و بدهی فنی انباشته میشود 😥
---
🧩 چگونه بهتر کد را سازماندهی کنیم؟
✔️ کامپوننتهای UI — مسئول نمایش و واکنش به تعاملات کاربر
✔️ منطق کسبوکار — در سرویسها، استورها یا ماژولها
✔️ یکپارچهسازی — کامپوننتها سرویسها یا اکشنها را فراخوانی کرده و دادهها/وضعیتهای آماده را دریافت میکنند
مثال جریان داده:
---
🧩 چگونه خود را بررسی کنیم؟
اگر قالب (template) را از کامپوننت حذف کنیم و کد باقیمانده هنوز معنای مستقلی داشته باشد — یعنی منطق کسبوکار به کامپوننت نفوذ کرده است. این نشانهای برای تفکر درباره ریفکتورینگ است.
💡 نتیجهگیری:
UI = لایه نمایش
منطق کسبوکار = لایه تصمیمگیری
ادغام آنها ممکن است در ابتدا راحت باشد، اما در بلندمدت تقریباً همیشه منجر به افزایش پیچیدگی، شکنندگی سیستم و بدهی فنی میشود 🙈
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
اغلب یک الگوی تکراری را میبینم: یک کامپوننت کوچک با چند شرط ساده که پس از چند قابلیت کوچک به موجودی عظیم تبدیل میشود 🤯 — هم رابط را نمایش میدهد، هم تصمیم میگیرد، هم با API ارتباط برقرار میکند و کمی «جادو» هم انجام میدهد. در نتیجه، بهجای یک UI تمیز، مجموعهای از منطق پنهان خواهیم داشت که نگهداری آن بعداً بسیار دشوار است.
---
🧩 چگونه این اتفاق میافتد؟
در ابتدا همه چیز منطقی به نظر میرسد: زمانبندی محدود، فیتچر کوچک — سادهتر است که پردازش را مستقیم در کامپوننت قرار دهیم. سپس «بعداً بیرون میکشیم» هیچگاه اتفاق نمیافتد و کامپوننت رشد میکند:
➖ فراخوانی API و تبدیل پاسخها
➖ تصمیمگیری درباره گامهای فرایند
➖ شامل شاخههای قوانین کسبوکار
➖ منبعی برای کپیپیست هنگام استفاده مجدد
---
🧩 مشکل چیست؟
☑️ ادغام نقشها — کامپوننت باید رابط را نمایش دهد، نه مدیریت فرایند را. وقتی UI شروع به «تفکر» میکند، سیستم بسیار شکننده میشود.
☑️ از بین رفتن قابلیت استفاده مجدد — نیاز به همان منطق در جای دیگر باعث کپیپیست، ناهماهنگی و باگها میشود.
☑️ ریسک تغییرات — تغییر نمایش، فرایند را خراب میکند؛ تغییر قانون، UI را بهطور غیرمنتظره میشکند.
☑️ پیچیدگی تست
---
🧩 چرا با این حال منطق را در کامپوننتها مینویسند؟
⏺️ سریعتر در شروع پروژه
⏺️ «برای یک قابلیت کوچک» بهنظر میرسد نیازی به جداکردن نیست
⏺️ تیم خسته است یا استاندارد معماری وجود ندارد
اما معمولاً همان «قابلیت کوچک» رشد میکند و بدهی فنی انباشته میشود 😥
---
🧩 چگونه بهتر کد را سازماندهی کنیم؟
✔️ کامپوننتهای UI — مسئول نمایش و واکنش به تعاملات کاربر
✔️ منطق کسبوکار — در سرویسها، استورها یا ماژولها
✔️ یکپارچهسازی — کامپوننتها سرویسها یا اکشنها را فراخوانی کرده و دادهها/وضعیتهای آماده را دریافت میکنند
مثال جریان داده:
کامپوننت → اکشن / use-case → سرویس → مخزن/API → سرویس → use-case → کامپوننت (وضعیت بهروز شده)---
🧩 چگونه خود را بررسی کنیم؟
اگر قالب (template) را از کامپوننت حذف کنیم و کد باقیمانده هنوز معنای مستقلی داشته باشد — یعنی منطق کسبوکار به کامپوننت نفوذ کرده است. این نشانهای برای تفکر درباره ریفکتورینگ است.
💡 نتیجهگیری:
UI = لایه نمایش
منطق کسبوکار = لایه تصمیمگیری
ادغام آنها ممکن است در ابتدا راحت باشد، اما در بلندمدت تقریباً همیشه منجر به افزایش پیچیدگی، شکنندگی سیستم و بدهی فنی میشود 🙈
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
❤3👍1
خاصبودگی در CSS (معادل Specificity) به معنای «وزن» یا «قدرت» یک سلکتور است.
هرچه خاصبودگی یک سلکتور بیشتر باشد، در صورت تعارض با سایر قوانین، احتمال برنده شدن آن بیشتر است.
بهصورت خلاصه، ترتیب قدرت به این شکل است:
استایل درونخطی > شناسه (ID) > کلاس و شبهکلاس > عناصر و شبهعناصر
خاصبودگی معمولاً به شکل یک چهارتایی نمایش داده میشود، مانند:
(صفر، صفر، صفر، یک)
این اعداد بهترتیب نشاندهندهٔ تعداد استایلهای درونخطی، شناسهها، کلاسها/شبهکلاسها و عناصر هستند.
بنابراین «خاصبودگی» یعنی میزان اولویت یک قانون CSS هنگام بروز تداخل.
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
هرچه خاصبودگی یک سلکتور بیشتر باشد، در صورت تعارض با سایر قوانین، احتمال برنده شدن آن بیشتر است.
بهصورت خلاصه، ترتیب قدرت به این شکل است:
استایل درونخطی > شناسه (ID) > کلاس و شبهکلاس > عناصر و شبهعناصر
خاصبودگی معمولاً به شکل یک چهارتایی نمایش داده میشود، مانند:
(صفر، صفر، صفر، یک)
این اعداد بهترتیب نشاندهندهٔ تعداد استایلهای درونخطی، شناسهها، کلاسها/شبهکلاسها و عناصر هستند.
بنابراین «خاصبودگی» یعنی میزان اولویت یک قانون CSS هنگام بروز تداخل.
#myId#myId#myId span {
/* 0-3-0-1 */
}
.myClass.myClass.myClass span {
/* 0-0-3-1 */
}#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
«میخواهم برای تگ p داخل header استایل تعریف کنم، اما نمیخواهم خاصبودگی را افزایش دهم» 😎
گاهی سادهترین کار — تعیین استایل برای p داخل header — به رقابتی بیپایان میان سلکتورها تبدیل میشود. شما مینویسید header p { … }، فرد دیگری .text { … } اضافه میکند، شما سلکتورها را پیچیدهتر میکنید و پروژه بهآرامی در وزنهای «جهنمی» CSS فرو میرود. 😞 خوشبختانه یک راهکار ظریف و بسیار کاربردی وجود دارد: استفاده از :where()
🧩 :where() چه میکند:
:where() یک شبهکلاس در CSS است که فهرستی از سلکتورها را میپذیرد و بدون توجه به محتوای درون آن، همواره خاصبودگی صفر دارد.
💡 یعنی حتی اگر درون آن #id .class element قرار دهید، «وزن» نهایی همچنان صفر خواهد بود — برای کل سازهی :where().
🔍 یادآوری کوتاهی درباره خاصبودگی:
خاصبودگی — وزن سلکتور است. بهصورت ساده: استایل درونخطی بیشتر از شناسه، شناسه بیشتر از کلاس یا شبهکلاس، و آنها بیشتر از عناصر یا شبهعناصر وزن دارند.
الگوریتمهای CSS هنگام بروز تعارض از آن برای تعیین برنده استفاده میکنند:
⏺️ p → خاصبودگی (صفر، صفر، صفر، یک)
⏺️ :where(header) p → :where(header) صفر میدهد، p یک میدهد → در مجموع (صفر، صفر، صفر، یک)
⏺️ header p → header بهعلاوه p → (صفر، صفر، صفر، دو) — این سلکتور از قبل سنگینتر است
➡️ p و :where(header) p خاصبودگی یکسانی دارند — در صورت تعارض، قانونی که دیرتر تعریف شده باشد برنده خواهد شد.
در نتیجه، از :where() برای تعریف قواعد پیشفرض وابسته به کانتکست، بدون افزایش خاصبودگی استفاده کنید: ریست یا نرمالسازی، تایپوگرافی پایه، پیشفرضها درون کانتینرهای لایهبندی. این کار به شما اجازه میدهد کانتکست موردنظر را تعریف کنید، بدون آنکه آبشار را بر هم بزنید یا سلکتورها را سنگینتر کنید. 👍
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
گاهی سادهترین کار — تعیین استایل برای p داخل header — به رقابتی بیپایان میان سلکتورها تبدیل میشود. شما مینویسید header p { … }، فرد دیگری .text { … } اضافه میکند، شما سلکتورها را پیچیدهتر میکنید و پروژه بهآرامی در وزنهای «جهنمی» CSS فرو میرود. 😞 خوشبختانه یک راهکار ظریف و بسیار کاربردی وجود دارد: استفاده از :where()
🧩 :where() چه میکند:
:where() یک شبهکلاس در CSS است که فهرستی از سلکتورها را میپذیرد و بدون توجه به محتوای درون آن، همواره خاصبودگی صفر دارد.
💡 یعنی حتی اگر درون آن #id .class element قرار دهید، «وزن» نهایی همچنان صفر خواهد بود — برای کل سازهی :where().
🔍 یادآوری کوتاهی درباره خاصبودگی:
خاصبودگی — وزن سلکتور است. بهصورت ساده: استایل درونخطی بیشتر از شناسه، شناسه بیشتر از کلاس یا شبهکلاس، و آنها بیشتر از عناصر یا شبهعناصر وزن دارند.
الگوریتمهای CSS هنگام بروز تعارض از آن برای تعیین برنده استفاده میکنند:
⏺️ p → خاصبودگی (صفر، صفر، صفر، یک)
⏺️ :where(header) p → :where(header) صفر میدهد، p یک میدهد → در مجموع (صفر، صفر، صفر، یک)
⏺️ header p → header بهعلاوه p → (صفر، صفر، صفر، دو) — این سلکتور از قبل سنگینتر است
➡️ p و :where(header) p خاصبودگی یکسانی دارند — در صورت تعارض، قانونی که دیرتر تعریف شده باشد برنده خواهد شد.
در نتیجه، از :where() برای تعریف قواعد پیشفرض وابسته به کانتکست، بدون افزایش خاصبودگی استفاده کنید: ریست یا نرمالسازی، تایپوگرافی پایه، پیشفرضها درون کانتینرهای لایهبندی. این کار به شما اجازه میدهد کانتکست موردنظر را تعریف کنید، بدون آنکه آبشار را بر هم بزنید یا سلکتورها را سنگینتر کنید. 👍
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript