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

🆔@IR_javascript
Download Telegram
متد navigator.sendBeacon() این امکان را فراهم می‌کند که حجم کمی از داده‌ها به‌صورت تضمینی به سرور ارسال شود، حتی در شرایطی که کاربر صفحه یا مرورگر را ببندد. برخلاف درخواست‌های سنتی AJAX که ممکن است هنگام بارگذاری یا بستن صفحه ناتمام بمانند، sendBeacon در چنین سناریوهایی ارسال داده را تضمین می‌کند.

مرورگر به درخواست sendBeacon اولویت اجرای بالا نسبت به فرآیند بسته شدن صفحه می‌دهد، که این ویژگی، این متد را برای ارسال داده‌های حیاتی، ابزاری ایده‌آل می‌سازد.

### کاربردهای عملی

* نهایی‌سازی داده‌های تحلیلی: ارسال اطلاعات آماری جمع‌آوری‌شده در طول یک نشست، درست پیش از بسته شدن صفحه
* ذخیره‌سازی خودکار: ثبت آخرین وضعیت برنامه در شرایطی که ممکن است کاربر به‌صورت دستی آن را ذخیره نکرده باشد
* گزارش خطاها: ارسال تضمینی لاگ‌های مربوط به خطاهای بحرانی
* ردیابی رفتار کاربر: ثبت آخرین اقدامات کاربر پیش از ترک صفحه

const data = JSON.stringify({event: 'page_close', time: Date.now()});
navigator.sendBeacon("/analytics", data);


### محدودیت‌ها

* حداکثر اندازه بار داده محدود است (معمولاً تا شصت و چهار کیلوبایت)
* فقط از درخواست‌های POST پشتیبانی می‌کند
* از هدرهای سفارشی پشتیبانی نمی‌کند
* پاسخ سرور قابل پردازش نیست

این ویژگی‌ها sendBeacon را برای ارسال داده‌های ساده، سریع و قابل اعتماد، به‌ویژه هنگام بستن صفحه، به ابزاری کاربردی تبدیل کرده‌اند.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
چگونه یک نشان (Badge) برای برنامه ایجاد کنیم


نشان‌ها (Badge) برای انتقال اطلاعات غیر اضطراری به کاربر استفاده می‌شوند. برای نمونه، می‌توان از آن‌ها برای نمایش وضعیت یک برنامه یا تعداد آیتم‌های خوانده‌نشده بهره گرفت. روش کلاسیک ایجاد نشان برای برنامه، افزودن یک عدد به فاو‌آیکن (favicon) بود. اما در مرورگرهای مدرن، پس از نصب برنامه، راهکاری داخلی برای افزودن نشان به آیکون برنامه در نوار وظیفه سیستم‌عامل وجود دارد.

روش نوین
استفاده از متد navigator.setAppBadge()
متد navigator.setAppBadge() امکان افزودن یک نشان به آیکون برنامه نصب‌شده را فراهم می‌سازد. این متد یک آرگومان اختیاری دریافت می‌کند که یک عدد صحیح است و به‌عنوان مقدار نشان استفاده می‌شود.
اگر این عدد صفر تعیین شود، نشان پاک خواهد شد. در صورتی که هیچ مقداری ارائه نشود، یک نشان عمومی (معمولاً به‌صورت نقطه‌ای رنگی) نمایش داده می‌شود.
این روش مدرن و استاندارد، تجربه کاربری بهتری را در برنامه‌های تحت وب فراهم می‌کند و به‌ویژه در برنامه‌های وب پیش‌رونده (PWA) نقش مؤثری در اطلاع‌رسانی ساده و مؤثر دارد.


روش کلاسیک: افزودن عدد به فاوآیکون
اگر برنامه هنوز نصب نشده باشد، می‌توانید عددی را به فاوآیکون اضافه کنید. راه‌های گوناگونی برای انجام این کار وجود دارد؛ برای نمونه، می‌توان فاوآیکون را به‌صورت پویا بر روی یک عنصر بوم (canvas) ترسیم کرد و اطلاعات مربوط به نشان (badge) را به آن افزود و سپس آن را به‌صورت یک نشانی «بلاب» (Blob URL) نمایش داد. یا می‌توان تصویری از نوع SVG ساخت که اطلاعات نشان را به‌صورت یک نشانی داده‌ای (data URL) در خود داشته باشد.

🔗https://web.dev/patterns/web-apps/badges
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
در هنگام استفاده از router-view همراه با transition و تعیین `mode="out-in"`، در حالت توسعه (dev mode)، هنگام جابه‌جایی بین مسیرها (routes) اغلب با مشکل نمایش صفحه سفید مواجه می‌شویم.

تنها راه‌حل مؤثری که تاکنون یافته شده، غیرفعال کردن این حالت (mode) در زمان توسعه است.

نمونه‌ای از کد مربوطه:

<router-view v-slot="{ Component }">
<Transition mode="out-in">
<component :is="Component" />
</Transition>
</router-view>


در این وضعیت، پیشنهاد می‌شود برای جلوگیری از بروز مشکل، در محیط توسعه از مقدار پیش‌فرض mode یا از حالت‌هایی مانند "in-out" یا بدون مشخص‌کردن mode استفاده شود و تنها در محیط تولید (production) از حالت out-in بهره بگیرید، چرا که این حالت در محیط توسعه ممکن است باگ‌هایی مانند نمایش صفحه سفید موقت ایجاد کند.



#️⃣#tip #vue
👥@IR_javascript_group
🆔@IR_javascript
👍31
### متا تگ‌ها: خطوطی پشت‌صحنه که سرنوشت وب‌سایت شما را رقم می‌زنند

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

---

### بیایید قدم به قدم بررسی کنیم: تگ <meta> چیست؟

تگ‌های متا، تگ‌هایی در زبان HTML هستند که در بخش <head> صفحه قرار می‌گیرند و اطلاعات کلی درباره‌ی خود صفحه را ارائه می‌دهند:

