阅读 309

浏览器渲染原理

进程: 开的每一个程序(饭店)

线程: 程序中要做还多事情 这些事情就是线程(干活的服务员),但浏览器是多线程的,浏览器分一个线程给js,所以js是单线程

栈内存: 提供一个环境供我们执行代码的

图例

大致流程

以图为例 1.客户端(浏览器)输入网址 ->像服务器发起request请求阶段->服务器找到请求的资源(index.html)

2.服务器端Response响应阶段(像客户端发送HTTP报文)

3.客户端接收到代码后: 浏览器在内存条中开辟出一块栈内存,用来给代码的执行提供环境;同时分配一个主线程去一行行的解析和执行代码;

4.处理代码,一行行的处理,进栈执行->执行完出栈 知道执行完最后一行代码,其中浏览器遇到link/script/img等请求后,都会开辟全新的线程去加载资源文件

5.第一次自上而下走完后,只生成DOM树

6.CSS处理完成生成CSSOM

7.最后生成Render Tree渲染树

DOM的重绘和回流Repaint & Reflow

重绘

元素样式的改变(但宽高、大小、位置等不变)

如outline,visibility,color,background-color等

回流

元素的大小或者位置发生了变化(当页面布局和几何信息发生变化的时候),触发了重新布局,导致渲染树重新计算布局和渲染

如添加或删除可见的DOM元素; 元素的位置发生变化;元素的尺寸发生变化;内容发生变化(比如文本变化或图片被另外一个不同尺寸的图片所替代);页面一开始渲染的时候(这个无法避免);因为回流是根据视口的大小来计算元素的位置和大小的,所以浏览器的窗口尺寸变化也会引发回流

注意:回流一定会触发重绘,而重绘不一定会回流

前端性能优化之:避免DOM的回流

1.放弃传统操作dom的时代,基于vue/react开始数据影响视图模式 mvvm/mvc/virtual dom/ dom diff...... 2.分离读写操作(现代的浏览器都有渲染队列的机制,同时处理的样式问题会统一处理触发一次回流) offsetTop

// 这种同时处理就只会触发一次回流
 <script>
    let box = document.getElementById('box');
    box.style.width = '200px';
    box.style.height = '200px';
    box.style.margin = '10px';
  </script>
  // 但是这种就会触发两次回流,因为中加了个获取元素会中断下面的样式改变,
  // 在处理完获取,才会继续执行下面的,再触发一次回流
  <script>
    let box = document.getElementById('box');
    box.style.width = '200px';
    console.log(box.clientWidth);
    box.style.height = '200px';
    box.style.margin = '10px';
  </script>
  // 这样的写法是分离读写, 读取和写入分开写不要进行穿插
   <script>
    let box = document.getElementById('box');
    box.style.width = '200px';
    box.style.height = '200px';
    box.style.margin = '10px';
    console.log(box.clientWidth);
  </script>
复制代码

3.批量处理

// 批量处理
    box.style.cssText = 'width: 200px;height: 200px';
    box.className = 'aa';
复制代码

4.缓存处理

let a = box.clientWidth;
let b = box.clientHidth;
box.style.width = a + 10 +'px';
box.style.hidth = b + 10 +'px';
复制代码

5.元素批量修改 文档碎片: createDocumentFragment 模板字符串拼接

<body>
  <ul id="box"></ul>
  <script>
    let box = document.getElementById('box');
   let frg = document.createDocumentFragment(); // 文档碎片
    for(let i=0;i<5;i++){
      let newLi = document.createElement('li');
      newLi.innerHTML = i;
      // 创建的li放到文档碎片中
      frg.appendChild(newLi);
    }
    // 一次性把内容放到容器中: 引发一次回流
    box.appendChild(frg);
    frg = null;
    // 或者用ES6语法写
    let str = ``;
    for(let i=0;i<5;i++){
      str+=`<li>${i}</li>`
    }
    box.innerHTML = str;
    </script>
</body>
复制代码

6.动画效果应用到position属性为absolute或fixed的元素上(脱离文档流)

7.css3硬件加速(GPU加速)

比起考虑如何减少回流重绘,我们更期望的是,根本不要回流重绘;transform\opacity\filters... 这些属性会触发硬件加速,不会引发回流和重绘 可能会引发的坑: 过多使用会占用大量内存,性能消耗严重,有时候会导致字体模糊

 box.style.transform = 'translateX(100px)'
复制代码

8.牺牲平滑度换取速度

每次1像素移动一个动画,但是如果此动画使用了100%的CPU,动画就会看上去是跳动的,因为浏览器正在与更新回流做斗争.每次移动3像素可能看起来平滑度低了,但它不会导致CPU在较慢的机器中抖动

9.避免table布局和使用css的JavaScript表达式

性能优化:

1.减少HTTP的请求次数和大小

  1. 图片懒加载

3.音视频走流文件

...

需要了解的网络请求:

Request请求阶段:DNS解析、TCP协议的三次握手和四次挥手、HTTPS和HTTP的区别

Response响应阶段:HTTP状态码、304缓存、HTTP报文

DNS解析

在浏览器中输入一个网址(域名)(给人看的) ->借助DNS服务查找域名对应的IP(DNS解析)(机器只能识别IP地址) DNS解析图片示例

浏览器渲染的详细总结流程

在浏览器中输入一个网址(域名)(给人看的) ->借助DNS服务查找域名对应的IP(DNS解析)-> 向服务器发送一个请求通过路由器判断你发送的数据包到达正确的服务器(请求)->请求成功服务器向浏览器返回一个包->浏览器接收后正式发送"我要什么东西"这件事->服务器接收之后拆解请求,查找你要的是"什么东西(index.html图片视频等)" 然后返回给浏览器(响应)->浏览器解析服务端响应信息呈现出看到的页面信息

浏览器渲染的简单总结流程

域名解析 => 连接服务器 => 请求响应 => 解析渲染

https介绍

什么是认证中心,证书如何签字?

参考地址:B站智能社DNS解析

参考地址:B站HTTPS

文章分类
前端
文章标签