美文网首页
输入url 到页面渲染完成(四处抄)

输入url 到页面渲染完成(四处抄)

作者: 白日梦想家x | 来源:发表于2017-08-10 01:18 被阅读0次

开始上网,输入 url

当我们开始输入 url 的时候,浏览器就已经开始匹配 url ,从历史纪录,书签等,找到已经输入的字符串可能对应的 url ,然后给出智能提示,自动补全等。


服务器返回 HTTP 请求

响应类似请求:

  • 状态行
  • 响应头
  • 响应体

这五步中,三四步比较慢生成布局和绘制合成渲染


当文档加载过程中遇到js文件,html文档会挂起渲染(加载解析渲染同步)的线程,不仅要等待文档中js文件加载完毕,还要等待解析执行完毕,才可以恢复html文档的渲染线程。因为JS有可能会修改DOM,最为经典的document.write,这意味着,在JS执行完成前,后续所有资源的下载可能是没有必要的,这是js阻塞后续资源下载的根本原因。所以我明平时的代码中,js是放在html文档末尾的。

DOM 树


DOM 树中的每一个需要显示的节点再渲染树中至少存在一个对应的节点,隐藏的 DOM 元素则没有对应节点,渲染树中的节点被称为 “帧(frames)”或“盒(boxes)”,
符合 CSS 模型的定义,一旦DOM 树和渲染树构建完成,浏览器就开始显示绘制元素

很多时候,密集的重新渲染是无法避免的,比如scroll事件的回调函数和网页动画。
网页动画的每一帧(frame)都是一次重新渲染。每秒低于24帧的动画,人眼就能感受到停顿。一般的网页动画,需要达到每秒30帧到60帧的频率,才能比较流畅。如果能达到每秒70帧甚至80帧,就会极其流畅。

大多数显示器的刷新频率是60Hz,为了与系统一致,以及节省电力,浏览器会自动按照这个频率,刷新动画(如果可以做到的话)。
所以,如果网页动画能够做到每秒60帧,就会跟显示器同步刷新,达到最佳的视觉效果。这意味着,一秒之内进行60次重新渲染,每次重新渲染的时间不能超过16.66毫秒。

一秒之间能够完成多少次重新渲染,这个指标就被称为"刷新率",英文为FPS(frame per second)。60次重新渲染,就是60FPS。
如果想达到60帧的刷新率,就意味着JavaScript线程每个任务的耗时,必须少于16毫秒。一个解决办法是使用Web Worker,主线程只用于UI渲染,然后跟UI渲染不相干的任务,都放在Worker线程。

DOM 解析

<html>
<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>

DOM 解析成这样


CSS 解析

假设有下面这样的 DOM 结构

<doc>
<title>A few quotes</title>
<para>
  Franklin said that <quote>"A penny saved is a penny earned."</quote>
</para>
<para>
  FDR said <quote>"We have nothing to fear but <span>fear itself.</span>"</quote>
</para>
</doc>

CSS 文档

 /* rule 1 */ doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; }
/* rule 3 */ para { display: block; }
/* rule 4 */ [class="emph"] { font-style: italic; }

CSS Rule tree 时这样


  • 图中的第4条规则出现了两次,一次是独立的,一次是在规则3的子结点。所以,我们可以知道,建立CSS Rule Tree是需要比照着DOM Tree来的。CSS匹配DOM Tree主要是从右到左解析CSS的Selector,好多人以为这个事会比较快,其实并不一定。关键还看我们的CSS的Selector怎么写了。
  • CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,你就会在N多地方看到很多人都告诉你,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去

通过这俩个树我们可以得到一个叫 Style Context Tree


所以,Firefox基本上来说是通过CSS 解析 生成 CSS Rule Tree,然后,通过比对DOM生成Style Context Tree,然后Firefox通过把Style Context Tree和其Render Tree(Frame Tree)关联上,就完成了。注意:Render Tree会把一些不可见的结点去除掉。而Firefox中所谓的Frame就是一个DOM结点,不要被其名字所迷惑了。


在 Firefox 中,系统会针对 DOM 更新注册展示层,作为侦听器。展示层将框架创建工作委托给FrameConstructor,由该构造器解析样式(请参阅样式计算)并创建框架。
在 WebKit 中,解析样式和创建呈现器的过程称为“附加”。每个 DOM 节点都有一个“attach”方法。附加是同步进行的,将节点插入 DOM 树需要调用新的节点“attach”方法

