[译]深入了解现代web浏览器(四)
本文是根据Mariko Kosaka在谷歌开发者网站上的系列文章https://developer.chrome.com/blog/inside-browser-part4/翻译而来,共有四篇,该篇是第四篇。对于其中一些直译出来不太好理解的句子,笔者做了加工处理和提炼。
输入来到了合成器
在上篇文章中,我们了解了渲染过程和合成器;在这片文章中,我们将来了解下合成器是如何在用户输入到来时保持交互流畅的。
从浏览器的角度看输入事件
当你听到“输入事件”时,你可能只会想到在文本框中输入或是鼠标点击;但从浏览器的角度来看,来自用户的任何动作都是输入。鼠标滚轮滚动、触摸或者鼠标悬浮都是一个输入事件。
当用户在屏幕做出触摸等动作时,浏览器进程最先接收到该动作。但是浏览器进程只关注该动作发生的位置,因为tab页中的内容是由渲染进程处理的。浏览器进程把事件类型(比如touchstart)和其坐标发送给渲染进程;渲染进程会找到对应的事件目标并执行目标上绑定的事件监听器。

通过浏览器进程路由到渲染进程的输入事件
合成器接收输入事件
在上一篇文章中,我们知道了合成器是如何通过合成光栅化的图层来达到流畅地处理滚动的。如果页面上没有绑定事件监听,合成线程可以完全独立于主线程来创建合成帧。但如果页面上绑定有事件监听呢?毕竟事件监听的回调函数只能由主线程来执行。
理解非快速滚动区域
由于运行Javascript是主线程的工作,当页面被合成时,合成线程会将页面上绑定有事件监听的区域标记为“非快速滚动区域(Non-Fast Scrollable Region)”。拥有这些信息,合成线程能够确保当有事件发生在该区域时能将输入事件发送给主线程。如果输入事件是来自该区域之外的,则合成线程会继续合成新的帧而无需等待主线程执行事件处理函数。

非快速滚动区域的输入事件
注意你编写的事件处理函数
在web开发中一种很常见的处理模式是事件委派。由于事件冒泡机制的存在,你可以在最顶层的元素绑定事件处理函数然后根据事件目标来委派处理函数。你可能见过或者写过如下的代码:
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
由于你只需要为所有的元素只编写一个处理函数,从工程学上讲这种事件委派模式很有吸引力。但如果从浏览器的角度来看这段代码,现在整个页面都被标记为了“非快速滚动区域”。这意味着,即使你的应用并不关心页面上某些部分产生的输入事件,但只要发生了输入事件,合成线程还是不得不与主线程发生通信并等待。因此,合成线程的流畅性就会收到影响。

覆盖到了整个页面的非快速滚动区域
为了减轻这种情况的影响,你可以向事件处理函数中传入passive: true选项。这能提示浏览器你在事件处理函数中不会调用event.preventDefault(),就意味着你代码中不会通过event.preventDefault()语句阻止事件的默认行为(没有这个选项的话,则需要主线程执行完你的处理函数然后才能决定是否要阻止诸如滚动、失焦之类的事件默认行为,再告知合成线程要合成新的帧)。因此,在有passive: true的情况下,就可以让主线程在执行处理函数的同时,合成线程能继续合成下一帧。
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
寻找事件目标
当主线程收到合成线程发送的输入事件后,首先要做的就是执行命中测试来找到事件目标。命中测试利用渲染阶段生成的绘制记录来找出发生事件的点坐标下方的内容。

主线程根据绘制记录查询x.y点处绘制的内容
最小化事件调度到主线程
在上一篇文章中,我们讨论了典型的显示器是如何一秒钟刷新60次并保持动画流畅的节奏。对于输入,典型的触屏设备每秒会传递60-120次触屏事件,而典型的鼠标每秒会传递100次事件。输入事件的保真度高于我们屏幕刷新频率的保真度。
如果像touchmove这样的连续事件被每秒120次地发送到主线程,那么与屏幕的刷新速度相比,它会触发过多的命中测试和Javascript执行。

帧的时间轴上被大量事件淹没导致页面卡顿
为了尽量减少在主线程上的调用,Chrome会合并连续的事件(例如wheel, mousewheel, mousemove, pointermove, touchmove)并延迟调度直至下一次requestAnimationFrame之前。