* محتوای صفحه
* قوانین ایندکس شدن در موتورهای جستجو
* نحوه‌ی نمایش در هنگام اشتراک‌گذاری در شبکه‌های اجتماعی
* رنگ رابط کاربری در مرورگرهای موبایل
و حتی بیشتر از این‌ها.

(چند نمونه‌ی کاربردی هم در تصویر بالا توضیح داده شده است.)

---

### اگر می‌خواهید هنگام اشتراک‌گذاری لینک صفحه در VK یا تلگرام، عنوان، توضیح و تصویری زیبا نمایش داده شود، بدانید که این هیچ‌گونه جادویی نیست — این قدرت متا تگ‌ها و استاندارد Open Graph است.

---

### چند ویژگی جالب و کاربردی:

🔁 ریدایرکت خودکار پس از پنج ثانیه:

<meta http-equiv="refresh" content="5;url=https://example.com">


🎨 تنظیم رنگ رابط کاربری مرورگر موبایل:

<meta name="theme-color" content="#317EFB">


---

### جمع‌بندی:

متا تگ‌ها صرفاً «موارد فرمالی برای رفع تکلیف» نیستند.
بلکه ابزارهایی حیاتی هستند که به شما اجازه می‌دهند کنترل کاملی روی نحوه‌ی نمایش وب‌سایت برای کاربران و موتورهای جستجو داشته باشید.

به آن‌ها اهمیت بدهید؛ تا وب‌سایت شما نه‌تنها از بیرون، بلکه از درون نیز حرفه‌ای و هوشمندانه عمل کند.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2
در نسخه‌ی جدید مرورگر کروم — کروم شماره‌ی یک‌صد و سی و هفت — ویژگی جدیدی برای CSS معرفی شده است که از ساختار شرطی شبیه به if پشتیبانی می‌کند.

نمونه‌ای از استفاده‌ی این قابلیت به شکل زیر است:

div {
color: var(--color);
background-color: if(style(--color: white): black; else: white);
}

@media (prefers-color-scheme: dark) {
--color: black;
}

@media (prefers-color-scheme: light) {
--color: white;
}


---

### 🆕 توضیح:

ویژگی if() در CSS امکان می‌دهد بر اساس وضعیت یا مقدار یک متغیر (مثلاً --color) تصمیم‌گیری شود. این ساختار شرطی باعث می‌شود استایل‌ها واکنش‌گرا، منعطف و هوشمندانه‌تر شوند — بدون نیاز به JavaScript یا ساختارهای پیچیده‌تر.

---

این قابلیت در حال حاضر تازه معرفی شده و احتمال دارد تنها در نسخه‌های آزمایشی یا با پرچم فعال باشد. برای استفاده‌ی گسترده‌تر، بررسی وضعیت پشتیبانی در مرورگرها توصیه می‌شود.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
😱1😢1
اگر نیاز دارید در صفحه‌ وب، یک فیلد قابل ویرایش برای وارد کردن متن اضافه کنید، می‌توانید از ویژگی contenteditable استفاده کنید. این ویژگی، در بسیاری از مواقع جایگزین خوشایندتری نسبت به textarea است (هرچند برای فرم‌های بزرگ، جایگزین کاملی محسوب نمی‌شود).

---

### محدودسازی ورودی فقط به متن ساده

برای اینکه کاربر فقط متن ساده وارد کند (بدون HTML، تصویر یا استایل)، می‌توانید مقدار plaintext-only را به ویژگی contenteditable اختصاص دهید. این کار از وارد شدن محتوای قالب‌بندی‌شده جلوگیری می‌کند.

<div
contenteditable="plaintext-only"
data-placeholder="شروع به نوشتن کنید..."
></div>


---

### نکته‌های تکمیلی

می‌توانید با استفاده از رویدادهای input و `paste`، کنترل بیشتری بر محتوای واردشده داشته باشید. مثلاً هنگام paste، با استفاده از قطعه‌کدی مانند زیر، محتوای HTML را به متن ساده تبدیل کنید:

const text = e.clipboardData.getData('text/plain');




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
‏### CSS Reset

گاهی به‌نظر می‌رسد که مرورگرهای مدرن امروزی به‌طور کلی عناصر را تقریباً یکسان نمایش می‌دهند. اما اخیراً در تیم ما بحثی پیش آمد:
آیا واقعاً به CSS Reset نیاز داریم، وقتی «همه‌چیز انگار درست کار می‌کند»؟
این بحث برایم یادآور شد که بسیاری از توسعه‌دهندگان هنوز اهمیت این موضوع را دست‌کم می‌گیرند.

---

### CSS Reset یعنی چه؟

‏CSS Reset یک ابزار برای «زیباتر شدن کد» یا پیروی از مد نیست. بلکه روشی برای ایجاد پیش‌بینی‌پذیری، یکپارچگی و کنترل در طراحی رابط کاربری است.

در نبود CSS Reset، حتی ساده‌ترین عناصر HTML ممکن است در مرورگرهای مختلف ظاهر متفاوتی داشته باشند و همین از همان ابتدا می‌تواند مشکلات غیرمنتظره ایجاد کند.

---

### چرا به CSS Reset نیاز داریم؟

هر مرورگر، به‌شکل پیش‌فرض، HTML را با استایل‌های مخصوص خود نمایش می‌دهد:
از جمله تعیین فاصله‌ها، نوع و اندازه‌ی فونت‌ها، نحوه نمایش تیترها و غیره.
در نتیجه، یک صفحه‌ی وب ممکن است در مرورگرهای مختلف ظاهر کاملاً متفاوتی داشته باشد.

CSS Reset این تفاوت‌ها را از بین می‌برد و یک بستر تمیز و کنترل‌شده برای استایل‌دهی فراهم می‌کند.

---

### نمونه‌ای از CSS Reset:

/* حذف حاشیه‌ها و تنظیم box-sizing */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}


این تکه‌کد ساده، حاشیه‌ها و فاصله‌های پیش‌فرض را حذف کرده و رفتاری قابل‌پیش‌بینی برای box-sizing ایجاد می‌کند.

