浏览器基础结构主要包括如下7部分,参考:
- 用户界面(User Interface):用户所看到及与之交互的功能组件,如地址栏,返回,前进按钮等;
- 浏览器引擎(Browser engine):负责控制和管理下一级的渲染引擎;
- 渲染引擎(Rendering engine):负责解析用户请求的内容(如HTML或XML,渲染引擎会解析HTML或XML,以及相关CSS,然后返回解析后的内容);
- 网络(Networking):负责处理网络相关的事务,如HTTP请求等;
- UI后端(UI backend):负责绘制提示框等浏览器组件,其底层使用的是操作系统的用户接口;
- JavaScript解释器(JavaScript interpreter):负责解析和执行JavaScript代码;
- 数据存储(Data storage):负责持久存储诸如cookie和缓存等应用数据。
- 浏览器下载的顺序是从上到下,渲染的顺序也是从上到下,下载和渲染是同时进行的。
- 在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(并不是说所有相关联的元素都已经下载完)。
- 如果遇到语义解释性的标签嵌入文件(JS脚本,CSS样式),那么此时IE的下载过程会启用单独连接进行下载。
- 并且在下载后进行解析,解析过程中,停止页面所有往下元素的下载。
- 样式表在下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素(含以前已经渲染的)重新进行渲染。
- JS、CSS中如有重定义,后定义函数将覆盖前定义函数。
css选择器渲染的机制
浏览器CSS匹配不是从左到右进行查找,而是从右到左进行查找。比如之前说的DIV#divBox p span.red{color:red;},浏览器 的查找顺序如下:先查找html中所有class=’red’的span元素,找到后,再查找其父辈元素中是否有p元素,再判断p的父元素中是否有id为 divBox的div元素,如果都存在则CSS匹配上。
浏览器从右到左进行查找的好处是为了尽早过滤掉一些无关的样式规则和元素。firefox称这种查 找方式为keyselector(关键字查询),所谓的关键字就是样式规则中最后(最右边)的规则,上面的key就是span.red。
Using Feature Detection, Conditionals, and Groups with Selectors
Why Browsers Download Stylesheets With Non-Matching Media Queries
The Simplest Way to Load CSS Asynchronously
script integrity属性,hash防止修改
JS触发重绘和重流优化:
- 读取DOM或者写入DOM,尽量写在一起,不要混杂
- 缓存DOM信息
- 不要一项一项地改变样式,而是使用CSS class一次性改变样式
- 使用document fragment操作DOM
- 动画时使用absolute定位或fixed定位,这样可以减少对其他元素的影响
- 只在必要时才显示元素
- 使用window.requestAnimationFrame(),因为它可以把代码推迟到下一次重流时执行,而不是立即要求页面重流
- 使用虚拟DOM(virtual DOM)库
动态嵌入脚本,及保护执行顺序
The cost of JavaScript in 2019
通过网络模块加载到HTML文件后渲染引擎渲染流程如下,这也通常被称作关键渲染路径(Critical Rendering Path):
- 构建DOM树(DOM tree):从上到下解析HTML文档生成DOM节点树(DOM tree),也叫内容树(content tree);
- 构建CSSOM(CSS Object Model)树:加载解析样式生成CSSOM树;
- 执行JavaScript:加载并执行JavaScript代码(包括内联代码或外联JavaScript文件);
- 构建渲染树(render tree):根据DOM树和CSSOM树,生成渲染树(render tree);渲染树:按顺序展示在屏幕上的一系列矩形,这些矩形带有字体,颜色和尺寸等视觉属性。
- 布局(layout):根据渲染树将节点树的每一个节点布局在屏幕上的正确位置;
- 绘制(painting):遍历渲染树绘制所有节点,为每一个节点适用对应的样式,这一过程是通过UI后端模块完成;
回流:可通过JS中断等方法,强制缓存回流。
Are long JavaScript tasks delaying your Time to Interactive?
-
涉及多域名的网站,可以开启域名预解析。
用meta信息来告知浏览器, 当前页面要做DNS预解析:<meta http-equiv="x-dns-prefetch-control" content="on" />
在页面header中使用link标签来强制对DNS预解析:<link rel="dns-prefetch" href="http" />
link rel="preload" rel="prefetch"
Preload, prefetch and other <link> tags
-
使用HTTP缓存:添加 Expires 或 Cache-Control / Pragma 信息头,Last-Modified最后修改时间,ETag控制hash。
-
使用客户端反馈资源调整
-
HTML文档结构层次尽量少,最好不深于六层;
-
脚本尽量后放,放在</body>前即可;
-
少量首屏样式内联放在<head>标签内;
-
样式结构层次尽量简单;
-
在脚本中尽量减少DOM操作,尽量缓存访问DOM的样式信息,避免过度触发回流;
-
减少通过JavaScript代码修改元素样式,尽量使用修改class名方式操作样式或动画;
-
动画尽量使用在绝对定位或固定定位的元素上;
-
隐藏在屏幕外,或在页面滚动时,尽量停止动画;
-
尽量缓存DOM查找,查找器尽量简洁;
-
响应式渲染;
Experimenting with the Streams API
- setTimeout分段渲染,减少主进程堵塞
- 数据缓存,页面按需渲染(scroll等)
- 优化循环,将同步循环用setTimeout拆解成异步继发
- 优化函数,用setTimeout拆成异步
- 优化递归操作,找出重复计算的部分优化,用迭代互补,尾调优化
- 利用缓存
Understanding Memoization in JavaScript to Improve Performance
Accurately measuring layout on the web