خلاصه و تحلیل مقاله: بهینه‌سازی تأخیر ورودی (Input Delay)

مقاله ارائه‌شده از وب‌سایت web.dev به بررسی مفهوم تأخیر ورودی (Input Delay)، یکی از اجزای کلیدی معیار Interaction to Next Paint (INP) در Core Web Vitals، و روش‌های کاهش آن برای بهبود پاسخگویی و تعاملات وب‌سایت می‌پردازد. در ادامه، خلاصه‌ای جامع از محتوای مقاله به همراه توضیحات تکمیلی ارائه می‌شود.


تأخیر ورودی چیست؟

تأخیر ورودی (Input Delay) مدت زمانی است که از لحظه شروع تعامل کاربر با صفحه (مانند کلیک، ضربه روی صفحه لمسی، یا فشردن کلید) تا آغاز اجرای callbackهای رویداد (event callbacks) طول می‌کشد. این تأخیر بخشی از تأخیر کلی تعامل است که در معیار INP اندازه‌گیری می‌شود.

  • چرا مهم است؟ تأخیر ورودی می‌تواند تجربه کاربری را تحت تأثیر قرار دهد، به‌ویژه اگر طولانی باشد و باعث تأخیر در پاسخگویی صفحه شود.
  • اجتناب‌ناپذیر بودن بخشی از تأخیر: مقداری از تأخیر ورودی به دلیل زمان لازم برای شناسایی ورودی توسط سیستم‌عامل و انتقال آن به مرورگر اجتناب‌ناپذیر است. با این حال، فعالیت‌های سنگین در نخ اصلی (main thread) می‌توانند این تأخیر را به‌طور قابل‌توجهی افزایش دهند.

تصویر تأخیر ورودی


چگونه درباره تأخیر ورودی فکر کنیم؟

برای دستیابی به یک امتیاز خوب در معیار INP (زیر 200 میلی‌ثانیه)، باید تمام بخش‌های تعامل، از جمله تأخیر ورودی، تا حد ممکن کوتاه شوند. اگرچه نمی‌توان تأخیر ورودی را کاملاً حذف کرد، اما با مدیریت فعالیت‌های نخ اصلی می‌توان آن را به حداقل رساند تا تجربه کاربری بهبود یابد.


چگونه تأخیر ورودی را کاهش دهیم؟

مقاله چندین راهکار برای کاهش تأخیر ورودی ارائه می‌دهد که به سه دسته اصلی تقسیم می‌شوند:

1. اجتناب از تایمرهای تکراری که کار سنگین در نخ اصلی ایجاد می‌کنند

  • تایمرهای جاوااسکریپت:
  • setTimeout: این تابع یک callback را پس از زمان مشخصی اجرا می‌کند. اگرچه به‌خودی‌خود مشکل‌ساز نیست و حتی می‌تواند برای تقسیم وظایف طولانی مفید باشد (مانند جلوگیری از وظایف طولانی)، اما اگر callback آن کار سنگینی انجام دهد یا به‌صورت بازگشتی (recursive) استفاده شود، ممکن است باعث تأخیر ورودی شود.
  • setInterval: این تابع callback را به‌صورت دوره‌ای و مداوم اجرا می‌کند، که احتمال تداخل با تعاملات کاربر را افزایش می‌دهد، زیرا ممکن است در زمان نامناسبی اجرا شود و نخ اصلی را مشغول کند.

  • مشکلات:

  • تایمرهای تکراری: setInterval به دلیل اجرای مداوم، احتمال بیشتری برای ایجاد تأخیر ورودی دارد، به‌ویژه اگر callback آن شامل کارهای سنگین باشد.
  • اسکریپت‌های شخص ثالث: تایمرهای موجود در اسکریپت‌های شخص ثالث ممکن است خارج از کنترل شما باشند. در این موارد، باید ضرورت این اسکریپت‌ها را ارزیابی کرده و با ارائه‌دهندگان آن‌ها برای بهینه‌سازی همکاری کنید.

  • راهکارها:

  • بررسی کنید که آیا تایمرها واقعاً لازم هستند یا خیر.
  • کار داخل callbackهای تایمر را به حداقل برسانید.
  • در صورت امکان، از setTimeout به‌جای setInterval استفاده کنید تا کنترل بیشتری بر زمان‌بندی داشته باشید.

تصویر تأثیر تایمر بر تأخیر ورودی

2. اجتناب از وظایف طولانی (Long Tasks)

  • وظایف طولانی:
  • وظایف طولانی (کارهایی که بیش از 50 میلی‌ثانیه طول می‌کشند) نخ اصلی را مسدود می‌کنند و باعث افزایش تأخیر ورودی می‌شوند.
  • این وظایف ممکن است ناشی از پردازش جاوااسکریپت سنگین، بارگذاری منابع، یا تجزیه و تحلیل اسکریپت‌ها باشند.

  • راهکارها:

  • تقسیم وظایف طولانی: وظایف سنگین را به چندین task کوچک‌تر تقسیم کنید تا نخ اصلی فرصت پاسخگویی به تعاملات کاربر را داشته باشد. برای مثال: javascript setTimeout(() => { /* کار غیرضروری */ }, 0);
  • استفاده از Web Workers: کارهای سنگین محاسباتی را به Web Workers منتقل کنید تا نخ اصلی آزاد بماند.
  • مطالعه بیشتر: بهینه‌سازی وظایف طولانی.

  • توجه: وظایف شخص ثالث ممکن است همچنان بین وظایف شما اجرا شوند. API جدید scheduler.yield می‌تواند به مدیریت بهتر این مشکل کمک کند.