---

### رویکردهای رایج در CSS Reset:

🔹 Reset.css یا نسخه اریک مایر (Eric Meyer):
https://meyerweb.com/eric/tools/css/reset/

روشی کلاسیک و بسیار جامع که تقریباً تمام استایل‌های پیش‌فرض را حذف می‌کند (اما سال‌هاست به‌روزرسانی نشده).

🔹 Normalize.css:
https://necolas.github.io/normalize.css/

رویکردی مدرن‌تر که به‌جای حذف کامل، استایل‌ها را یکسان‌سازی می‌کند؛
درعین‌حال معنای اصلی عناصر HTML را حفظ می‌نماید.

🔹 Modern CSS Reset:
https://piccalil.li/blog/a-more-modern-css-reset/
https://www.joshwcomeau.com/css/custom-css-reset/

شامل نسخه‌هایی مانند ریست اندی بل (Andy Bell) یا نسخه‌های سفارشی مانند ریست جاش کومو (Josh Comeau) که با دیدگاهی به‌روز طراحی شده‌اند.

---

📌 نکته مهم:
Reset و Normalize.css دو رویکرد متفاوت‌اند:

* Reset همه‌چیز را به «صفر» می‌رساند.
* Normalize سعی دارد استایل‌های مفید را نگه دارد و فقط تفاوت‌ها را بین مرورگرها همگام‌سازی کند.

در کاربرد روزمره، این دو گاهی با یکدیگر اشتباه گرفته می‌شوند، اما هدف نهایی و روش اجرا کاملاً با هم تفاوت دارند.

---

📐 با اعمال CSS Reset، می‌توانید از همان ابتدا کنترل کامل‌تری روی نحوه‌ی نمایش عناصر در مرورگرهای مختلف داشته باشید و از بروز ناسازگاری‌های ظاهری جلوگیری کنید.




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
برنامه‌ی توسعه‌ی فردی: نقشه‌ی راه اختصاصی تو در دنیای فناوری اطلاعات

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

🔑 پاسخ ساده است: برنامه‌ی توسعه‌ی فردی (Individual Development Plan یا IDP)

---

### برنامه توسعه فردی چیست؟

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

---

### چرا این‌قدر مهم است؟

۱. اهداف را شفاف تعریف می‌کنی:
به‌جای «یادگیری TypeScript»، می‌گویی:
«ماژول لاگین را به TypeScript منتقل می‌کنم، برای آن تست می‌نویسم و در CI ادغامش می‌کنم».
این مسیر رشد صرفاً برای رشد نیست، بلکه برای اثرگذاری واقعی است.

۲. معیار و ضرب‌الاجل تعیین می‌کنی:
عباراتی مثل «بهبود عملکرد» کافی نیستند. باید هدف مشخص باشد، مثلاً:
«کاهش زمان بارگذاری قابل تعامل (Time to Interactive) صفحه اصلی به کمتر از دو ثانیه، طی دو اسپرینت».
این سبک هدف‌گذاری پیگیری پیشرفت و ارائه مستندات را آسان می‌کند.

۳. ادغام در جریان کاری واقعی:
اهداف این برنامه نباید فقط در نوت‌ها بمانند. آن‌ها باید وارد بک‌لاگ تیم در ابزارهایی مانند Jira یا Trello شوند، و مدام در جریان کار باشند. در غیر این صورت، همه‌چیز با جمله‌ی آشنا تمام می‌شود:
«می‌خواستم، ولی نشد...»

۴. ارزیابی مستمر:
پیشرفت خود را با تیم‌لید در میان بگذار، بازخورد بگیر و در صورت نیاز جهت‌گیری را اصلاح کن.
اینجا همان نقطه‌ای است که اهداف شخصی با اهداف محصول و سازمان هم‌راستا می‌شوند.

---

### چطور یک IDP پنج‌مرحله‌ای بسازیم؟

۱. تحلیل سطح فعلی خودت:
صادقانه ارزیابی کن: کجا «عالی» هستی و کجا هنوز «ضعیف»؟
(مثلاً: تست‌نویسی، DevOps، اصول شی‌گرایی و غیره)

۲. انتخاب سه تا چهار مسیر کلیدی رشد:
مثلاً: طراحی کامپوننت‌ها (Atomic Design)، بهینه‌سازی عملکرد وب، تست، سیستم‌عامل‌های یونیکس، شبکه، یا مهارت‌های نرم (ارائه، بازبینی کد و غیره)

۳. تعریف اهداف SMART:
اهدافی مشخص، قابل اندازه‌گیری، دست‌یافتنی، مرتبط با کار و زمان‌بندی‌شده.

۴. ادغام با روند کاری واقعی:
تسک‌ها را در ابزارهای مدیریت پروژه ثبت کن و مدام به‌روز نگه‌دار. بگذار جلوی چشمت بمانند تا تمرکز حفظ شود.

۵. بررسی و بازنگری:
در پایان هر ماه یا اسپرینت، یک مرور کوچک برگزار کن:
چه چیزی پیش رفت؟ چه چیزی عقب افتاد؟ چه عواملی مانع شدند؟ چه چیز باید اصلاح شود؟

---

### مزایا برای سطوح مختلف شغلی

* توسعه‌دهنده‌ی تازه‌کار (Junior): مسیر روشن برای ورود به پروژه و تقویت مهارت‌های پایه
* میان‌رده (Middle): توانایی سنجش تأثیرگذاری و طراحی معماری
* ارشد (Senior): گسترش تخصص، پیاده‌سازی استانداردهای حرفه‌ای و هدایت تیم

---

با یک برنامه‌ی توسعه‌ی فردی دقیق، دیگر فقط «دوره نمی‌گذرانی»؛
بلکه تغییرات واقعی در دانش و محصولت را مستند می‌کنی.

🎯 وقت آن است که دست به کار شوی!
پی‌نوشت: در بسیاری از شرکت‌ها، **ارتقا شغلی و افزایش سطح مسئولیت**، دقیقاً به همین برنامه‌های توسعه‌ی فردی دقیق و اجراشده بستگی دارد.



