前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端资源浏览器渲染原理

前端资源浏览器渲染原理

作者头像
冷环渊
发布2023-02-26 16:37:31
5360
发布2023-02-26 16:37:31
举报

浏览器的渲染页面过程

HTML解析过程

一般情况下服务器会给浏览器返回 xx.html 文件 解析html 其实就是 Dom 树的构建过程

我们可以根据以下html 结构 来简单的分析出 html 的解析过程

image-20230224173537427
image-20230224173537427
image-20230224173452450
image-20230224173452450

解析CSS 规则树

在解析的过程中,如果遇到CSS的link元素,那么会由浏览器负责下载对应的CSS文件: PS: 这里下载 CSS 是不会影响到 DOM树的解析的

下载完成后 就会对CSS 文件解析出对应的 规则树 , 案例如下图 :

代码语言:javascript
复制
body{font-size: 16px}
p{font-weight: bold}
span{color: red}
p span{display:none}
img{float: right}
image-20230224173851072
image-20230224173851072

解析步骤 构建 Render Tree

当有了DOM Tree和 CSSOM Tree后,就可以两个结合来构建Render Tree了

image-20230224173938905
image-20230224173938905

需要注意的是:

  • link元素不会阻塞DOM Tree的构建过程,但是会阻塞Render Tree的构建过程
  • Render Tree和DOM Tree并不是一一对应的关系,比如对于display为none的元素,压根不会出现在render tree中;

解析步骤 布局和绘制

  • 渲染树(Render Tree)上运行布局(Layout)以计算每个节点的几何体。
    • 渲染树会表示显示哪些节点以及其他样式,但是不表示每个节点的尺寸、位置等信息;
    • 布局是确定呈现树中所有节点的宽度、高度和位置信息;
  • 将每个节点绘制(Paint)到屏幕上
    • 在绘制阶段,浏览器将布局阶段计算的每个frame转为屏幕上实际的像素点;
    • 包括将元素的可见部分进行绘制,比如文本、颜色、边框、阴影、替换元素(比如img)

渲染的流程可以参考下图 :

image-20230224174204939
image-20230224174204939

完成以上五步 成功在浏览器渲染出 对应的 xx.html 文件

回流和重绘

回流(reflow)

reflow

  • 我们渲染出来的节点大小位置 也就是布局时第一次渲染出之后就确定的
  • 之后对于节点大小和位置重新计算的行为 叫做回流(reflow)

回流在什么时候会出现 :

  1. DOM 结构发生变化 (添加 & 移除)
  2. 改变了 CSS 样式代码 也就是布局
  3. 修改了 窗口尺寸
  4. 或者是调用了某些内置函数 获取位置和尺寸信息
重绘 (reprint)
  • 我们渲染的第一次,在之前的流程图中叫做 printing
  • 在之后需要重新渲染的时候 成为重绘

重绘怎么出现 :

  1. 修改CSS 如 颜色 文字样式
拓展思路
  1. 只要出现回流 就一定会引起重绘 其实看到上述的解释 也很容易就发现 回流也是在出发样式代码或者改变的时候触发
  2. 回流的性能并不好 也很明显 重新渲染整个DOM 很浪费性能
总结
  • 修改样式 尽可能减少回流次数 也就是设计好之后,非必要不去改动样式和DOM的结构
  • 避免频繁使用 JS 去操作DOM
  • 尽可能减少函数获取储存位置的信息

特殊解析 - composite合成

绘制的过程,可以将布局后的元素绘制到多个合成图层中。

会形成新的合成层的属性:

  • 3D transforms
  • video、canvas、iframe
  • opacity 动画转换时
  • position: fixed
  • will-change
  • animation 或 transition 设置了opacity、transform

PS:分层确实可以提高性能,但是它以内存管理为代价,所以不作为性能优化策略来使用

script元素和页面解析的关系

JS 在我们渲染过程中的那一步呢?

  1. 在渲染html的时候 js 没有继续构造DOM的能力
  2. 如果需要需要的部分 会先停止构建,下载js 执行脚本
  3. 把需要构建的东西构建完成后 继续执行构建 DOM

这么做有什么好处?

  1. JS 有操作和修改DOM的作用
  2. 为什么会先去执行js脚本? 因为之前提到了 回流时很吃性能的所以最好一次性弄好 减少不必要的回流

代码案例

index.html

代码语言:javascript
复制
<script src="./js/test.js">script>

<body>
    <div class="box">div>
body>
<script>
    var boxel = document.getElementsByClassName("box")
    console.log(boxel);
script>

test.js

代码语言:javascript
复制
debugger
console.log("hello")

新的问题:

  • 在现在的开发模式中 大多都是使用vue和React 作为开发框架 JS 的占比往往很大 处理事件也会变长
  • 这也导致了 如果解析阻塞 那么在脚本解析完成之前 可能界面什么都不显示

这里 js 给我们提供了两个属性 来解决这个问题

defer属性

defer 属性告诉浏览器不要等待脚本下载,而继续解析HTML,构建DOM Tree,如果脚本提前下载好就等待加载,等DOM完成 在触发DOMContentLoaded之前执行defer中的代码

PS: defer 按照默认顺序执行 不会影响顺序 且可以操作DOM

代码语言:javascript
复制
<script>
    window.addEventListener("DOMContentLoaded", () => {
        console.log("DOMContentLoaded");
    })
</script>
<script>
    var boxel = document.getElementsByClassName("box")
    console.log(boxel);
</script>
<script defer>
    console.log("defer-demo")
</script>
<script>
    debugger
    console.log("hello")
</script>

建议:

  • 将defer放入head中使用 这个属性的特性放在末尾 就本末倒置了
  • defer 只对外置脚本有效果

async属性

async 特性与 defer 有些类似,它也能够让脚本不阻塞页面。

它的特性:

  • 浏览器不会因 async 脚本而阻塞(与 defer 类似);
  • async脚本不能保证顺序,它是独立下载、独立运行,不会等待其他脚本
  • async不会能保证在DOMContentLoaded之前或者之后执行
代码语言:javascript
复制
<script>
    window.addEventListener("DOMContentLoaded", () => {
        console.log("DOMContentLoaded");
    })
</script>
<script async>
    console.log("defer-demo")
</script>

总结

  • defer 通常用于文档解析操作DOM且有顺序要求的JS代码
  • async 通常用于独立脚本 可以理解为没有什么依赖的脚本 如果有依赖 那么不保证一定能提前加载到

总结

  1. 首先时了解和认识一些浏览器的内核
  2. 了解从服务器加载 到渲染页面的流程
  3. 细化每一步的大致内容
  4. 发现有问题且探索到问题的一些解决方法
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-02-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 浏览器的渲染页面过程
    • HTML解析过程
      • 解析CSS 规则树
        • 解析步骤 构建 Render Tree
          • 解析步骤 布局和绘制
            • 回流和重绘
              • 回流(reflow)
              • 重绘 (reprint)
              • 拓展思路
              • 总结
            • 特殊解析 - composite合成
              • script元素和页面解析的关系
                • defer属性
                  • async属性
                    • 总结
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档