通俗的说下浏览器的渲染过程

本文详细探讨了浏览器如何处理HTML、CSS及JavaScript等资源,包括下载、解析、执行及渲染的过程,并介绍了不同类型的资源加载时机及其对页面渲染的影响。

最初的模型:

  • 浏览器下载 html

  • 开始解析 html

    • 遇见外链资源, 保存起来, 并且继续解析

    • html 解析结束

    • 开始下载外链

      • 下载结束

        • 开始处理

          • css 处理

          • js 处理

            • 处理完毕, 开始渲染

            • 用户看到界面

这个模型的基础是: 浏览器是单线程的.

但是实际上: 浏览器不是单线程, 是多个线程.
浏览器有如下几个线程:
1 javascript引擎线程
2 界面渲染线程
3 浏览器事件触发线程
4 http请求线程

也就是说: 下载和解析是可以同步的, 遇见外链就开始下载.

更改之后的模型

  • 浏览器下载 html

  • 开始解析 html

    • 遇见外链资源, 开始下载, 并且继续解析

    • html 解析结束

    • 下载结束

      • 开始处理

        • css 处理

        • js 处理

          • 处理完毕, 开始渲染

          • 用户看到界面

这个模型的基础是:
资源下载和 html 解析是同步的, 所有的资源下载结束, 才开始进行下一步:渲染.
实际情景是:
资源大致可以分成
css
js
imgs
others

imgs以及 others 这种, 如果一个资源过大, 比如说一个媒体文件100M, 非要等到用户下载结束
才开始下一步, 这显然是不合理的.
而 css 和 js 是可以对页面产生修改和效果的, 所以必须要等待它们的参与才能进行下一步操作,
比如说 css,js 都没有下载解析执行结束, 就开始下一步渲染, 最终渲染的结果是一个没有样式的
页面.

看浏览器是不是这么想的?
实验:
在demo 中加一个 p 标签, 在底部加一个 css 外链
如果 css 都没有加载完毕, p 标签就显示出来了, 说明浏览器就没有等 css 文件
也就是说: html 解析结束之后, 什么都不管, 就开始下一步渲染了.

demo:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
</head>
<body>
    <p>hello world</p>
    <link rel="stylesheet" href="https://www.google.com.hk/test.css">
</body>
</html>

结果:
css 没有加载之前, 页面空白, 说明 html 解析结束之后, 会等到css加载出来再开始渲染.

更一步的实验:
资源变成 js, 页面先渲染出来, js 还在加载.
资源变成 img, 页面会先渲染出来, img 还在加载.

结论:
**html 解析结束之后, 会先等到 css 下载和解析结束之后(通过 link 标签知道是 css 文件)
再开始下一步, 并不会等所有的非 js 资源.**

所以模型变成:

  • 浏览器下载 html

  • 开始解析 html

    • 遇见外链资源, 开始下载, 并且继续解析

    • html 解析结束

    • 等到css下载结束

      • 开始处理 css

        • 处理完毕, 开始渲染

        • 用户看到界面

现在考虑一种情况:
js 是有能力去改变 DOM, 那么如果都渲染结束了, js 这个时候开始执行了,然后把页面重新干掉了.
这个时候怎么办?


只能将修改应用到已经渲染好的页面上.

考虑一种极端情况, 页面里面有成千上万的节点, 比如说1万个节点, css 文件都 一两百k
辛辛苦苦浏览器把页面渲染出来了, 然后这个时候, js 下载结束开始执行, 啪的一下把页面


document.write('中奖啦');

这种情况肯定不能允许发生.

为了避免这种情况, 可以这样
先全局检测下是不是有 script 标签, 如果有的话, html 就等着 script 加载执行之后,
再开始渲染.

这种方式有一个不好: 也就是说, 即使我们现在有了 html 和 css, 其实都可以把页面渲染出来了
但是还是要等 script 下载执行之后才敢进行渲染, 有点投鼠忌器的感觉.
有时候等半天, 可能 script 返回的就一句话:

console.log('逗你玩');

而且全局检测 script 标签, 这句话说的简单, 实际上是要建立在你已经把 html 解析结束了之后才知道
到底有没有 script 标签.

所以实际的情况是:

浏览器不知道页面里面有没有 script 标签
不知道script 里面会不会有 DOM 操作, 是 '中奖啦' 还是 '逗你玩'

面对这种情况, 实际上只能赌, 或者说博弈.

浏览器拿到 html 和 css 之后依旧开始解析渲染
为了减小万一中奖之后全盘都输的情况, 当遇见 script 之后

停止解析, 专心下载 js 文件
    这样即使中奖, 我也就渲染了前面了一点内容, 后面的还没有渲染, 输少点
    但是这样后面如果还有资源要加载。。。
    

所以更新策略:

浏览器遇见 script, 开始下载, 把后面的html 解析掉, 所有的资源都开始下载
然后回头安心等这个 script, 看看到底中奖不中奖.

所以模型变成:

  • 浏览器下载 html

  • 开始解析 html

    • 遇见外链, 开始下载

      • 发现 script 外链, 继续html解析

        • 将页面分成两部分, script 标签之前, 之后

          • 处于 script 之前的页面

            • css 下载结束

              • 渲染

              • 处于 script 之后的页面

                • script 下载完毕, 执行

                  • css 下载完毕

                    • 渲染

浏览器不是等所有的资源都下载结束才开始渲染
浏览器也不是等到所有的 js 都执行结束之后才会渲染

具体的渲染过程

当 html 解析成 DOM tree, css 解析成 CSSOM, 二者合并成
Render Tree, 就可以开始渲染了.

