جاوااسکریپت | JavaScript
527 subscribers
704 photos
158 videos
4 files
566 links
کانال @IR_javascript حاوی اطلاعات مفید در حوزه برنامه نویس فرانت که بصورت روزانه بروز می‌شود.
در این کانال شما به:
[1] مطالب تازه
[2] تحلیل‌های عمیق
[3] نکات آموزشی
[4] چالش
[5] ابزار و راهنمایی‌های کاربردی
دسترسی خواهید داشت.

🆔@IR_javascript
Download Telegram
⚡️ OffscreenCanvas: چگونه انتقال رندر به Worker باعث بهبود عملکرد می‌شود

وقتی صحبت از عملکرد فرانت‌اند به میان می‌آید، مشکل اغلب در JavaScript کند نیست، بلکه در نخ اصلی است؛ نخی که هم‌زمان رویدادها را پردازش می‌کند، layout را محاسبه می‌کند، رابط کاربری را می‌کشد و canvas را رندر می‌کند. OffscreenCanvas راهکاری است که امکان انتقال رندر به یک نخ جداگانه را فراهم می‌کند؛ در نتیجه نخ اصلی آزاد می‌شود و عملکرد کلی برنامه بهبود می‌یابد.

❗️ OffscreenCanvas چیست؟

‏OffscreenCanvas یک canvas است که به DOM متصل نیست. می‌توان آن را در نخ اصلی ایجاد کرد، به Web Worker منتقل نمود و بدون مسدود کردن رابط کاربری در آن رسم انجام داد. این کار باعث می‌شود نخ اصلی برای پردازش رویدادها، انیمیشن‌ها و رندر layout و paint آزاد بماند و منابع خود را صرف پردازش گرافیک نکند.

❗️ چه زمانی باید از OffscreenCanvas استفاده کرد؟

رندر در یک نخ جداگانه به‌ویژه برای وظایف پیچیده‌ای مانند گرافیک و بصری‌سازی بسیار مفید است. برای مثال، بازی‌ها، شبیه‌سازی‌ها، نمودارهای پیچیده یا سیستم‌های ذره‌ای می‌توانند به‌طور قابل‌توجهی از OffscreenCanvas سود ببرند، زیرا این کار از افت FPS که معمولاً هنگام رندر در نخ اصلی رخ می‌دهد جلوگیری می‌کند. همچنین این راهکار برای کار با حجم بالای داده‌ها، مانند heatmapها، timelineها یا نمودارها و بصری‌سازی‌های بلادرنگ با به‌روزرسانی‌های مداوم، گزینه‌ای مناسب است.

❗️ چرا این روش سریع‌تر است؟

مهم‌ترین مزیت OffscreenCanvas عدم مسدود شدن نخ اصلی است. canvas دیگر باعث مسدود شدن reflow و repaint نمی‌شود؛ مسائلی که اغلب منجر به تأخیر و افت FPS می‌شوند. انتقال رندر به یک نخ جداگانه امکان رندر موازی و FPS پایدار را فراهم می‌کند؛ موضوعی که به‌خصوص روی دستگاه‌های ضعیف‌تر به‌وضوح قابل مشاهده است.

❗️ محدودیت‌های OffscreenCanvas

چند محدودیت وجود دارد که باید در نظر گرفته شوند. نخست این‌که پشتیبانی مرورگرها محدود است: OffscreenCanvas در مرورگرهای مبتنی بر Chromium و Firefox در دسترس است و در Safari پشتیبانی آن ناقص و همراه با ظرافت‌ها و محدودیت‌هایی است. بنابراین همیشه باید برای مرورگرهای ناسازگار یک fallback به canvas معمولی در نظر گرفت.

دوم این‌که هنگام کار با Worker امکان تعامل مستقیم با DOM وجود ندارد و تمام داده‌ها باید از طریق پیام‌ها منتقل شوند. این موضوع مستلزم تغییر در معماری برنامه است. همچنین باید توجه داشت که اشکال‌زدایی چنین راهکارهایی دشوارتر است، زیرا منطق رندر بین نخ‌ها تقسیم می‌شود و در تب استاندارد Canvas در DevTools نیز به‌طور کامل پشتیبانی نمی‌شود.

❗️ چه زمانی نباید از OffscreenCanvas استفاده کرد؟

اگر پروژهٔ شما مشکل جدی از نظر عملکرد ندارد و رندر به‌ندرت انجام می‌شود، استفاده از OffscreenCanvas می‌تواند غیرضروری باشد. این راهکار بیشتر برای مسائل پیچیده با نیازهای بالای عملکرد مناسب است؛ برای مثال، محاسبات سنگین گرافیکی و بصری‌سازی‌هایی که به FPS پایدار نیاز دارند.

📝 چگونه از OffscreenCanvas استفاده کنیم؟

