美文网首页
输入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