#️⃣#discussion
👥@IR_javascript_group
🆔@IR_javascript
در مواقعی که در یک پروژه‌ی CSS، ترتیب بارگذاری استایل‌ها به‌هم می‌ریزد و استایل‌ها با یکدیگر تداخل پیدا می‌کنند، دیرکتیو `@layer` یا همان *لایه‌های آبشاری CSS (CSS Cascade Layers)* می‌تواند راه‌حل مناسبی باشد.

این ویژگی، یک ساختار سلسله‌مراتبی شفاف برای استایل‌ها ایجاد می‌کند — برای مثال، لایه‌هایی مانند core`، `reset`، `base — و در بسیاری از موارد، شما را از استفاده‌ی بی‌رویه از !important بی‌نیاز می‌سازد.

### چطور یک لایه تعریف کنیم؟

خیلی ساده:

@layer reset {
*, ::before, ::after {
box-sizing: border-box;
margin: ۰;
padding: ۰;
}
}


### و چطور ترتیب لایه‌ها را مشخص کنیم؟

باز هم خیلی ساده:

@layer reset, base;


---

### اما اولویت‌بندی چطور عمل می‌کند؟

* قوانین خارج از `@layer` همیشه بر قوانین عادی (غیر !important) داخل لایه‌ها غلبه دارند**، فارغ از اینکه چه زمانی تعریف شده باشند.
* اگر ترتیب مشخصی برای لایه‌ها تعیین نشده باشد (یعنی `
@layer reset, base;` نیامده باشد)، **ترتیب اولین تعریف هر لایه در فایل CSS تعیین‌کننده خواهد بود.
* درون یک لایه**، قواعد مانند همیشه عمل می‌کنند: قانون با **ویژگی‌مندی (specificity) بالاتر برنده است؛ در صورت برابر بودن ویژگی‌مندی، قانونی که دیرتر نوشته شده**، اعمال خواهد شد.
* اما برای قوانین `!important`، این منطق **برعکس
است؛ یعنی ترتیب تعریف لایه‌ها مهم‌تر از موقعیت خط یا ویژگی‌مندی خواهد بود.

---

### جمع‌بندی

ویژگی `@layer`:

* ترتیب استایل‌ها را قابل‌پیش‌بینی می‌کند؛
* از بروز مشکلات مربوط به ویژگی‌مندی جلوگیری می‌کند؛
* و نیاز به !important را تا حد زیادی کاهش می‌دهد.

اگر به دنبال کدنویسی CSS حرفه‌ای، ساخت‌یافته و قابل نگهداری هستید، توصیه می‌شود از @layer در پروژه‌های مدرن خود استفاده کنید.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🤬1😡1
دامِ جاوااسکریپت: مقایسه‌ی ‎`parseInt("")‎ با ‎`Number("")

گاهی ممکن است فکر کنید که ‎`parseInt("")`‎ و ‎`Number("")`‎ رفتار یکسانی دارند.
اما این‌طور نیست، و اگر تفاوت آن‌ها را ندانید، ممکن است باگ‌های عجیبی در برنامه‌تان به‌وجود بیاید — مخصوصاً هنگام کار با پارامترهای URL.

### بیایید رفتار آن‌ها را بررسی کنیم:

parseInt("")     // ← نتیجه: NaN
Number("") // ← نتیجه: ۰


### چه اتفاقی می‌افتد؟

* ‎`parseInt("")`‎ تلاش می‌کند رشته را به‌صورت عددی، کاراکتر به کاراکتر تجزیه کند.
اما چون رشته خالی است، چیزی برای تجزیه وجود ندارد، در نتیجه: `NaN` (یعنی Not a Number).

* ‎`Number("")`‎ بر اساس قوانین داخلی تبدیل نوع در جاوااسکریپت، رشته را به عدد تبدیل می‌کند.
رشته‌ی خالی طبق این قوانین معادل صفر در نظر گرفته می‌شود، در نتیجه: `۰`.

---

### یک مثال کاربردی: صفحه‌بندی کالاها

فرض کنید در وب‌سایت‌تان صفحه‌ای برای نمایش محصولات دارید و آدرس URL به این صورت است:

https://example.com/products?page=&limit=10


پارامترها را این‌طور دریافت می‌کنید:

const params = new URLSearchParams(location.search);
const page = Number(params.get("page"));
const limit = Number(params.get("limit"));


در اینجا:

* ‎`params.get("page")‎ مقدار رشته‌ی خالی (""`) برمی‌گرداند؛
* ‎`Number("")`‎ آن را تبدیل به عدد صفر می‌کند؛
* در نتیجه، صفحه‌ای با شماره‌ی صفر در منطق برنامه جایگزین می‌شود، در حالی‌که چنین صفحه‌ای اصلاً تعریف نشده!

ممکن است کاربر با صفحه‌ی خالی، خطا یا محتوای نادرست مواجه شود.

---

### راهکار ایمن‌تر:

const pageRaw = params.get("page");
const page = parseInt(pageRaw);
const safePage = Number.isNaN(page) || page < ۱ ? ۱ : page;


در این روش:

* مقدار خام را می‌گیریم؛
* با ‎`parseInt`‎ آن را تبدیل می‌کنیم؛
* اگر نتیجه ‎`NaN`‎ یا عددی کمتر از یک بود، مقدار پیش‌فرض یک را جایگزین می‌کنیم.

این روش قابل‌اعتمادتر است، زیرا ‎`parseInt("")`‎ خروجی `NaN` می‌دهد و به‌وضوح نشان می‌دهد که داده نامعتبر است.

---

### جمع‌بندی:

* ‎`Number("") → ۰`‎ ممکن است به‌ظاهر بی‌دردسر باشد، اما در عمل می‌تواند منطق برنامه را بی‌سروصدا خراب کند.
* ‎`parseInt("") → NaN`‎ به‌روشنی هشدار می‌دهد که داده مشکل دارد.