// تمام رندر در یک نخ جداگانه انجام می‌شود و نخ اصلی برای پردازش UI و تعامل با کاربر آزاد می‌ماند.
// در نخ اصلی یک canvas معمولی می‌سازیم و آن را به worker منتقل می‌کنیم:
const canvas = document.querySelector('canvas')
const offscreen = canvas.transferControlToOffscreen()
worker.postMessage({ canvas: offscreen }, [offscreen])

// در worker، canvas را دریافت می‌کنیم و شروع به رسم می‌کنیم:
self.onmessage = ({ data }) => {
const ctx = data.canvas.getContext('2d')
ctx.fillRect(0, 0, 100, 100)
}


📌 OffscreenCanvas ابزار فوق‌العاده‌ای برای کار با گرافیک در مرورگر است. این قابلیت باعث می‌شود همه‌چیز سریع‌تر انجام شود، به‌ویژه زمانی که با تصاویر پیچیده یا بازی‌ها سر و کار دارید. اگر در پروژهٔ شما مشکلات FPS به وجود آمده یا رسم گرافیک دشوار شده است، کافی است رندر را به Worker منتقل کنید. این یکی از بهترین روش‌ها برای بهبود عملکرد است، بدون آن‌که مجبور باشید کل برنامه را از نو بازنویسی کنید.
واحد های اندازه گیری CSS (قسمت پنجم)

واحدهای نسبی جدید CSS: واحدهای کانتینری (Container Units) برای رابط‌های کاربری تطبیقی

در CSS به‌صورت سنتی برای پیاده‌سازی رابط‌های واکنش‌گرا از واحدهایی مانند vw و vh استفاده می‌شود. بااین‌حال، این واحدها در لِی‌اوت‌های پیچیده کارایی لازم را ندارند. مدیاکوئری‌ها، راه‌حل‌های موقتی و استفاده از درصدها تا حدی این مشکل را برطرف می‌کنند، اما با معرفی Container Queries و Container Units، بسیاری از این پیچیدگی‌ها عملاً به گذشته تعلق دارند.

واحدهای Container Units چیستند؟

‏Container Units واحدهای اندازه‌گیری‌ای هستند که بر اساس ابعاد یک کانتینر محاسبه می‌شوند؛ کانتینری که با استفاده از ویژگی container-type تعریف شده است. این رویکرد به ما اجازه می‌دهد تطبیق‌پذیری را با دقت و راحتی بسیار بیشتری پیاده‌سازی کنیم و به‌جای تکیه بر اندازه کل صفحه، ابعاد واقعی هر کامپوننت درون کانتینر خودش را در نظر بگیریم.

مهم‌ترین این واحدها عبارت‌اند از:

• cqw — معادل یک درصد از عرض کانتینر
• cqh — معادل یک درصد از ارتفاع کانتینر
• cqi — معادل یک درصد از اندازه inline کانتینر (وابسته به writing-mode)
• cqb — معادل یک درصد از اندازه block کانتینر
• cqmin و cqmax — به‌ترتیب حداقل و حداکثر ابعاد کانتینر

چرا این موضوع اهمیت دارد؟

• استقلال کامپوننت‌ها
کامپوننت‌ها می‌توانند بدون وابستگی به context کلی صفحه، به‌صورت مستقل تطبیق پیدا کنند. مهم نیست در کجا استفاده شوند؛ آن‌ها خودشان را با اندازه کانتینر والد وفق می‌دهند.

• کاهش نیاز به مدیاکوئری‌ها
به‌جای نوشتن تعداد زیادی مدیاکوئری، می‌توان به‌سادگی از @container به‌همراه cqw استفاده کرد. این کار هم حجم کد را کمتر می‌کند و هم خوانایی آن را بهبود می‌بخشد.

• حذف بسیاری از هک‌های جاوااسکریپتی
دیگر نیازی نیست برای محاسبه ابعاد و تنظیم تایپوگرافی یا فاصله‌ها از ResizeObserver استفاده شود. اکنون می‌توان همه این کارها را مستقیماً با CSS انجام داد.

نکات مهم و ظریف

— کانتینر حتماً باید تعریف شود؛ برای مثال با container-type: inline-size.
— این واحدها فقط درون کانتینر عمل می‌کنند، بنابراین انتخاب نوع مناسب کانتینر اهمیت زیادی دارد.
— واحدهای cqi و cqb به‌ویژه زمانی بسیار مفید هستند که نیاز به پشتیبانی از writing-mode عمودی یا رابط‌های چندزبانه و بین‌المللی دارید.

چه زمانی باید از Container Units استفاده کرد؟

— در طراحی سیستم‌های طراحی (Design System) و کامپوننت‌های قابل استفاده مجدد.
— در لِی‌اوت‌های پیچیده مانند داشبوردها یا ویرایشگرها.
— در معماری‌های میکروفِرانت‌اند، جایی که کامپوننت‌ها باید کاملاً مستقل از یکدیگر باشند.