首先要先计算这棵树上面的所有的节点的位置, 这一步叫做 layout
然后要给每个节点上色, 这一步叫做 paint
layout 和 paint 统称为 render.

当页面的元素的位置修改之后, 就会出现 relayout (重绘)
relayout 必定会造成 repaint.

附录: defer, async 之间的区别.

defer
之前说了, 浏览器遇见 js 之后会始终等着它执行, 后面的内容都不渲染了
然后经常就报错了, 我草获取某个节点怎么没有, 想要获取后面的节点但是节点还没有
渲染出来, 所以呢, 所以就有了 defer
相当于说, 我等你全部渲染之后再执行吧, 要不然我老是出错, 烦人.
执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

async
还有一种情况, 就是说, 浏览器辛辛苦苦等到 js 下载执行结束发现哎吆我草这个玩意
对dom屁改动都没有, 我等她干嘛啊, 我草草, 那就出来 async
这个东西就是说, 不需要等我, 也不需要关心我的执行, 我不会干扰你的, 你做自己的事情就好.
同时也解决了多个js之间的依赖, 加上这个就表示, 我是孤立的, 我不依赖任何其他js也不给任何其他
js 依赖.

<think>嗯,用户想了解浏览器控制台里的Performance面板下Summary部分的获取方法。首先,我需要回忆一下Chrome DevTools的结构。Performance面板是用来分析页面运行时性能的,通常包括录制、分析结果等步骤。用户提到的是Summary,也就是摘要信息,这部分应该是在录制结束后显示的概览数据。 接下来,我需要确定如何引导用户找到Summary。可能需要分步骤明:打开控制台,进入Performance面板,开始录制,执行操作,停止录制,然后查看结果。其中Summary会在结果页面的顶部显示,包含加载、脚本、渲染、绘制等时间信息。 用户可能的需求是优化网页性能,所以需要解释Summary中各指标的含义,比如Loading、Scripting、Rendering、Painting的时间分布,帮助用户理解哪里存在瓶颈。同时,要提醒他们可能需要多次录制取平均值,或者结合其他面板如Network或Memory来综合分析。 另外,需要注意用户可能对专业术语不太熟悉,需要用通俗的语言解释,避免过于技术化。例如,解释渲染和绘制的区别,或者为什么脚本执行时间过长会影响性能。 最后,确保回答结构清晰,按照步骤明如何获取Summary,并详细解释各个部分的作用,这样用户能够实际应用这些信息来优化他们的网页。</think>浏览器控制台中的 `Performance` 面板下的 **Summary(摘要)** 是用于分析网页运行时性能的核心数据概览。以下是逐步明如何获取和解读它的方法: --- ### **1. 如何获取 Performance Summary** #### **步骤 1:打开浏览器控制台** - 右键点击网页,选择 **“检查”**(或按 `F12`/`Ctrl+Shift+I`)。 - 切换到 **`Performance`** 面板。 #### **步骤 2:录制性能数据** - 点击 **⚫ 圆形录制按钮**(或按 `Ctrl+E`)开始录制。 - 在页面上执行需要分析的操作(例如点击按钮、滚动页面)。 - 点击 **⏹️ 停止按钮** 结束录制。 #### **步骤 3:查看 Summary** - 录制结束后,面板会自动生成性能报告。 - **Summary 区域** 通常位于报告顶部,以条形图形式展示时间分布。 --- ### **2. Summary 的核心内容** Summary 将页面运行时间按类型划分为 4 类(不同浏览器可能略有差异): 1. **Loading(加载)** - 资源下载、解析 HTML/CSS、构建 DOM/CSSOM 的时间。 - 高值可能意味着资源过大或网络问题。 2. **Scripting(脚本执行)** - JavaScript 解析、编译、执行的时间。 - 长时间可能表示复杂计算或未优化的代码。 3. **Rendering(渲染)** - 计算布局(Layout)和样式(Style)的时间。 - 频繁触发布局抖动(Layout Thrashing)会导致此值偏高。 4. **Painting(绘制)** - 将像素绘制到屏幕的时间。 - 复杂 CSS 效果(如阴影、渐变)会增加绘制时间。 --- ### **3. 关键分析技巧** - **定位瓶颈**:Summary 中的时间占比直接反映性能瓶颈。例如,如果 `Scripting` 占 70%,需优化 JavaScript。 - **结合其他面板**: - 使用 **`Main`** 面板查看主线程活动。 - 用 **`Network`** 分析资源加载。 - 用 **`Memory`** 检查内存泄漏。 - **多次录制**:性能可能受缓存或随机因素影响,建议多次录制取平均值。 --- ### **4. 示例代码(模拟分析场景)** 若需手动触发性能分析,可结合 `console` API: ```javascript // 开始标记 performance.mark('start'); // 模拟耗时操作(例如遍历大数组) const array = new Array(1000000).fill(0).map((_, i) => i); // 结束标记 performance.mark('end'); performance.measure('耗时操作', 'start', 'end'); // 获取测量结果 const measure = performance.getEntriesByName('耗时操作')[0]; console.log('操作耗时:', measure.duration + 'ms'); ``` --- ### **5. 注意事项** - **无痕模式**:避免浏览器插件干扰,建议在无痕窗口测试。 - **CPU 节流**:可模拟移动端性能(通过 DevTools 右上角 ⚙️ 设置)。 - **内存限制**:长时间录制可能导致浏览器卡顿或崩溃。 通过 Summary,你可以快速定位性能问题并制定优化策略。如果需要更细粒度的分析,可进一步查看 `Call Tree`(调用树)或 `Event Log`(事件日志)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值