در جاوااسکریپت، همیشه خطاها فریاد نمی‌زنند!
گاهی با لبخند می‌گویند: «همه‌چی خوبه»، و بعد یک صفر بی‌ربط تحویل‌تان می‌دهند.
و شما می‌مانید با این سؤال:
«چرا هیچ کالایی توی صفحه نمایش داده نمی‌شه؟!» 🤨


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
ماژول‌های مجازی در Vite
در چارچوب Vite، ماژول‌های مجازی سازوکاری هستند که به شما امکان می‌دهند ماژول‌هایی را ایجاد کنید که به صورت فایل فیزیکی در دیسک وجود ندارند، اما می‌توانند در پروژه شما وارد (import) شده و مورد استفاده قرار گیرند.
نحوه عملکرد:
ساختار وارد کردن (Import): شما از ساختار استاندارد وارد کردن ESM برای ارجاع به ماژول‌های مجازی استفاده می‌کنید.
قاعده پیشوند: طبق قرارداد، ماژول‌های مجازی در Vite (و Rollup، که Vite از آن بهره می‌برد) در مسیر وارد کردن کاربر نهایی با پیشوند "virtual:" مشخص می‌شوند.
پلاگین‌ها: پلاگین‌های Vite کلید پیاده‌سازی ماژول‌های مجازی هستند. یک پلاگین درخواست وارد کردن برای یک شناسه ماژول مجازی را رهگیری کرده و محتوای ماژول را فراهم می‌آورد.
حل و فصل داخلی: در داخل، پلاگین‌ها هنگام حل و فصل شناسه ماژول، آن را با یک کاراکتر تهی (\0) پیشوندگذاری می‌کنند. این کار به تمایز ماژول‌های مجازی از فایل‌های عادی کمک کرده و از پردازش نادرست آنها توسط سایر پلاگین‌ها جلوگیری می‌کند.
محتوای ماژول: هوک load پلاگین، محتوای رشته‌ای ماژول مجازی را برمی‌گرداند.
چرا از ماژول‌های مجازی استفاده کنیم؟
ماژول‌های مجازی برای موارد زیر مفید هستند:
انتقال اطلاعات زمان ساخت (build-time): شما می‌توانید داده‌ها یا پیکربندی‌هایی را که در طول فرآیند ساخت تعیین می‌شوند، تولید کرده و تزریق کنید، و آنها را در کد منبع خود در دسترس قرار دهید.
تعامل با پلاگین‌ها: برخی از پلاگین‌ها، مانند vite-plugin-pwa، ماژول‌های مجازی را برای ارائه یک رابط کاربری برای تعامل با عملکرد خود در معرض دید قرار می‌دهند.
ایجاد ماژول‌های سفارشی: می‌توانید ماژول‌های مجازی برای ارائه داده‌ها یا منطق خاصی که برنامه شما به آن نیاز دارد، ایجاد کنید، بدون اینکه مجبور به ایجاد فایل‌های فیزیکی باشید.
مثال:
یک مثال ساده از یک ماژول مجازی در مستندات Vite نمایش داده شده است:
// vite.config.js
export default function myPlugin() {
const virtualModuleId = 'virtual:my-module';
const resolvedVirtualModuleId = '\0' + virtualModuleId;

return {
name: 'my-plugin',
resolveId(id) {
if (id === virtualModuleId) {
return resolvedVirtualModuleId;
}
},
load(id) {
if (id === resolvedVirtualModuleId) {
return `export const msg = "from virtual module"`;
}
},
};
}

سپس، در کد منبع خود، می‌توانید این ماژول مجازی را وارد کنید:
// main.js
import { msg } from 'virtual:my-module';
console.log(msg); // Output: "from virtual module"

در اصل، ماژول‌های مجازی روشی قدرتمند برای تزریق داده‌های پویا یا مختص ساخت (build-specific) به پروژه Vite شما از طریق یک سازوکار وارد کردن استاندارد ارائه می‌دهند.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1
هفت تکنیک قدرتمند وراثت در زبان JavaScript

در زبان JavaScript، وراثت یکی از راهکارهای کلیدی برای بازاستفاده از کد و مدیریت روابط پیچیده میان اشیاء محسوب می‌شود. این زبان با تکیه بر مدل مبتنی بر نمونه‌اولیه (Prototype)، الگوهای گوناگونی برای پیاده‌سازی وراثت ارائه می‌دهد که هر یک مزایا و کاربردهای منحصربه‌فردی دارند. در این راهنما به بررسی این تکنیک‌ها می‌پردازیم و موارد استفاده‌ی مناسب برای هر یک را معرفی می‌کنیم.

این مقاله به معرفی هفت نوع اصلی وراثت در JavaScript می‌پردازد؛ از وراثت زنجیره‌ای مبتنی بر نمونه‌اولیه، گرفته تا وراثت مدرن مبتنی بر کلاس‌ها در ES6. هر روش، نقاط قوت و ضعف خاص خود را دارد که به توسعه‌دهندگان اجازه می‌دهد بسته به شرایط و نیازمندی‌های عملکردی، بهترین گزینه را انتخاب کنند. با درک و اجرای صحیح این مدل‌های وراثت، توانایی ایجاد کدی ساخت‌یافته، قابل نگهداری و منظم در JavaScript را به‌دست خواهید آورد.

---

### ۱. وراثت زنجیره‌ای از طریق نمونه‌اولیه (Prototype Chain Inheritance)

وراثت زنجیره‌ای یکی از ساده‌ترین روش‌های وراثت در JavaScript به شمار می‌آید. در این الگو، یک شیء می‌تواند از طریق زنجیره‌ای از نمونه‌اولیه‌ها، به ویژگی‌ها و متدهای شیء والد دسترسی پیدا کند.

نمونه کد:

function Animal() {
this.species = 'پستاندار';
this.habits = ['خواب', 'غذا خوردن'];
}
function Dog() {
this.breed = 'بولداگ';
}
Dog.prototype = new Animal();

let d1 = new Dog();
let d2 = new Dog();
d1.habits.push('پارس کردن');