📝 مثال‌ها:

/* در این مثال، اندازه فونت .card__title به عرض کانتینر .card وابسته است، نه به عرض کل صفحه. */
.card {
container-type: inline-size;
}

.card__title {
font-size: 4cqw;
}

/* تایپوگرافی */
.title {
font-size: clamp(16px, 3cqw, 24px);
}

/* فاصله‌گذاری */
.card {
padding: 4cqi;
}


📌 تطبیق‌پذیری مبتنی بر viewport دیگر متعلق به دیروز است. Container Units گامی جدید به‌سوی تفکر کامپوننت‌محور در CSS محسوب می‌شوند. حالا کامپوننت‌های شما به صفحه وابسته نیستند و رفتاری قابل پیش‌بینی دارند؛ انگار CSS هوشمندتر شده، نه پیچیده‌تر.


#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍21
چه زمانی باید اولویت بارگذاری را مشخص کنیم؟ 🤔

لود تنبل (‎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‎ — کاراکتر یا نام کلید (مثل "a" یا "Enter"
✔️ ‎event.code‎ — کلید فیزیکی روی کیبورد (مثل "KeyA" یا "Enter"
✔️ ‎event.ctrlKey‎، ‎event.shiftKey‎، ‎event.altKey‎، ‎event.iss.onetaKey‎ — کلیدهای کمکی.

مثال ساده: ‎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
👍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
This media is not supported in your browser
VIEW IN TELEGRAM
نود و نه درصد توسعه‌دهندگان از این ترفند در Chrome DevTools خبر ندارند 🤯

می‌توانید تم تاریک را روی هر سایتی فعال کنید، حتی اگر آن سایت خود تم تاریک نداشته باشد. برای این کار، DevTools را باز کرده، روی آیکون قلم‌مو کلیک کنید و گزینه‌ی Automatic Dark Mode را انتخاب نمایید.

این روش برای زمانی که در حال طراحی تم تاریک برای وب‌سایت خود هستید ایده‌آل است — شما فوراً پیش‌نمایشی از رابط کاربری تقریباً نود درصدی دریافت می‌کنید.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2
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
پژوهشگران ۳۷ هزار رزومهٔ جعلی از فارغ‌التحصیلان را ارسال کردند و بررسی کردند که چه کسانی بیشتر به مصاحبه دعوت می‌شوند [+لینک].

در این رزومه‌ها همه‌چیز به‌صورت تصادفی تغییر داده شده بود: رشتهٔ تحصیلی، دوره‌های کارآموزی، تحصیل در خارج از کشور و مهارت‌های کامپیوتری. نتایج جالبی که به‌طور غیرمنتظره جواب داد:

— کارآموزی‌هایی که بر توسعهٔ مهارت‌های نرم (Soft Skills) تمرکز دارند؛ آن هم حتی در درخواست برای موقعیت‌های شغلی تحلیلی(فقط بلد بودن کافی نیست شرکت‌ها به این هم توجه می‌کنند که آیا طرف «مهارت‌های انسانی» دارد یا نه) .

— تحصیل در خارج از کشور، همان‌طور که انتظار می‌رفت، شانس پیدا کردن سریع اولین شغل را افزایش می‌دهد.

— ترکیب برنامه‌نویسی + تحلیل داده‌ها یک امتیاز خیلی بزرگ برای دریافت تماس مجدد (دعوت به مصاحبه) ایجاد می‌کند. در حالی که هرکدام از این مهارت‌ها به‌تنهایی چنین اثری ندارند.

#️⃣#discussion
👥@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
👍3
آیا می‌دانستید دکمهٔ ارسال فرم می‌تواند خارج از خود فرم قرار بگیرد؟

در بیشتر مواقع، دکمهٔ ارسال را داخل تگ <form> قرار می‌دهیم و این کار کاملاً درست است.
اما گاهی به‌دلیل محدودیت‌های چیدمان (layout) یا دلایل دیگر، منطقی‌تر است که دکمهٔ ارسال بیرون از تگ <form> قرار داده شود.

در این حالت می‌توانیم به‌سادگی با استفاده از ویژگی‌های form و id دکمه را به فرم موردنظر متصل کنیم.

به همین روش، در صورت نیاز می‌توان سایر عناصر کنترلی مثل textarea، checkbox و موارد مشابه را هم به یک فرم خاص مرتبط کرد، حتی اگر خارج از آن فرم قرار داشته باشند.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
این ۴ خط را به فایل `.vscode/settings.json` اضافه کنید تا تجربهٔ توسعه‌تان بلافاصله راحت‌تر و خواناتر شود.

با این تنظیمات، نام تب‌ها در 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