渲染

  1. 计算 CSS 样式
  2. 构建 render tree
  3. Layout
  4. 开始绘制

上图流程中有很多连接线,这表示了Javascript动态修改了DOM属性或是CSS属会导致重新Layout,有些改变不会,就是那些指到天上的箭头,比如,修改后的CSS rule没有被匹配到,等。

Repaint

屏幕的一部分要重画,比如某个元素的 CSS 背景变了,但尺寸没有变

Reflow

当 DOM 的变化影响了元素的几何属性 => 比如改变边框宽度或者给段落增加文字,导致行数增加 => 浏览器需要重新计算元素的几何属性,同样其他元素的几何属性和位置也会收到影响,浏览器会使渲染树中受到影响部分失效,并重新构造渲染树,发生重排,完成重排后,浏览器会重新绘制受影响部分的元素到屏幕中,也会发生重绘。

  • 样式表越简单,重排和重绘就越快。
  • 重排和重绘的DOM元素层级越高,成本就越高。
  • table元素的重排和重绘成本,要高于div元素

发生重绘

  • 当你增加、删除、修改DOM结点时,会导致Reflow或Repaint
  • 当你移动DOM的位置,或是搞个动画的时候。(元素位置发生改变)
  • 当你修改CSS样式的时候。或者页面渲染初始化
  • 当你Resize窗口的时候(移动端没有这个问题),或是滚动的时候。
  • 当你修改网页的默认字体时。
  • 元素尺寸发生改变(边距, 高度等)
  • 注:display:none会触发reflow,而visibility:hidden只会触发repaint,因为没有发现位置变化。

渲染树的变化的排队与刷新

由于每次重排都行会产生消耗,大多数浏览器通过队列化修改并批量执行来优化重排过程,然而,你可能会不知不觉的强制刷新对了要求计划立刻执行,获取布局的信息会导致队列刷新

  • offsetTop, offsetBottom, offsetWidth, offsetHeight
  • scrollTop, scrollBottom, scrollWidth, scrollHeight
  • clientTop, clientBottom, clientWidth, clientHeight
  • getComputedStyle() =>( currentStyle in IE)
    以上属性和方法需要返回最新的布局信息,因此浏览器不得不执行渲染队列中的‘待处理变化’并触发重排以返回正确的值。

"重绘"不一定需要"重排" ---- "重排"必然导致"重绘"

最小化重绘和重排

  • 改变样式 => 不要一条条地改变样式,多个改变合并 => 直接更换 CSS 的 Class
  • 批量修改 DOM => 使元素脱离文档流(隐藏显示,使用文档片段,拷贝到一个脱离文档的节点中完成后再替换) => 修改 => 带回文档
  • 动画使用绝对定位,使用拖放代理
  • 缓存布局信息 => 偏移量,滚动位置, 计算出的样式等 获取一次后赋值给局部遍历
  • 事件委托 => 减少事件处理器的数量

浏览器请求嵌在 HTML 中的资源(图片,视频音频, CSS, JavaScript 等)

其实这个步骤可以并列在步骤8中,在浏览器显示HTML时,它会注意到需要获取其他地址内容的标签。这时,浏览器会发送一个获取请求来重新获得这些文件。比如我要获取外图片,CSS,JS文件等,类似于下面的链接:

图片:http://or3233yyd.bkt.clouddn.com//17-8-9/67016800.jpg

CSS式样表:https://cdn.bootcss.com/animate.css/3.5.2/animate.css

JavaScript 文件:https://cdn.bootcss.com/jquery/3.2.1/core.js

这些地址都要经历一个和HTML读取类似的过程。所以浏览器会在DNS中查找这些域名,发送请求,重定向等等...

不像动态页面,静态文件会允许浏览器对其进行缓存。有的文件可能会不需要与服务器通讯,而从缓存中直接读取,或者可以放到CDN中

转载整理:

相关文章

网友评论

      本文标题:输入url 到页面渲染完成(四处抄)

      本文链接:https://www.haomeiwen.com/subject/loecrxtx.html