与上一张图片相同的时间轴,但事件被合并和延迟了
任何的离散事件例如keydown,keyup,mouseup,mousedown,touchstart和touchend都会被立即调度。
使用getCoalescedEvents获取帧内事件
对于绝大部分的web应用,合并事件足以提供良好的用户体验。然而,如果你正在构建诸如绘画或者基于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.
}
})
下一步
在本系列中,我们介绍了Web浏览器的内部工作原理。如果您从未想过为什么DevTools建议在事件处理程序中添加{passive: true},或者为什么你可能要在脚本标签中写入async属性;我希望本系列文章能够阐明为什么浏览器需要这些信息来提供更快、更流畅的Web体验。
使用Lighthouse
如果你想让自己的代码对浏览器更友好但不知道从哪里开始,Lighthouse会是一个不错的工具。它可以对任何网站执行审计并提供一份报告,告知你哪些地方做的不错而哪些地方还需要改进。通过阅读审计列表,可以让你知道浏览器关心哪些指标。
了解如何衡量性能
对于不同站点性能调整会有所不同,因此如何衡量你的站点性能并确定最适合的方案是非常重要的。Chrome的DevTools团队有一些关于衡量站点性能的教程。
总结
当我开始构建网站的时候,几乎只关心书写代码和哪些能帮助我提高效率的东西。这些事当然很重要,但我们也应该思考下浏览器是如何处理我们书写的代码的。现代浏览器为给用户提供更好的web体验而持续努力。书写对浏览器“友好”的代码,这反过来会改进你的用户体验。希望你能加入我们一起追求对浏览器更为友好的世界!
[译]深入了解现代web浏览器(四)的更多相关文章
- [译]36 Days of Web Testing(四)
Day 19: UX 用户体验 Why ? 最近UX变得越来越火,用户提现往往会直接联想到易用性和设计. 在我看来,UX不仅仅是这两点.UX, User Experience ,对我而言,不单单是产 ...
- [C# 网络编程系列]专题四:自定义Web浏览器
转自:http://www.cnblogs.com/zhili/archive/2012/08/24/WebBrowser.html 前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发 ...
- 转:【专题四】自定义Web浏览器
前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...
- 专题四:自定义Web浏览器
前言: 前一个专题介绍了自定义的Web服务器,然而向Web服务器发出请求的正是本专题要介绍的Web浏览器,本专题通过简单自定义一个Web浏览器来简单介绍浏览器的工作原理,以及帮助一些初学者揭开浏览器这 ...
- 前端Web浏览器基于Flash如何实时播放监控视频画面(四)之使用videoJs‘拉流’
本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 0x001: 下载videoJs 对于Video.js 5.x及更低版本,Flash技术(v ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- java web 学习四(http协议)
一.什么是HTTP协议 HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的 ...
- JavaScript权威指南--WEB浏览器中的javascript
知识要点 1.客户端javascript window对象是所有客户端javascript特性和API的主要接入点.它表示web浏览器的一个窗口或窗体,并且可以用window表示来引用它.window ...
- 前端Web浏览器基于Flash如何实时播放监控视频画面(前言)之流程介绍
[关键字:前端浏览器如何播放RTSP流画面.前端浏览器如何播放RTMP流画面] 本片文章只是起到抛砖引玉的作用,能从头到尾走通就行,并不做深入研究.为了让文章通俗易懂,尽量使用白话描述. 考虑到视频延 ...
- Kendo UI for jQuery使用教程:支持Web浏览器
[Kendo UI for jQuery最新试用版下载] Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support ...
随机推荐
- 艾莫尔研究院基于Karmada的落地实践
摘要:本文从企业的业务背景.应用需求以及选择Karmada前后的对比和收益等方面,阐述了艾莫尔使用多集群技术完成企业技术升级的过程. 本文分享自华为云社区<艾莫尔研究院基于Karmada的落地实 ...
- Kubernetes(K8S) 镜像拉取策略 imagePullPolicy
镜像仓库,镜像已更新,版本没更新, K8S 拉取后,还是早的服务,原因:imagePullPolicy 镜像拉取策略 默认为本地有了就不拉取,需要修改 [root@k8smaster ~]# kube ...
- Django增删改查
增删改查.配置对应路由,函数,视图.报错注意看控制台. 添加取到前台传来的参数,后端给予验证.入库 编辑,取到当前编辑得id,在后台查到对应数据.重新update 删除,取到当前点击ID,后台dele ...
- 敏捷编辑器Sublime text 4中文配置Python3开发运行代码环境
敏捷编辑器Sublime text 4中文配置Python3开发运行代码环境 首先来到Win11环境下,进入Sublime text 4官网的下载页面:https://www.sublimetext. ...
- 机器学习周刊 第4期:动手实战人工智能、计算机科学热门论文、免费的基于ChatGPT API的安卓端语音助手、每日数学、检索增强 (RAG) 生成技术综述
LLM开发者必读论文:检索增强(RAG)生成技术综述! 目录: 1.动手实战人工智能 Hands-on Al 2.huggingface的NLP.深度强化学习.语音课 3.Awesome Jupyte ...
- 自媒体时代的贤内助——AI 视频云
视频,通常是一段由活动画面组成的传递信息的内容.在如今这个信息爆炸的时代,我们每天都要在浩瀚的内容海洋中寻找需求的信息.一个视频是否吸引人内容固然是最重要的,但是播放是否流畅,画质是否清晰的影响力也不 ...
- Step by step guide to becoming a C++ developer in 2023
https://roadmap.sh/cpp https://roadmap.sh/backend
- JSP | 常见 JSP 简答题
一.简述 JSP 的工作原理 当我们访问一个JSP页面的时候,这个文件首先会被JSP引擎翻译为一个Java源文件,其实就是一个Servlet,并进行编译,然后像其他Servlet一样,由Servlet ...
- 「Codeforces 1131D」Gourmet Choice
Description 美食家 Apple 先生是一家美食杂志的主编.他会用一个正整数来评价每一道菜. 美食家在第一天品尝第 $n$ 道菜,第二天品尝了 $m$ 道菜.他制作了一张 $n\times ...
- Tomcat 优雅关闭之路
本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/ZqkmoAR4JEYr0x0Suoq7QQ作者:马运杰 本文通过阅读Tomcat启动和关闭流程 ...