مزایا:
راه‌اندازی ساده؛ دسترسی کامل زیرکلاس‌ها به متدهای نمونه‌اولیه‌ی والد.

معایب:
ویژگی‌های ارجاعی (مانند آرایه‌ها) بین تمام نمونه‌ها مشترک‌اند که ممکن است باعث ایجاد عوارض جانبی شود؛ همچنین سازنده‌ی والد برای هر نمونه جدید فراخوانی می‌شود.

---

### ۲. وراثت سازنده (Constructor Inheritance)

در این روش، ویژگی‌های شیء والد با فراخوانی مستقیم سازنده‌ی آن درون سازنده‌ی فرزند، به فرزند منتقل می‌شود.

نمونه کد:

function Animal(species) {
this.species = species;
this.activities = [];
}
function Dog(breed) {
Animal.call(this, 'پستاندار');
this.breed = breed;
}


مزایا:
هر نمونه، ویژگی‌های مستقل خود را دارد؛ امکان ارسال پارامتر به شیء والد وجود دارد.

معایب:
متدها بین نمونه‌ها به اشتراک گذاشته نمی‌شوند و این امر می‌تواند منجر به افزونگی در کد شود.


### ۳. وراثت ترکیبی (Composite Inheritance)

وراثت ترکیبی، دو روش وراثت زنجیره‌ای و سازنده را با یکدیگر تلفیق می‌کند تا هم ویژگی‌های منحصر‌به‌فردی به زیرکلاس‌ها بدهد و هم امکان استفاده از متدهای شیء والد را فراهم سازد.

نمونه کد:

