乐趣区

关于前端:⭐⭐浏览器原理-之-页面形成的原理和性能优化篇

本来地址

掘金

github

大家好,我是林一一,这是一篇对于浏览器是如何渲染一个页面造成的原理,话不多说,间接开始浏览吧👍

001 浏览器的底层渲染页面篇

浏览器中的 5 个过程

浏览器在获取服务器的资源后将 html 解析成 DOM 树,CSS 计算成 CSSOM 树,将两者合成 render tree。具体如下浏览器依据 render tree 布局生成一个页面。须要了解的是浏览器从服务器获取回来的资源是一个个的字节码 3C 6F 6E 62 .... 等,浏览器会依照一套标准 W3C 将字节码最初解析一个个的代码字符串才成为咱们看到的代码

浏览器加载资源的机制

  • 浏览器会开拓一个 GUI 渲染线程,自上而下执行代码,专门用于渲染渲染页面的线程。

遇到 CSS 资源

  • 遇到 <style> 内联标签会交给 GUI 渲染线程解析,然而遇到 <link> 标签会异步解决,浏览器会开拓一个 HTTP 申请解决的线程,GUI 渲染线程持续往下执行
  • 如果遇到@import 时,也会开拓一个新的 HTTP 申请线程解决,因为 @import 是同步的 GUI 渲染线程会阻塞期待申请的后果。

    须要留神 chrome 中,同一个源下,最多同时开拓 6-7 和 HTTP 申请线程。

遇到 JS 资源

最底部的线示意 GUI 线程的过程,渲染线程遇到不同状况下的 script 资源,有不同的解决。

  • 遇到 <script></script> 资源,默认是同步的。此时 GUI 渲染线程会阻塞。期待 JS 渲染线程渲染完结后,GUI 线程才会持续渲染。
  • 如果遇到 <script async></script> 那么资源是异步的 async,浏览器也会开拓一个 HTTP 申请线程加载资源,这时 GUI 渲染线程会持续向下渲染,申请的资源回来后 JS 渲染线程开始执行,GUI 线程再次被阻塞。
  • 如果遇到 <script defer></script> 和 async 相似都会开拓一个新的 HTTP 线程,GUI 持续渲染。和 async 不一样的中央在于,defer 申请回来的资源须要期待 GUI 同步的代码执行完结后才执行 defer 申请回来的代码。

    async 不存在资源的依赖关系先申请回来的先执行。defer 须要期待所有的资源申请回来当前,依照导入的程序 / 依赖关系顺次执行。

图片或音频

  • 遇到 <img/> 异步,也会开拓一个新的 HTTP 线程申请资源。GUI 持续渲染,当 GUI 渲染完结后,才会解决申请的资源。

须要留神的是:假如某些资源加载很慢,浏览器会疏忽这些资源接着渲染前面的代码,在 chrome 浏览器中会先应用预加载器 html-repload-scanner 先扫描节点中的 src,link 等先进行预加载,防止了资源加载的工夫

浏览解析资源的机制

  • 浏览器是怎么解析加载回来的资源文件的?页面自上而下渲染时会确定一个 DOM 树CSSOM 树,最初 DOM 树CSSOM 树 会被合并成 render 树,这些所谓的树其实都是 js 对象,用 js 对象来示意节点,款式,节点和款式之间的关系。

DOM 树

所谓的 DOM 树是确定好节点之间的父子、兄弟关系。这是 GUI 渲染线程自上而下渲染完结后生成的,等到 CSS 资源申请回来当前会生成 CSSOM 款式树。

CSSOM 树

CSSOM(CSS Object Model),CSS 资源加载回来当前会被 GUI 渲染成 款式树

Render tree 渲染树

浏览器依据 Render tree 渲染页面须要经验上面几个步骤。留神 display:node 的节点不会被渲染到 render tree 中

  • layout 布局,依据渲染树 计算出节点在设施中的地位和大小
  • 分层解决。依照层级定位分层解决
  • painting 绘制页面

下面的图形就是浏览器分成解决后的显示成果

002 浏览器的性能优化篇

前端浏览器的性能优化,能够从 CRP: 要害渲染门路动手

DOM Tree

  • 缩小 DOM 的层级嵌套
  • 不要应用被规范标签

CSSOM

  • 尽量不要应用 @import,会妨碍 GUI 渲染线程。
  • CSS 代码量少能够应用内嵌式的 style 标签,缩小申请。
  • 缩小应用link,能够缩小 HTTP 的申请数量。
  • CSS 选择器链尽可能短,因为 CSS 选择器的渲染时从右到左的。
  • 将写入的 link 申请放入到<head></head> 外部,一开始就能够申请资源,GUI 同时渲染。

其余资源

  • <script></script> 中的同步 js 资源尽可能的放入到页面的开端,避免妨碍 GUI 的渲染。如果遇到 <script async/defer></script> 的异步资源,GUI 渲染不会中断,然而 JS 资源申请回来当前会中断 GUI 的渲染。
  • <img /> 资源应用懒加载,懒加载:第一次加载页面时不要加载图片,因为图片也会占据 HTTP 的数量。还能够应用图片 base64,代表图片。

003 回流和重绘篇

layout 阶段就是页面的回流期,painting 就是重绘阶段。第一次加载页面时必有一次回流和重绘。

  • 浏览器渲染页面的流程

    浏览器会先把 HTML 解析成 DOM 树 计算 DOM 构造;而后加载 CSS 解析成 CSSOM;最初将 DOM 和 CSSOM 合并生成渲染树 Render Tree,浏览器依据页面计算 layout(重排阶段);最初浏览器依照 render tree 绘制(painting,重绘阶段) 页面。

重排(DOM 回流)

重排是指 render tree 某些 DOM 大小和地位产生了变动 (页面的布局和几何信息产生了变动),浏览器从新渲染 DOM 的这个过程就是 重排(DOM 回流),重排会耗费页面很大的性能,这也是虚构 DOM 被引入的起因。

产生重排的状况

  • 第一次页面计算 layout 的阶段
  • 增加或删除 DOM 节点,扭转了 render tree
  • 元素的地位,元素的字体大小等也会导致 DOM 的回流
  • 节点的几何属性扭转,比方 width, height, border, padding,margin 等 被扭转
  • 查找盒子属性的 offsetWidth、offsetHeight、client、scroll等,浏览器为了失去这些属性会重排操作。
  • 框架中 v-if 操作也会导致回流的产生。
  • 等等

一道小题,问上面的代码浏览器重排了几次(chrome 新版浏览器为主)?

box.style.width = "100px";
box.style.width = "100px";
box.style.position = "relative";

你可能会感觉是 3 次,然而在当代浏览器中,浏览器会为下面的款式代码开拓一个渲染队列,将所有的渲染代码放入到队列外面,最初一次更新,所以重排的次数是 1 次。问上面的代码会导致几次重排

box.style.width = "100px";
box.style.width = "100px";
box.offsetWidth;
box.style.position = "relative";

答案是 2 次,因为 offsetWidth 会导致渲染队列的刷新,才能够获取精确的 offsetWidth 值。最初 position 导致元素的位子产生扭转也会触发一次回流。所以总共有 2 次。

重绘

重绘是指 页面的款式产生了扭转然而 DOM 构造 / 布局没有产生扭转。比方色彩产生了变动,浏览器就会对须要的色彩进行从新绘制。

产生重绘的状况

  • 第一次页面 painting 绘制的阶段
  • 元素色彩的 color 产生扭转

间接合成

如果咱们更改了一个不影响布局和绘制的属性,浏览器的渲染引擎会跳过重排和重绘的阶段,间接合成

  • 比方咱们应用了 CSS 的 transform 属性,浏览器的能够师姐合成动画成果。

重排肯定会引发重绘,然而重绘不肯定会导致重排

重排 (DOM 回流)和重绘吗?说一下区别

思路:先讲述浏览器的渲染机制 -> 重排和重绘的概念 -> 怎么缩小重排和重绘。。。

区别

重排会导致 DOM 构造 产生扭转,浏览器须要从新渲染布局生成页面,然而重绘不会引发 DOM 的扭转只是款式上的扭转,前者的会耗费很大的性能。

如何缩小重排和重绘

    1. 防止应用 table 布局,因为 table 布局计算的工夫比拟长耗性能;
    1. 款式集中扭转,防止频繁应用 style,而是采纳批改 class 的形式。
    1. 防止频繁操作 DOM,应用 vue/react。
    1. 款式的拆散读写。设置款式 style 和读取款式的 offset 等分来到,也能够缩小回流次数。
    1. 将动画成果设计在文档流之上即 position 属性的 absolutefixed 上。应用 GPU 减速合成。

参考

《浏览器工作原理与实际》

Render Tree 页面渲染

完结

感激浏览到这里,如果这篇文章能对你有点启发或帮忙欢送给👍👍,我是林一一,下次见。

浏览器原理篇:本地存储和浏览器缓存

Vue 原理篇:Vue 高频原理具体解答

webpack 原理篇:编写 loader 和 plugin

掘金 合集

github 合集

退出移动版