Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化关键渲染路径,加速浏览器首次渲染 #54

Open
amandakelake opened this issue Sep 11, 2018 · 0 comments
Open

优化关键渲染路径,加速浏览器首次渲染 #54

amandakelake opened this issue Sep 11, 2018 · 0 comments
Labels
Web 网络、性能、优化类

Comments

@amandakelake
Copy link
Owner

amandakelake commented Sep 11, 2018

优化关键渲染路径能够让浏览器尽可能快地绘制网页:更快的网页渲染速度可以提高吸引力、增加网页浏览量以及提高转化率。为了最大程度减少访客看到空白屏幕的时间,我们需要优化加载的资源及其加载顺序。
分析关键渲染路径性能  |  Web  |  Google Developers

渲染树构建、布局及绘制

89588ef5-d787-4f20-b9e1-6b9c23c7a6c6

  1. 处理 HTML 标记并构建 DOM 树,初始的 HTML 被完全加载和解析后会触发 DOMContentLoaded 事件
  2. 处理 CSS 标记并构建 CSSOM 树。
  3. 将 DOM 与 CSSOM 合并成一个渲染树renderTree。
  4. 根据渲染树来布局,以计算每个节点的几何信息。
  5. 将各个节点绘制到屏幕上。

优化关键渲染路径_就是指最大限度缩短执行上述第 1 步至第 5 步耗费的总时间。 这样一来,就能尽快将内容渲染到屏幕上,此外还能缩短首次渲染后屏幕刷新的时间,即为交互式内容实现更高的刷新率。

阻塞渲染的CSS

在渲染树构建中,HTML 和 CSS 都是阻塞渲染的资源,HTML 显然是必需的,因为如果没有 DOM,我们就没有可渲染的内容,但 CSS 的必要性可能就不太明显

  1. 默认情况下,CSS被视为阻塞渲染的资源
  2. 我们可以通过媒体类型和媒体查询将一些CSS资源标记为不阻塞渲染
  3. 浏览器会下载所有CSS资源,无论阻塞还是不阻塞,所以阻塞渲染仅仅是指浏览器是否需要暂停网页的首次渲染,直至该资源准备就绪
<style>/* styles here */</style> 
{{-- link标签需要加一个网络来回的时间开销 --}}
<link href="style.css" rel="stylesheet">
<link href="print.css" rel="stylesheet" media="print">
<link href="other.css" rel="stylesheet" media="(min-width: 40em)">

几种引入CSS资源的方法,是否阻塞首次渲染

  • link引入,是
  • style标签直接写入,是
  • 通过DOM api引入, 否
const style = document.createElement('link');
style.rel = 'stylesheet';
style.href = 'index.css';
document.head.appendChild(style);
  • 使用preload方式载入CSS,否
<link rel="preload" href="index_print.css" as="style" onload="this.rel='stylesheet'">
  • 为link添加media query, 当媒体查询不匹配时,不会阻塞

注意

  • CSS选择器越详细,匹配工作越多,匹配节点越慢
  • renderTree只包含了渲染网页所需要的元素,不需要的是不会被添加进去的,比如<head>,display: none的节点
    设置了visibility:hidden的元素虽不可见,但仍然占有空间,仍会被添加到RenderTree
  • layout是指计算DOM元素在最终屏幕上显示的大小和位置,由于web页面的元素布局是相对的,所以任意其中一个元素的位置发生变化,都会联动其他元素,就会产生reflow(回流)
    • 屏幕旋转
    • 浏览器视窗改变,触发resize事件
    • 与大小和位置相关的CSS属性发生改变
    • 尽量不用table布局,可能很小的一个小改动会造成整个 table 的重新布局

repaint(重绘):节点需要更改外观,但不改变布局和几何属性,就叫做重绘,比如color

JS对渲染的影响

JavaScript 可以查询和修改 DOM 与 CSSOM

由于浏览器不了解脚本计划在页面上执行什么操作,它会作最坏的假设并阻止解析器。当 HTML 解析器遇到一个 script 标记时,它会暂停构建 DOM,将控制权移交给 JavaScript 引擎;等 JavaScript 引擎运行完毕,浏览器会从中断的地方恢复 DOM 构建。因此,执行内联脚本会阻止 DOM 构建,也就延缓了首次渲染

另外,由于JS可以读取和修改CSSOM属性
如果浏览器尚未完成 CSSOM 的下载和构建,这时遇到了脚本需要运行,浏览器将延迟脚本执行和 DOM 构建,直至其完成 CSSOM 的下载和构建

如果是外部 JavaScript 文件,浏览器必须停下来,等待从磁盘、缓存或远程服务器获取脚本,这就可能给关键渲染路径增加数十至数千毫秒的延迟

所以可以通过标记外部JS文件为异步(async/defer),指示浏览器在等待脚本可用期间不阻止DOM构建
f8467ebf-c260-4595-9b54-5a4d0ea0c9dd

另外,对于执行时间过长的JS代码,可以考虑用Web Worker去处理,它不会操作DOM元素,只能做一些纯计算的工作

JavaScript代码运行在浏览器的主线程上,但浏览器的主线程还负责样式计算、布局、绘制的工作,所以JS运行时间过长会阻塞其他渲染工作,导致丢帧,每帧的渲染应该在16ms内完成,而动画占据了不少时间,所以JS代码的运行消耗应该控制在3~4ms

其他资源的影响

构建渲染树甚至绘制网页时无需等待页面上的每个资产:并非所有资源都对快速提供首次绘制具有关键作用
谈论关键渲染路径时,通常谈论的是 HTML 标记、CSS 和 JavaScript。图像不会阻止页面的首次渲染

优化关键渲染路径

为尽快完成首次渲染,我们需要最大限度减小以下三种可变因素:

  • 关键资源的数量:可能阻止网页首次渲染的资源
  • 关键路径长度:获取所有关键资源所需的往返次数或总时间
  • 关键字节的数量:所有关键资源传送文件大小的总和

优化关键渲染路径的常规步骤如下

  • 对关键路径进行分析和特性描述:资源数、字节数、长度
  • 最大限度减少关键资源的数量:删除它们,延迟它们的下载,将它们标记为异步等
  • 优化关键字节数以缩短下载时间(往返次数)
  • 优化其余关键资源的加载顺序:您需要尽早下载所有关键资产,以缩短关键路径长度

PageSpeed 规则和建议

  • 消除阻塞渲染的 JavaScript 和 CSS
  • 优化 JavaScript 的使用
    • 首选使用异步 JavaScript 资源 async
    • 延迟解析 JavaScript defer
    • 避免运行时间长的 JavaScript,也就是常说的拆分代码
  • 优化 CSS 的使用
    • 将 CSS 置于文档 head 标签内,浏览器尽早发现 标记并尽早发出 CSS 请求
    • 避免使用 CSS import,它们会在关键路径中增加往返次数
    • 内联阻塞渲染的 CSS,不会增加关键路径中的往返次数
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Web 网络、性能、优化类
Projects
None yet
Development

No branches or pull requests

1 participant