function Animal(species) {
this.species = species;
this.activities = [];
}
Animal.prototype.getSpecies = function () {
return this.species;
};
function Dog(breed) {
Animal.call(this, 'پستاندار');
this.breed = breed;
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;


مزایا:
زیرکلاس‌ها دارای ویژگی‌های خاص خود و دسترسی به متدهای نمونه‌اولیه والد هستند.

معایب:
سازنده‌ی والد دو بار فراخوانی می‌شود که این موضوع منجر به افزایش سربار اجرایی می‌گردد.

---

### ۴. وراثت انگلی (Parasitic Inheritance)

در این الگو، یک شیء ایجاد، تغییر داده شده و سپس بازگردانده می‌شود. این رویکرد انعطاف‌پذیری زیادی فراهم می‌کند، اما پیچیدگی نیز به همراه دارد.

نمونه کد:

function Animal() {
this.species = 'پستاندار';
this.habits = ['غذا خوردن', 'خوابیدن'];
}
function Dog() {
Animal.call(this);
this.breed = 'بولداگ';
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;


مزایا:
امکان توسعه‌ی نمونه‌اولیه در اشیای شبیه‌سازی‌شده را فراهم می‌سازد.

معایب:
برای ساختارهای بزرگ وراثتی مناسب نیست.

---

### ۵. وراثت مبتنی بر نمونه‌اولیه (Prototype Inheritance)

در این الگو از تابع Object.create برای ایجاد مستقیم یک شیء جدید با نمونه‌اولیه‌ی مشخص استفاده می‌شود.

نمونه کد:

let animal = {
species: 'پستاندار',
traits: ['خون‌گرم', 'مهره‌دار'],
};
function createClone(obj) {
let clone = Object.create(obj);
clone.getTraits = function () {
return this.traits;
};
return clone;
}
let dog = createClone(animal);


مزایا:
ساده است و نیازی به تعریف سازنده ندارد.

معایب:
تمام نمونه‌ها ویژگی‌های نمونه‌اولیه را به‌صورت مشترک دارند.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1
---

### ۶. وراثت انگلی ترکیبی (Parasitic Compositional Inheritance)

این روش، نسخه‌ای بهینه‌شده از وراثت ترکیبی است که با استفاده از Object.create از فراخوانی چندباره‌ی سازنده جلوگیری می‌کند.

نمونه کد:

function Animal(species) {
this.species = species;
this.traits = [];
}
function Dog(breed) {
Animal.call(this, 'پستاندار');
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;


مزایا:
فراخوانی مضاعف سازنده حذف می‌شود و در عین حال مزایای وراثت ترکیبی حفظ می‌گردد.

معایب:
پیاده‌سازی پیچیده‌تر شده و نیاز به محصورسازی بیشتری دارد.

---

### ۷. وراثت مبتنی بر کلاس در ES6 (ES6 Class Inheritance)

با معرفی ES6، زبان JavaScript سینتکسی برای کلاس‌ها ارائه داد که فرآیند وراثت را برای توسعه‌دهندگان آسان‌تر و شهودی‌تر می‌سازد.

نمونه کد:

class Animal {
constructor(species) {
this.species = species;
}
getSpecies() {
return this.species;
}
}

class Dog extends Animal {
constructor(breed) {
super('پستاندار');
this.breed = breed;
}
}


مزایا:
سینتکس تمیز و قابل‌فهم، مشابه زبان‌های شیء‌گرای سنتی.

معایب:
ممکن است نیاز به تبدیل (Transpiling) داشته باشد و در برخی موارد، تفاوت اندکی از نظر عملکرد با روش‌های مبتنی بر نمونه‌اولیه دارد.

---

### جمع‌بندی

انتخاب مناسب‌ترین روش وراثت در JavaScript بستگی به نیازهای پروژه دارد. در حالی که وراثت مبتنی بر کلاس‌های ES6 به‌دلیل خوانایی و سادگی بسیار محبوب است، اما الگوهای مبتنی بر نمونه‌اولیه همچنان نقش پررنگی در توسعه‌ی ماژولار و کارآمد ایفا می‌کنند. درک این تکنیک‌ها به شما کمک می‌کند تا ابزاری متناسب با ساختار و انعطاف‌پذیری مورد نیاز خود را انتخاب کرده و کدی منظم، توسعه‌پذیر و بهینه تولید نمایید.


🔗https://jsdev.space/inheritance-js/
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
برای همگام‌سازی یا انتقال داده‌ها میان تب‌های مختلف مرورگر**، می‌توان از **LocalStorage استفاده کرد.

در فریم‌ورک Vue نیز امکان ایجاد یک پوشش واکنشی (reactive wrapper) بر روی آن وجود دارد.

اما راه‌حلی بسیار ساده‌تر و کارآمدتر هم در دسترس است: استفاده از Broadcast Channel API
[مشاهده در MDN](https://developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)

با استفاده از این API می‌توان یک کانال ارتباطی ایجاد کرد، در آن پیام ارسال نمود و به پیام‌های دریافتی نیز گوش داد.

### ✳️ نمونه کد:

// ایجاد کانال
const bc = new BroadcastChannel("share_channel");

// ارسال پیام به کانال
bc.postMessage("یک پیام نمونه");

// دریافت پیام از کانال
bc.onmessage = (event) => {
console.log(event);
};


همچنین می‌توان از متد postMessage برای ارتباط میان پنجره‌های باز شده (مانند صفحه ورود) با پنجره والد استفاده کرد؛ به‌صورت زیر:

window.opener.postMessage()


این روش برای سناریوهایی مانند احراز هویت در پنجره‌ی جداگانه و اطلاع‌رسانی به برنامه اصلی بسیار مفید است.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1👌1
iframe چیست؟
<iframe> یا *Inline Frame* یک عنصر HTML است که امکان درج یک صفحه HTML یا یک برنامه وب دیگر را درون سند فعلی فراهم می‌کند.

---

### 🔹 موارد اصلی استفاده از iframe:

* جاسازی محتوای خارجی مانند ویدیوهای YouTube، نقشه‌های Google Maps یا انواع ویجت‌ها
* جداسازی کدهای شخص ثالث (مانند فرم‌های پرداخت بانکی)
* بارگذاری اسناد مانند PDF یا گزارش‌های HTML
* معماری مایکروسرویس و تعامل میان برنامه‌های مستقل

---

### 🔸 نمونه ساده‌ی استفاده از iframe:

<iframe 
src="https://example.com"
width="۶۰۰"
height="۴۰۰"
title="نمونه iframe"
></iframe>


---

### 🔹 ویژگی‌های کلیدی عنصر iframe:
src نشانی محتوایی که درون فریم بارگذاری می‌شود
width / height تعیین عرض و ارتفاع فریم
frameborder ویژگی منسوخ‌شده؛ بهتر است با CSS مدیریت شود (border: none)
allow تعیین مجوزها مانند استفاده از دوربین، میکروفن یا پرداخت
sandbox محدودسازی دسترسی iframe به اسکریپت‌ها، فرم‌ها و منابع دیگر

---

### 🔸 نمونه‌ای از بارگذاری پویا در Vue:

<template>
<div>
<input v-model="iframeUrl" placeholder="یک آدرس وارد کنید (مثلاً https://vuejs.org)" />
<button @click="loadIframe">بارگذاری</button>

<iframe
ref="iframeRef"
:src="currentUrl"
width="۱۰۰%"
height="۵۰۰px"
style="border: none;"
></iframe>
</div>
</template>

<script setup>
import { ref } from 'vue';

const iframeUrl = ref('');
const currentUrl = ref('');
const iframeRef = ref(null);

const loadIframe = () => {
if (!iframeUrl.value.startsWith('http')) {
alert('آدرس باید با http:// یا https:// شروع شود');
return;
}
currentUrl.value = iframeUrl.value;
};
</script>


---

### 🔐 ملاحظات امنیتی iframe:

خطرات احتمالی:

* *حمله XSS* در صورت بارگذاری سایت مخرب
* *نشت داده‌ها* به دلیل دسترسی iframe به پنجره والد

راه‌حل: استفاده از ویژگی sandbox برای محدودسازی دسترسی‌ها

<iframe 
src="https://example.com"
sandbox="allow-scripts allow-same-origin"
></iframe>


گزینه‌های متداول sandbox:

* allow-scripts: اجازه اجرای اسکریپت‌ها
* allow-same-origin: اجازه دسترسی به اطلاعات دامنه‌ی مشابه
* allow-forms: مجوز ارسال فرم‌ها
* allow-popups: امکان باز کردن پنجره جدید

---

### 🧩 نمونه‌های کاربردی واقعی:

#### جاسازی ویدئوی یوتیوب:

<template>
<iframe
width="۵۶۰"
height="۳۱۵"
src="https://www.youtube.com/..."
title="پخش‌کننده ویدیوی YouTube"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>
</template>


#### جاسازی نقشه گوگل:

<template>
<iframe
width="۶۰۰"
height="۴۵۰"
style="border:0"
loading="lazy"
:src="`https://www.google.com/maps/embed/v1/place....`"
></iframe>
</template>


#### نمایش فایل PDF:

<template>
<iframe
src="/documents/document.pdf"
width="۱۰۰%"
height="۶۰۰px"
></iframe>
</template>


---

### جمع‌بندی

<iframe> ابزاری قدرتمند برای درج محتوای خارجی در صفحات وب است، اما نیازمند مدیریت دقیق امنیتی می‌باشد.

* از ویژگی sandbox برای محدودسازی استفاده کنید
* بارگذاری فریم را با رویداد @load کنترل نمایید
* از postMessage برای برقراری ارتباط بین iframe و پنجره والد بهره بگیرید



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
نسبت فشرده‌سازی (Compression Ratio) چیست؟
نسبت فشرده‌سازی، نسبت اندازه داده‌های اولیه به اندازه داده‌های فشرده‌شده است.

### فرمول:

نسبت فشرده‌سازی = اندازه اولیه ÷ اندازه پس از فشرده‌سازی

### مثال:

* فایل اولیه: صد کیلوبایت
* پس از فشرده‌سازی: بیست کیلوبایت
* نسبت فشرده‌سازی: ۱۰۰ ÷ ۲۰ = پنج به یک (یا به‌صورت خلاصه: پنج)

هرچه این نسبت بزرگ‌تر باشد، فشرده‌سازی مؤثرتر است و داده کمتری از طریق شبکه منتقل می‌شود.

---

## فشرده‌سازی در HTTP (مانند Gzip، Brotli، Deflate)

در این روش، سرور فایل‌های متنی (مانند HTML، CSS، JS و JSON) را پیش از ارسال به کاربر، فشرده می‌کند.

### نمونه‌ای از هدر پاسخ HTTP:

Content-Encoding: gzip


---

## فشرده‌سازی تصاویر (WebP، AVIF، JPEG XL)

فرمت‌های تصویری از الگوریتم‌های فشرده‌سازی مختلف استفاده می‌کنند:

* بدون افت کیفیت (Lossless): مانند PNG، WebP در حالت بدون افت
* با افت کیفیت (Lossy): مانند JPEG، WebP، AVIF

### مثال:

* تصویر PNG اولیه: پانصد کیلوبایت
* تصویر WebP فشرده‌شده: صد کیلوبایت
* نسبت فشرده‌سازی: پنج به یک

---

## فشرده‌سازی ویدیو و صدا (H.265، Opus، AAC)

کدک‌های ویدیویی مانند H.265 می‌توانند نسبت فشرده‌سازی ده به یک یا حتی بیشتر داشته باشند، در مقایسه با ویدیوهای خام.

---

## فشرده‌سازی پاسخ‌های API و پایگاه‌های داده

پاسخ‌های JSON در API را می‌توان با gzip یا brotli فشرده کرد. برخی پایگاه‌های داده NoSQL مانند MongoDB از فشرده‌سازی بلادرنگ پشتیبانی می‌کنند.

---

## مقایسه الگوریتم‌های فشرده‌سازی

| الگوریتم | نسبت فشرده‌سازی | سرعت | پشتیبانی در مرورگرها |
| -------- | --------------- | -------------- | ------------------------- |
| Gzip | سه تا شش به یک | سریع | همه مرورگرها |
| Brotli | پنج تا ده به یک | کندتر ولی بهتر | مرورگرهای مدرن |
| Deflate | دو تا پنج به یک | سریع | سازگار با مرورگرهای قدیمی |

---

## فعال‌سازی فشرده‌سازی در سرور

### در Nginx:

gzip on;
gzip_types text/html text/css application/javascript;
gzip_min_length 256;
gzip_comp_level 6; # سطح فشرده‌سازی از یک تا نه


### در Node.js (Express):

const compression = require('compression');
app.use(compression({ level: 6 })); // سطح فشرده‌سازی Gzip


---

## مثال عملی: مقایسه Gzip و Brotli

فرض کنید فایل bundle.js با حجم یک مگابایت داریم:

| الگوریتم | اندازه فشرده‌شده | نسبت فشرده‌سازی |
| --------------- | ------------------- | ----------------------------- |
| بدون فشرده‌سازی | یک مگابایت | یک به یک |
| Gzip (سطح ۶) | دویست کیلوبایت | پنج به یک |
| Brotli (سطح ۱۱) | صد و پنجاه کیلوبایت | حدود شش و شصت و هفت صدم به یک |

نتیجه: Brotli فشرده‌سازی بهتری ارائه می‌دهد، اما مصرف CPU بیشتری دارد.

---

## چگونه نسبت فشرده‌سازی را اندازه‌گیری کنیم؟

### در Chrome DevTools:

۱. تب Network را باز کنید
۲. فایل مورد نظر را انتخاب کنید (مثلاً فایل‌های .js یا .css)
۳. در بخش Header بررسی کنید:

* Content-Length (اندازه پس از فشرده‌سازی)
* X-Original-Size (در صورت ارسال توسط سرور)

### ابزارهای ارزیابی:

* Lighthouse (تب Performance)
* WebPageTest (نمایش میزان صرفه‌جویی در ترافیک)

---

## بهینه‌سازی فشرده‌سازی در پروژه‌های وب

برای فایل‌های استاتیک، از Brotli استفاده کنید (فشرده‌سازی بهتر)
برای محتوای پویا، Gzip گزینه مناسبی است (سرعت بیشتر)
تصاویر را بهینه‌سازی کنید (WebP/AVIF + ابزار Sharp در Node.js)
فایل‌های JS/CSS را پیش از فشرده‌سازی minify کنید (با Terser، CSSNano)
کش‌کردن مناسب با Cache-Control و استفاده از CDN





#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
## نمونه‌ای از بهینه‌سازی پروژه Vue.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import viteCompression from 'vite-plugin-compression';

export default defineConfig({
plugins: [
vue(),
// حالت ساده با Gzip
viteCompression(),

// پیکربندی کامل‌تر برای Brotli + Gzip
viteCompression({
algorithm: 'brotliCompress', // الگوریتم پیش‌فرض 'gzip' است
ext: '.br', // پسوند فایل Brotli
threshold: 10240, // حداقل اندازه فایل (بر حسب بایت)
verbose: true, // نمایش لاگ در حین پردازش
deleteOriginFile: false, // عدم حذف فایل اصلی پس از فشرده‌سازی
filter: /\.(js|css|json|html|ico|svg)(\?.*)?$/i, // الگوی فایل‌های قابل فشرده‌سازی
}),
viteCompression({ algorithm: 'gzip' }), // پشتیبانی هم‌زمان از Gzip
],
build: {
// تنظیمات اضافی برای ساخت
chunkSizeWarningLimit: 1600, // افزایش محدودیت هشدار برای اندازه چانک‌ها
},
});


---

## نتیجه‌گیری

نسبت فشرده‌سازی**، یکی از شاخص‌های کلیدی برای ارزیابی اثربخشی فشرده‌سازی در وب است.
فشرده‌سازی صحیح، موجب افزایش سرعت بارگذاری صفحات و کاهش مصرف ترافیک می‌شود.

* **نسبت مناسب برای متن:
بین پنج تا ده به یک (Brotli)
* برای تصاویر: بین سه تا بیست به یک (WebP/AVIF)
* برای ویدیوها: بین ده تا صد به یک (H.265)



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript