前端性能优化-浏览器运行机制

解锁浏览器背后的运行机制

浏览器的"心"

之所以不同的浏览器下代码渲染结果有差异 正是因为浏览器的内核不一致导致的 , 浏览器的内核决定了浏览器解释网页语法的方式.

浏览器内核可以分为两部分 渲染引擎 和 js引擎

渲染引擎包含了 HTML解释器 , css 解释器 , 布局 , 网络 , 存储 , 图形 , 音视频 , 图片解码器等零件

开启浏览器渲染"黑盒"

Q : 什么是渲染过程 ? A : 简单的说 渲染引擎根据 html 文件描述 将资源转换为图像结果

其中比较重要的部分是

  • HTML 解释器 : 将 html 文档经过词法分析输出 DOM 树
  • CSS 解释器 : 解析 css 文档 , 生成样式规则
  • 图层布局计算模块 : 布局计算每个对象的精确位置和大小
  • 视图绘制模块 : 进行具体的图像绘制 , 将像素渲染到屏幕上
  • javascript 引擎 : 编译 执行 js 代码

浏览器渲染过程解析

  • 解析 HTML 在这一步浏览器执行了所有的加载解析逻辑,在解析 HTML 的过程中发出了页面渲染所需的各种外部资源请求。

  • 计算样式 浏览器将识别并加载所有的 CSS 样式信息与 DOM 树合并,最终生成页面 render 树(:after :before 这样的伪元素会在这个环节被构建到 DOM 树中)。

  • 计算图层布局 页面中所有元素的相对位置信息,大小等信息均在这一步得到计算。

  • 绘制图层 在这一步中浏览器会根据我们的 DOM 代码结果,把每一个页面图层转换为像素,并对所有的媒体文件进行解码。

  • 整合图层,得到页面 最后一步浏览器会合并合各个图层,将数据由 CPU 输出给 GPU 最终绘制在屏幕上。(复杂的视图层会给这个阶段的 GPU 计算带来一些压力,在实际应用中为了优化动画性能,我们有时会手动区分不同的图层)。

几棵重要的"树"

  • DOM 树: 解析 HTML 以创建的是 DOM 树(DOM tree ):渲染引擎开始解析 HTML 文档,转换树中的标签到 DOM 节点,它被称为"内容树"。

  • CSSOM 树: 解析 CSS(包括外部 CSS 文件和样式元素)创建的是 CSSOM 树。CSSOM 的解析过程与 DOM 的解析过程是并行的。

  • 渲染树: CSSOM 与 DOM 结合,之后我们得到的就是渲染树(Render tree )。

  • 布局渲染树: 从根节点递归调用,计算每一个元素的大小、位置等,给每个节点所应该出现在屏幕上的精确坐标,我们便得到了基于渲染树的布局渲染树(Layout of the render tree)。

  • 绘制渲染树: 遍历渲染树,每个节点将使用 UI 后端层来绘制。整个过程叫做绘制渲染树(Painting the render tree)。

渲染过程: 首先是基于 HTML 构建一个 DOM 树,这棵 DOM 树与 CSS 解释器解析出的 CSSOM 相结合,就有了布局渲染树。最后浏览器以布局渲染树为蓝本,去计算布局并绘制图像

之后每当一个新元素加入到这个 DOM 树当中,浏览器便会通过 CSS 引擎查遍 CSS 样式表,找到符合该元素的样式规则应用到这个元素上,然后再重新去绘制它。

css 优化建议

css 复制代码
#myList li {
  /*  */
}

CSS 选择符是从右到左进行匹配的。这个选择器实际开销相当高:浏览器必须遍历页面上每个 li 元素,并且每次都要去确认这个 li 元素的父元素 id 是不是 myList

通配符也是个消耗性能的选择器 , 因为他会遍历页面上的每一个元素

告别阻塞: css 与 js 的加载顺序优化

html css js 都具有阻塞渲染的特性

css 阻塞

因为 DOM Tree + CSSOM = Render Tree 所以只要 css 没加载完 就不会往后走渲染流程

由于 html 解析到 <link /> 和 <style />标签的时候 CSSOM 才开始构建 . 所以可以尽可能把构建时机提前.

比如 :

  • 放在 <head /> 里 (尽早)
  • 启用 CDN (尽快)

js 阻塞

js 的作用在于 修改节点 , 本质上都是对 DOM 和 CSSOM 进行修改 , 所以 JS 的执行会阻塞

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>JS阻塞测试</title>
    <style>
      #container {
        background-color: yellow;
        width: 100px;
        height: 100px;
      }
    </style>
    <script>
      // 尝试获取container元素
      var container = document.getElementById("container");
      console.log("container", container);
    </script>
  </head>
  <body>
    <div id="container"></div>
    <script>
      // 尝试获取container元素
      var container = document.getElementById("container");
      console.log("container", container);
      // 输出container元素此刻的背景色
      console.log(
        "container bgColor",
        getComputedStyle(container).backgroundColor
      );
    </script>
    <style>
      #container {
        background-color: blue;
      }
    </style>
  </body>
</html>

运行结果是

javscript 复制代码
container null
index.html:26 container <div id=​"container">​</div>​
index.html:28 container bgColor rgb(255, 255, 0)
index.html:63 Live reload enabled.

JS 是外部文件的时候 表现也是这样的

第一次获取 DOM 失败 说明 js 阻塞了 DOMTree 的生成 第二次获取 DOM 成功 (预期内) 但是获取 css 拿到的是 yellow 的颜色 而不是后续配置的 blue 证明 CSSOM 也被阻塞了

js 的加载方式

  • 正常模式

这种模式下会阻塞

javascript 复制代码
<script src="./index.js" />
  • async 模式

async 模式下,JS 不会阻塞浏览器做任何其它的事情。它的加载是异步的,当它加载结束,JS 脚本会立即执行。

javascript 复制代码
<script async src="./index.js" />
  • defer 模式

defer 模式下,JS 的加载是异步的,执行是被推迟的。等整个文档解析完成、DOMContentLoaded 事件即将被触发时,被标记了 defer 的 JS 文件才会开始依次执行。

javascript 复制代码
<script defer src="./index.js" />
相关推荐
续亮~1 小时前
6、Redis系统-数据结构-05-整数
java·前端·数据结构·redis·算法
顶顶年华正版软件官方2 小时前
剪辑抽帧技巧有哪些 剪辑抽帧怎么做视频 剪辑抽帧补帧怎么操作 剪辑抽帧有什么用 视频剪辑哪个软件好用在哪里学
前端·音视频·视频·会声会影·视频剪辑软件·视频剪辑教程·剪辑抽帧技巧
MarkHD3 小时前
javascript 常见设计模式
开发语言·javascript·设计模式
托尼沙滩裤3 小时前
【js面试题】js的数据结构
前端·javascript·数据结构
不熬夜的臭宝4 小时前
每天10个vue面试题(一)
前端·vue.js·面试
朝阳394 小时前
vue3【实战】来回拖拽放置图片
javascript·vue.js
不如喫茶去4 小时前
VUE自定义新增、复制、删除dom元素
前端·javascript·vue.js
长而不宰4 小时前
vue3+electron项目搭建,遇到的坑
前端·vue.js·electron
阿垚啊5 小时前
vue事件参数
前端·javascript·vue.js
加仑小铁5 小时前
【区分vue2和vue3下的element UI Dialog 对话框组件,分别详细介绍属性,事件,方法如何使用,并举例】
javascript·vue.js·ui