ورودی به Compositor می آید
این آخرین مورد از سری 4 قسمتی وبلاگ است که به داخل کروم نگاه می کند. بررسی نحوه مدیریت کد ما برای نمایش یک وب سایت. در پست قبلی به فرآیند رندر نگاه کردیم و با کامپوزیتور آشنا شدیم . در این پست، ما به این خواهیم پرداخت که چگونه کامپوزیتور هنگام ورود ورودی کاربر، تعامل صاف را ممکن میسازد.
رویدادها را از دیدگاه مرورگر وارد کنید
هنگامی که "رویدادهای ورودی" را می شنوید، ممکن است فقط به تایپ در جعبه متن یا کلیک ماوس فکر کنید، اما از دیدگاه مرورگر، ورودی به معنای هر حرکتی از طرف کاربر است. پیمایش چرخ ماوس یک رویداد ورودی است و لمس یا روی ماوس نیز یک رویداد ورودی است.
هنگامی که ژست کاربر مانند لمس روی صفحه رخ می دهد، فرآیند مرورگر همان چیزی است که در ابتدا ژست را دریافت می کند. با این حال، فرآیند مرورگر فقط از جایی که آن حرکت رخ داده است آگاه است زیرا محتوای داخل یک برگه توسط فرآیند رندر کنترل می شود. بنابراین فرآیند مرورگر نوع رویداد (مانند touchstart
) و مختصات آن را به فرآیند رندر میفرستد. فرآیند رندر با یافتن هدف رویداد و اجرای شنوندگان رویداد که پیوست شده اند، رویداد را به طور مناسب مدیریت می کند.
Compositor رویدادهای ورودی را دریافت می کند
در پست قبلی به این موضوع پرداختیم که چگونه کامپوزیتور میتواند با ترکیب لایههای شطرنجیشده، اسکرول را به راحتی انجام دهد. اگر هیچ شنونده رویداد ورودی به صفحه متصل نباشد، رشته Compositor می تواند یک فریم ترکیبی جدید کاملا مستقل از رشته اصلی ایجاد کند. اما اگر برخی از شنوندگان رویداد به صفحه متصل شوند چه میشود؟ چگونه موضوع ترکیبکننده متوجه میشود که آیا رویداد باید مدیریت شود؟
درک منطقه غیر سریع اسکرول
از آنجایی که اجرای جاوا اسکریپت کار رشته اصلی است، هنگامی که یک صفحه ترکیب می شود، رشته ترکیب کننده ناحیه ای از صفحه را که کنترل کننده های رویداد را به عنوان "منطقه غیر سریع اسکرول پذیر" متصل می کند، علامت گذاری می کند. با داشتن این اطلاعات، رشته ترکیبکننده میتواند از ارسال رویداد ورودی به رشته اصلی در صورت وقوع رویداد در آن منطقه اطمینان حاصل کند. اگر رویداد ورودی از خارج از این منطقه باشد، آنگاه رشته کامپوزیتور بدون انتظار برای رشته اصلی، فریم جدید را ترکیب می کند.
هنگام نوشتن کنترل کننده رویداد، مراقب باشید
یک الگوی رایج مدیریت رویداد در توسعه وب، تفویض رویداد است. از آنجایی که رویدادها حباب هستند، می توانید یک کنترل کننده رویداد را در بالاترین عنصر متصل کنید و وظایف را بر اساس هدف رویداد محول کنید. ممکن است کدهایی مانند زیر را دیده یا نوشته باشید.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
از آنجایی که شما فقط نیاز به نوشتن یک کنترل کننده رویداد برای همه عناصر دارید، ارگونومی این الگوی تفویض رویداد جذاب است. با این حال، اگر از دید مرورگر به این کد نگاه کنید، اکنون کل صفحه به عنوان یک منطقه غیر سریع اسکرول مشخص شده است. این به این معنی است که حتی اگر برنامه شما به ورودی از قسمتهای خاصی از صفحه اهمیتی نمیدهد، رشته ترکیبکننده باید با رشته اصلی ارتباط برقرار کند و هر بار که یک رویداد ورودی وارد میشود منتظر آن باشد. بنابراین، توانایی پیمایش روان ترکیبکننده شکست خورده است.
برای کاهش این اتفاق، میتوانید گزینههای passive: true
را در شنونده رویداد خود پاس کنید. این به مرورگر اشاره می کند که هنوز می خواهید به رویداد در رشته اصلی گوش دهید، اما compositor می تواند ادامه دهد و فریم جدید را نیز ترکیب کند.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
بررسی کنید آیا رویداد قابل لغو است یا خیر
تصور کنید کادری در صفحه ای دارید که می خواهید جهت اسکرول را فقط به اسکرول افقی محدود کنید.
استفاده از گزینه passive: true
در رویداد اشاره گر شما به این معنی است که پیمایش صفحه می تواند صاف باشد، اما ممکن است پیمایش عمودی تا زمانی که می خواهید از preventDefault
تا جهت پیمایش را محدود کنید، شروع شده باشد. با استفاده از روش event.cancelable
می توانید این موضوع را بررسی کنید.
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
از طرف دیگر، میتوانید از قانون CSS مانند touch-action
برای حذف کامل کنترلکننده رویداد استفاده کنید.
#area {
touch-action: pan-x;
}
یافتن هدف رویداد
هنگامی که thread کامپوزیتور یک رویداد ورودی را به رشته اصلی ارسال می کند، اولین چیزی که اجرا می شود یک تست ضربه برای یافتن هدف رویداد است. تست ضربه از دادههای ثبت رنگ استفاده میکند که در فرآیند رندر تولید شدهاند تا بفهمند که زیر مختصات نقطهای که رویداد در آن رخ داده است، چه چیزی وجود دارد.
به حداقل رساندن ارسال رویداد به موضوع اصلی
در پست قبلی، در مورد اینکه چگونه صفحه نمایش معمولی ما صفحه نمایش را 60 بار در ثانیه تازه می کند و چگونه باید با آهنگ حرکت برای انیمیشن روان همگام شویم، بحث کردیم. برای ورودی، یک دستگاه صفحه لمسی معمولی رویدادهای لمسی را 60 تا 120 بار در ثانیه ارائه می دهد و یک ماوس معمولی رویدادها را 100 بار در ثانیه ارائه می دهد. رویداد ورودی از وفاداری بالاتری نسبت به صفحه نمایش ما برخوردار است.
اگر یک رویداد پیوسته مانند touchmove
120 بار در ثانیه به رشته اصلی ارسال شود، ممکن است در مقایسه با میزان کندی که صفحه نمایش میتواند بازخوانی کند، تعداد زیادی تست ضربه و اجرای جاوا اسکریپت را آغاز کند.
برای به حداقل رساندن تماسهای بیش از حد به رشته اصلی، Chrome رویدادهای پیوسته (مانند wheel
، mousewheel
، mousemove
، pointermove
، touchmove
) را یکپارچه میکند و ارسال را درست قبل از requestAnimationFrame
بعدی AnimationFrame به تأخیر میاندازد.
هر گونه رویداد مجزا مانند keydown
، keyup
، mouseup
، mousedown
، touchstart
، و touchend
فورا ارسال می شود.
از getCoalescedEvents
برای دریافت رویدادهای درون فریم استفاده کنید
برای اکثر برنامه های کاربردی وب، رویدادهای ادغام شده باید برای ارائه یک تجربه کاربری خوب کافی باشد. با این حال، اگر در حال ساختن چیزهایی مانند ترسیم برنامه و قرار دادن مسیری بر اساس مختصات touchmove
هستید، ممکن است مختصات بینالمللی را برای کشیدن یک خط صاف از دست بدهید. در این صورت، میتوانید از متد getCoalescedEvents
در رویداد اشارهگر استفاده کنید تا اطلاعاتی درباره آن رویدادهای ادغام شده به دست آورید.
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
مراحل بعدی
در این مجموعه، عملکردهای داخلی یک مرورگر وب را پوشش داده ایم. اگر هرگز به این فکر نکردهاید که چرا DevTools اضافه کردن {passive: true}
را در کنترلکننده رویداد خود توصیه میکند یا اینکه چرا ممکن است ویژگی async
در تگ اسکریپت خود بنویسید، امیدوارم این مجموعه روشن کند که چرا مرورگر به این اطلاعات برای ارائه سریعتر و روانتر نیاز دارد. تجربه وب
از فانوس دریایی استفاده کنید
اگر میخواهید کد خود را برای مرورگر خوب کنید اما نمیدانید از کجا شروع کنید، Lighthouse ابزاری است که ممیزی هر وبسایتی را اجرا میکند و گزارشی از آنچه درست انجام میشود و آنچه نیاز به بهبود دارد به شما میدهد. خواندن لیست ممیزی ها همچنین به شما ایده می دهد که یک مرورگر به چه چیزهایی اهمیت می دهد.
یاد بگیرید چگونه عملکرد را اندازه گیری کنید
ترفندهای عملکرد ممکن است برای سایت های مختلف متفاوت باشد، بنابراین بسیار مهم است که عملکرد سایت خود را بسنجید و تصمیم بگیرید که چه چیزی برای سایت شما مناسب است. تیم Chrome DevTools آموزش های کمی در مورد نحوه اندازه گیری عملکرد سایت شما دارد.
سیاست ویژگی را به سایت خود اضافه کنید
اگر می خواهید یک قدم اضافی بردارید، سیاست ویژگی یک ویژگی جدید پلتفرم وب است که می تواند حفاظی برای شما در هنگام ساخت پروژه باشد. روشن کردن خط مشی ویژگی رفتار خاص برنامه شما را تضمین می کند و از اشتباه کردن شما جلوگیری می کند. به عنوان مثال، اگر میخواهید مطمئن شوید که برنامه شما هرگز تجزیه را مسدود نمیکند، میتوانید برنامه خود را روی خطمشی اسکریپتهای همزمان اجرا کنید. وقتی sync-script: 'none'
فعال باشد، جاوا اسکریپت مسدودکننده تجزیه کننده از اجرای آن جلوگیری خواهد شد. این مانع از مسدود کردن هر کد شما در تجزیه کننده می شود و مرورگر نیازی به نگرانی در مورد توقف تجزیه کننده ندارد.
جمع کنید
وقتی شروع به ساختن وبسایت کردم، تقریباً فقط به این اهمیت میدادم که چگونه کدم را بنویسم و چه چیزی به من کمک میکند تا کارایی بیشتری داشته باشم. این چیزها مهم هستند، اما باید به این فکر کنیم که مرورگر چگونه کدهایی را که می نویسیم می گیرد. مرورگرهای مدرن روی روش هایی سرمایه گذاری می کنند که تجربه وب بهتری را برای کاربران فراهم کنند. خوب بودن با مرورگر با سازماندهی کد ما، به نوبه خود، تجربه کاربری شما را بهبود می بخشد. امیدوارم در تلاش برای رفتار خوب با مرورگرها به من بپیوندید!
از همه کسانی که پیش نویس های اولیه این مجموعه را بررسی کردند، از جمله (اما نه محدود به): الکس راسل ، پل آیریش ، مگین کرنی ، اریک بیدلمن ، ماتیاس باینس ، آدی عثمانی ، کینوکو یاسودا ، ناسکو اسکوف و چارلی ریس بسیار سپاسگزاریم.
آیا از این سریال لذت بردید؟ اگر سؤال یا پیشنهادی برای پست آینده دارید، مایلم در بخش نظرات زیر یا @kosamari در توییتر از شما بشنوم.