重学前端 => 浏览器渲染原理,过程

本文深入探讨浏览器如何解析HTML、CSS和JavaScript,并渲染成视图。解释了DOM树、CSSOM树和渲染树的生成过程,以及布局、绘制和栅格化的细节。

我认为作为前端工程师了解HTML,CSS,JS,浏览器的渲染以及运行原理。

就好比士兵打仗要用枪,那么士兵一定对自身的武器非常了解这样在武器发生故障的时候才可以精准的定位问题解决问题。

那么浏览器,三剑客就是前端工程师的武器🏹

所以本篇将会作为重学前端笔记的第一章!

我的疑问🤔:

  • 浏览器是如何将获取的网页数据转换成视图的?

  • 浏览器如何解析三剑客(html,js,css)并渲染,其先后顺序是?

  • 三剑客的进化趋势是?

浏览器渲染原理:

这之前可以先看一下B站UP主卢克儿的视频 【干货】浏览器是如何运作的?

浏览器结构分为:🌕用户界面——>浏览器引擎🌗——>渲染引擎🌑

浏览器引擎起到将 用户操作渲染引擎 关联起来的作用。

而其中最重要的为渲染引擎,其关乎到网络请求,js解析等。( Blink,webkit,Gecko

目前的渲染引擎又分为多个进程同时进行工作,网络请求到数据后会通知ui进程进行渲染,
而其中应该注意的为渲染器进程中的 GUI Thread( 图形渲染 和 JS Thread ( js渲染

GUI Thread 将解析HTML标签 并创建document对象,并以其为根节点创建DOM树,但解析到script标签时将会暂停。

(因为标签多为嵌套关系,其父子关系会组成树状结构不难理解吧

原因在于,JavaScript可以操作DOM,如果GUI正在渲染界面,而JS引擎对页面元素属性进行修改,
就会出现界面丢失了JS引擎修改部分的情况( 出现不可预期的结果,比如找不到页面元素 )。🤒

故浏览器设置GUI Thread 和 JS Thread 不能同时工作,
当JS Thread 执行时,GUI Thread被挂起(GUI更新保存在一个队列中,等JS Thread 空闲时被立即执行)。

所以script标签应该放在其合适的位置上

那么浏览器到底是如何将获取的网页数据转换成视图的呢?该部分理解对JS和css有一定基础要求。

  • 在DOM树生成的同时如遇到了css代码将会对其进行下载解析,
    并生成样式规则树CSSOM树并附着在DOM树上,最终生成一个可渲染树render tree
😲注意这个过程:

例如当HTML解析器被脚本阻塞时,解析器虽然会停止构建DOM,但仍然会辨识该脚本后面的资源,并进行预加载。

  • 且由于以下两点。浏览器会延迟 JavaScript 的执行和 DOM 构建:

    • CSS 被默认被视为阻塞渲染的资源,因此浏览器将在 CSSOM 构建完毕前不会渲染任何已处理的内容。
    • JavaScript 不仅可以读取和修改 DOM 属性,还可以读取和修改 CSSOM 属性,因此CSS解析与script的执行互斥。
  • 正是由于以上这些原因,script标签的位置很重要我们在实际开发中应该尽量坚持以下两个原则:

    • 在引入顺序上,CSS 资源先于 JavaScript 资源。
    • JavaScript 应尽量少的去影响 DOM 的构建。

  • 可渲染树render tree生成后将会进行布局解析,对已经计算好样式的DOM结点进行遍历生成Layout tree
    • 但Layout tree并不是与DOM树一一对应的,例如某结点的样式 display:none
      那么其不会出现在Layout tree上,这就是display为none时不会占据页面内容,
      visibility:hidden会的原因。
    • 而伪类(before after 将会出现在Layout tree中

所以Layout tree将会与页面渲染的最终效果一一对应

  • 那么Layout tree生成之后是否可以直接显示了呢?😥当然是不可以的因为元素之间的层级关系还没有确定( z-index ,主线程通过遍历Layout tree来生成一张层级关系表Paint Record其中记录各元素之间的层级关系。

  • 好!经过页面分层阶段终于可以进行绘制成像素展示在页面上了。绘制的过程称为栅格化

    • 合成器线程将页面所有元素按照一定规则,进行分图层绘制;
    • 然后将浏览器可视部分的内容合成一帧即可;
    • 合成器线程会将页面一帧分成若干个小块,发送给栅格化线程,栅格化各个小块后将其合成。
    • 最终浏览器将合成器帧发送至GPU进行渲染最终显示给用户.
可喜可贺,页面终于显示在浏览器上了🤯,我要是浏览器可能已经累死了。

注意:

以上步骤并不一定一次性顺序完成,比如DOM或CSSOM被修改时,亦或是哪个过程会重复执行,这样才能计算出哪些像素需要在屏幕上进行重新渲染。而在实际情况中,JavaScript和CSS的某些操作往往会多次修改DOM或者CSSOM。

那么如果页面通过交互改变了样式以及布局呢?

  • 重排/回流:如果页面在绘制完成后发生布局改变,那么渲染器进程将会对页面元素重新进行样式计算及后续过程,这个过程称为重排/回流reflow
  • 重绘:如果元素发生样式改变,这个过程称为重绘repaint

所以如果页面动画与JS处理同时进行,而JS的处理量过大,将会导致,主线程被JS占用而无法及时被归还,导致页面丢失动画帧,造成页面卡顿。

那么如何优化页面呢?

结合上文和我看到的一些文章,有以下几点可以优化渲染效率:

  1. 合法地去书写 HTML 和 CSS ,且不要忘了文档编码类型。
  2. 样式文件应当在 head 标签中,而脚本文件在 body 结束前,这样可以防止阻塞的方式。
  3. 简化并优化CSS选择器,尽量将嵌套层减少到最小。
  4. 尽量减少在 JavaScript 中进行DOM操作。
  5. 修改元素样式时,更改其class属性是性能最高的方法。
  6. 尽量用 transform 来做形变和位移

参考文章:

https://zhuanlan.zhihu.com/p/78230297

https://www.bilibili.com/video/BV1x54y1B7RE

https://srtian96.gitee.io/blog/2018/06/01/%E6%B5%8F%E8%A7%88%E5%99%A8%E6%B8%B2%E6%9F%93%E5%8E%9F%E7%90%86/

本人博客地址:zyeeblog.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值