تصویر تأثیر وظایف طولانی

3. توجه به همپوشانی تعاملات (Interaction Overlap)

  • همپوشانی تعاملات:
  • زمانی رخ می‌دهد که کاربر تعامل جدیدی (مثل کلیک یا تایپ) را قبل از تکمیل رندر فریم مربوط به تعامل قبلی آغاز کند.
  • این مشکل در سناریوهایی مثل فیلدهای تکمیل خودکار (autocomplete) یا تایپ سریع در فرم‌ها شایع است.

  • راهکارها:

  • Debouncing ورودی‌ها: با محدود کردن تعداد اجرای callbackها در یک بازه زمانی، می‌توانید از اجرای بیش‌ازحد جلوگیری کنید: javascript function debounce(fn, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => fn(...args), wait); }; }
  • استفاده از AbortController:
    • برای لغو درخواست‌های fetch در حال انجام که ممکن است نخ اصلی را مشغول کنند: javascript const controller = new AbortController(); fetch(url, { signal: controller.signal }).catch(() => {}); controller.abort();
    • همچنین می‌توان از AbortController برای لغو رویدادهای خاص استفاده کرد.
  • استفاده از انیمیشن‌های CSS به‌جای جاوااسکریپت:
    • انیمیشن‌های جاوااسکریپت که از requestAnimationFrame استفاده می‌کنند، ممکن است نخ اصلی را مشغول کنند.
    • انیمیشن‌های CSS روی GPU یا نخ‌های compositor اجرا می‌شوند و تأثیر کمتری بر نخ اصلی دارند. از انیمیشن‌های غیرکامپوزیت‌شده (non-composited) اجتناب کنید.

تصویر همپوشانی تعاملات


نمودار پیشنهادی برای تجسم تأخیر ورودی

برای درک بهتر تأثیر تأخیر ورودی، می‌توان نموداری ایجاد کرد که زمان تأخیر ورودی را در سناریوهای مختلف (با وظایف طولانی و بدون آن‌ها) مقایسه کند. با این حال، مقاله داده‌های عددی دقیقی برای رسم نمودار ارائه نمی‌دهد، بنابراین نمودار زیر یک نمونه فرضی است که تأثیر وظایف طولانی و بهینه‌سازی آن‌ها را نشان می‌دهد:

{
  "type": "bar",
  "data": {
    "labels": ["With Long Tasks", "With Optimized Tasks"],
    "datasets": [{
      "label": "Input Delay (milliseconds)",
      "data": [100, 20],
      "backgroundColor": ["#FF3B30", "#34C759"],
      "borderColor": ["#CC2E2A", "#2E865F"],
      "borderWidth": 1
    }]
  },
  "options": {
    "scales": {
      "y": {
        "beginAtZero": true,
        "title": {
          "display": true,
          "text": "Input Delay (milliseconds)"
        }
      },
      "x": {
        "title": {
          "display": true,
          "text": "Scenario"
        }
      }
    },
    "plugins": {
      "legend": {
        "display": false
      },
      "title": {
        "display": true,
        "text": "Impact of Long Tasks on Input Delay"
      }
    }
  }
}

توضیح: این نمودار فرضی نشان می‌دهد که وظایف طولانی می‌توانند تأخیر ورودی را به 100 میلی‌ثانیه افزایش دهند، در حالی که با بهینه‌سازی (تقسیم وظایف یا استفاده از Web Workers)، این تأخیر به 20 میلی‌ثانیه کاهش می‌یابد. مقادیر فرضی هستند و باید با داده‌های واقعی جایگزین شوند.


جمع‌بندی

کاهش تأخیر ورودی بخش مهمی از بهبود معیار INP و ارائه تجربه کاربری سریع‌تر است. با اجتناب از تایمرهای تکراری سنگین، تقسیم وظایف طولانی، و مدیریت همپوشانی تعاملات، می‌توانید تأخیر ورودی را به حداقل برسانید. ابزارهایی مانند Chrome DevTools برای شناسایی تأخیرهای طولانی و تحلیل عملکرد نخ اصلی مفید هستند. همچنین، استفاده از تکنیک‌هایی مانند debouncing و AbortController می‌تواند به مدیریت تعاملات پیچیده کمک کند.

نویسنده: جرمی واگنر
منبع تصویر اصلی: Unsplash، توسط Erik Mclean

برای اطلاعات بیشتر، مطالعه مقالات مرتبط مانند بهینه‌سازی وظایف طولانی و debouncing ورودی‌ها توصیه می‌شود.