浏览器底层渲染机制

浏览器底层渲染机制

进程:一个程序,浏览器打开一个页面就开辟一个进程

线程:程序中具体“干活”的人,浏览器具备很多线程,这样就可以同时做很多事情

    一个进程中包含一到多个线程

      + 每一个线程同时只能做一件事,这件事情处理完成,才能处理下一件事情 => “同步编程”:单线程,同时只能处理一件事情,上一件事情处理完,才能处理下一件事情!!

      + “异步编程”:多线程,同时可以处理多件事情

    浏览器具备的线程:

      + GUI渲染线程:自上而下渲染页面的「含:HTML、CSS、IMG...」

      + JS引擎线程:渲染和解析JS代码

      + HTTP网络请求线程:从服务器端获取内容「最多同时可以开辟5~7个」

      + 定时器监听线程:监听定时器是否到达时间

      + 事件监听线程:监听事件是否触发

      + ...

 ============

    当我们从服务器获取HTML代码之后,浏览器需要按照代码规则,绘制出对应的页面

      @1 创建“DOM TREE”

       GUI渲染线程会自上而下,一行行的渲染解析页面中的代码;当渲染到底部的时候,浏览器已经规划出:当前页面的结构和层级嵌套关系(节点和节点之间的关系) -> 这就是DOM树

      @2 创建“CSSOM TREE”

       在DOM TREE生成后,浏览器把(从服务器获取的)样式代码进行渲染,生成CSSOM树!

       在GUI渲染过程中,我们会遇到<link>、<style>、@import、<img>、<script>...等标签,遇到不同的标签有不同的处理方案!!

      @3 把“DOM TREE”和“CSSOM TREE”合并在一起,生成“RENDER TREE”

      @4 Layout布局:根据视口大小,计算出每一个节点在视口中的具体位置及大小等

      @5 分层:规划出对应的层级,以及节点该在哪一个层级上「脱离文档流」

      @6 Painting绘制:按照所有解析出来的规则,一层层的开始绘制

    页面第一次渲染完成后,我们后期基于某些操作,修改了某个节点在视口中(自己所在层级中)的位置或者大小,这样浏览器需要重新计算当前视口(当前层级中)所有节点的布局位置「也就是把Layout操作重新搞了一遍」,然后重新进行Painting绘制,我们把这个操作称之为 “回流(Reflow)或重排”! 回流非常消耗页面性能,我们常说的操作DOM消耗性能,指的就是这件事!!

       哪些操作引发回流

       + 改变节点的位置

       + 改变节点的大小

       + 新增或者移除节点

       + 视口大小改变

       + 内容改变引发了节点的大小改变

       + ...

       而且回流一定会引发重绘,而且页面第一次渲染,本身就会有一次Layout和Painting

    某些对于DOM的操作(例如:改变文字颜色、背景、visibility「修改display可能会引发回流、但是设置visibility原始位置不动,则不会触发回流」...),并不会对节点的位置产生影响,此时只需要“重绘(Repaint)”即可!!

 @1 创建“DOM TREE”+@2 创建“CSSOM TREE” ↓

  ============加快页面第一次渲染,减少白屏等待时间

    关于样式:

      遇到<style>(内嵌式):无需去服务器获取样式代码了,但是也不会立即渲染,也是要等到DOM TREE生成完,外链式获取的样式代码也都拿到了,然后按照编写的先后顺序,依次渲染解析样式代码,以此保证CSS优先级正确!!

      遇到<link>(外链式):单独开辟一个新的HTTP线程去服务器获取样式代码,而GUI渲染线程会继续向下渲染「异步操作」;也就是CSS样式代码的渲染,一般都发生在DOM TREE生成之后!!

      遇到@import(导入式):也会开辟一个HTTP线程从服务器获取样式代码,只不过它会阻碍GUI的渲染;也就是,样式代码没有请求回来之前,GUI暂定渲染!!「同步编程」

      ------优化方案

      @1 样式“代码较少”的情况下,我们直接基于内嵌式<style>放在HTML页面中即可,没必要从服务器获取,这样可以在DOM TREE生成后,立即渲染样式,生成CSSOM TREE,加快页面渲染的速度!! 「移动端经典优化方案」

      @2 样式代码较多,我们基于外链式<link>;

         + 我们最好把CSS都写入到一个样式表中,只请求一次即可「减少HTTP请求次数」

         + 把<link>放在HEAD中,这样保证样式资源的提前获取,当DOM TREE生成后,可能样式代码已经回来了!

      @3 非必要情况,不用@import,因为他会阻碍GUI的渲染

    遇到<img>:

      + 开辟一个新的HTTP线程去请求图片,GUI继续向下渲染「异步编程」

      + 当获取到图片资源后,浏览器首先进行编码,然后按照编码进行渲染绘制!!

      -----

      @1 虽然请求图片资源不会阻碍GUI渲染,但每一次请求都占用了一个HTTP线程,而浏览器可同时开辟的HTTP有数量限制,所以最开始就加载真实图片,可能会导致其它类型的资源获取延后...所以我们需要做图片的“懒加载”

      @2 “BASE64”:如果想加快图片的渲染,我们可以跳过 获取资源&编码 这两步,直接让浏览器绘制即可

         + 如果图片较大,生成的BASE64码会超级多,这样增加了CSS文件的体积,而且代码维护起来会很麻烦,所以不要滥用BASE64;

         + 小图片可以BASE64;大图只有在各种解决办法都试过之后,发现还是达不到自己的要求,此时尝试用BASE64,发现图片渲染速度会明显提高!! {后期基于webpack可以自动打包时候BASE64}

    遇到<script src='xxx.js'>:

      + 开辟新的HTTP线程去获取JS代码,同时阻碍了GUI的渲染「同步编程」

      -----

      @1 把<script>放在页面底部

      @2 把<script>获取资源改为异步编程「不让其阻碍GUI渲染」

         + <script async>:GUI渲染中,遇到<script async>,开辟HTTP线程去获取JS代码;获取的过程中,GUI继续向下渲染,但是获取到了之后,立即暂停GUI,先把获取的JS先执行,执行完GUI继续!!

         + <script defer>:和<link>很相似,遇到<script defer>,开辟HTTP线程,异步去获取JS代码,GUI继续渲染;哪怕当JS代码拿回来后,也要等GUI渲染完,而且所有设置defer的JS都获取完,按照编写的先后顺序,依次渲染解析JS!!

         + <script>:GUI渲染中,遇到<script>,则暂停渲染;然后获取JS代码,获取后把JS渲染解析;都完成后,GUI继续渲染!!

         ----

         如果没有JS之间的相互依赖,完全可以说先回来执行谁,使用async即可;但凡需要根据导入的先后顺序去执行才可以,则一定要用defer;

      @3 和CSS一样,最好所有的JS都合并带一个文件中,减少HTTP请求次数

 onload和DOMContentLoaded的区别

 // window.onload : 页面中所有资源都加载完成「含DOM TREE」
window.onload = function () {
    console.log(document.querySelector('.box'));
};
// DOMContentLoaded :只要DOM TREE生成就可以触发
window.addEventListener('DOMContentLoaded', function () {
    console.log(document.querySelector('.box'));
}); 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值