ورودی به 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
به تأخیر میاندازد.

هر گونه رویداد مجزا مانند 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 در توییتر از شما بشنوم.
،ورودی به 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
به تأخیر میاندازد.

هر گونه رویداد مجزا مانند 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 در توییتر از شما بشنوم.
،ورودی به 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
به تأخیر میاندازد.

هر گونه رویداد مجزا مانند 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 در توییتر از شما بشنوم.
،ورودی به 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 بار در ثانیه به موضوع اصلی ارسال شود ، ممکن است در مقایسه با میزان کند بودن صفحه نمایش ، مقدار بیش از حد آزمایشات HIT و اجرای JavaScript را ایجاد کند.

برای به حداقل رساندن تماس های بیش از حد به موضوع اصلی ، Chrome وقایع مداوم (مانند wheel
، mousewheel
، mousemove
، pointermove
، touchmove
) را به هم می پیوندد و تاخیر را تا قبل requestAnimationFrame
بعدی درخواست می کند.

هر رویدادی گسسته مانند keydown
، keyup
، mouseup
، mousedown
، touchstart
و touchend
بلافاصله ارسال می شود.
برای بدست آوردن رویدادهای درون قاب getCoalescedEvents
استفاده کنید
برای اکثر برنامه های وب ، رویدادهای همبستگی باید برای ارائه یک تجربه خوب کاربر کافی باشد. با این حال ، اگر شما در حال ساختن مواردی مانند طراحی کاربرد و قرار دادن مسیری بر اساس مختصات touchmove
هستید ، ممکن است بین مختصات بین هماهنگی ها از دست دهید تا یک خط صاف بکشید. در این حالت ، می توانید از روش getCoalescedEvents
در رویداد Pointer استفاده کنید تا اطلاعاتی در مورد آن وقایع همبستگی کسب کنید.

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'
فعال شده است ، از JavaScript تجزیه کننده جداکننده جلوگیری می شود. این امر مانع از مسدود کردن هر یک از کد شما می شود و مرورگر نیازی به نگرانی در مورد مکث تجزیه کننده ندارد.
جمع کنید

وقتی شروع به ساختن وب سایت ها کردم ، تقریباً فقط به این موضوع اهمیت می دادم که چگونه کد خود را می نویسم و چه چیزی به من کمک می کند تا تولیدی تر باشم. این چیزها مهم هستند ، اما ما همچنین باید در مورد چگونگی مرورگر کدی که می نویسیم ، فکر کنیم. مرورگرهای مدرن سرمایه گذاری کرده اند و همچنان در راه هایی برای ارائه تجربه وب بهتر برای کاربران سرمایه گذاری می کنند. با سازماندهی کد ما ، به نوبه خود ، با مرورگر خوب است ، تجربه کاربر را بهبود می بخشد. امیدوارم که در تلاش برای خوب بودن با مرورگرها به من بپیوندید!
با تشکر فراوان از همه کسانی که پیش نویس های اولیه این سریال را مرور کردند ، از جمله (اما محدود به آن): الکس راسل ، پل ایرلندی ، مگگین کرنی ، اریک بیدلمن ، ماتیاس بیینز ، آدی عثمانی ، کینوکو یاسودا ، ناسکو اسکوف و چارلی ریس.
آیا از این سریال لذت بردید؟ اگر برای پست آینده سؤال یا پیشنهادی دارید ، دوست دارم در بخش نظر زیر یا Kosamari در توییتر از شما بشنوم.