原文: https://bitsofco.de/understan...做者:Ire Aderinokuncss
浏览器从接收到服务器返回的 HTML 到渲染像素到屏幕上,中间经历了不少的步骤。浏览器初次绘制网页的必通过程称之为“关键渲染路径(Critical Rendering Path,如下称CRP)”。html
CRP的知识对理解怎样提高网站性能很是有用。CRP有如下6个阶段:chrome
DOM 树是一个表示完整解析过的 HTML 网页的对象。它从根元素 <html> 开始,每个节点表明页面上的一个元素或者文本。包含在其余元素中间的元素被表示成子节点。每个节点记录着对应元素的全部属性,举例来讲,一个 <a>
元素对应的节点包含了元素的 href
属性。浏览器
<html> <head> <title>Understanding the Critical Rendering Path</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Understanding the Critical Rendering Path</h1> </header> <main> <h2>Introduction</h2> <p>Lorem ipsum dolor sit amet</p> </main> <footer> <small>Copyright 2017</small> </footer> </body> </html>
以这个网页为例,它将被解析成下图的 DOM树:服务器
A good thing about HTML is that it can be executed in parts. The full document doesn't have to be loaded for content to start appearing on the page. However, other resources, CSS and JavaScript, can block the render of the page.
HTML 的一点好处是它能够分块执行,无需加载整个文档,内容就能够开始出如今页面上。可是很差的地方是,诸如CSS 和 JavaScript 文件这样的资源,却可以阻塞页面的渲染。并发
CSSOM (CSS 对象模型) 是一个表示DOM相关联样式的对象。它与DOM的表现方式相似,但记录了每一个节点的关联样式,包含明确声明的样式和默认继承的样式。app
在上面文档中提到的style.css里, 咱们声明了以下样式:异步
body { font-size: 18px; } header { color: plum; } h1 { font-size: 28px; } main { color: firebrick; } h2 { font-size: 20px; } footer { display: none; }
上面的样式会生成以下的CSSOM 树:async
CSS 被称为 “渲染阻塞资源(render blocking resource)” 。渲染阻塞资源 没有通过初次完整解析,渲染树(后面会解释) 不会被构建。因为CSS 具备继承和层叠的特性,它不能像 HTML同样被分块解析。在CSS 文档后面定义的样式会覆盖或更改前面定义的样式。因此若是咱们只解析前面部分的 CSS 样式,而非整个 CSS 文档,那么有可能解析出来错误的结果。这意味着 CSS 必须被完整解析,咱们才能进入页面渲染的下一个阶段。布局
CSS 文件只有适用于当前设备的时候才会被认为是 ”渲染阻塞资源“ 。<link rel="stylesheet">
标签能够接受一个媒体属性,经过改属性咱们能够声明样式表适用的设备。例如:咱们有个样式表声明了一个媒体属性 orientation:landscape
, 只有咱们在纵向模式访问的时候,该资源才是阻塞渲染的。
因为 Javascript 文件必须等待 CSSOM 构建完成才可以运行。所以也能够说CSS 是 “阻塞脚本”的。
JavaScript 被认为是一种 解析阻塞资源,HTML 自己的解析会被 JavaScript 阻塞。
当解析器遇到 <script>
标签时,不论是内部脚本仍是外部脚本,解析器会停下来加载脚本(是外部脚本的状况下)并运行它。这就是为何咱们必须将哪些须要引用 Element 和文档的脚本放在文档外观的后面。
为了不 Javascript 阻塞解析,经过声明async
属性,可让它被异步加载。
<script async src="script.js">
渲染树 是 DOM 和 CSSOM的结合。它是一个表示页面被最终渲染效果的树。这意味着它只会表示哪些可见的内容,哪些不可见内容,好比声明了display:none;
的元素。
使用前面例子中提到的 DOM 和 CSSDOM ,下面的 渲染树 会被建立出来。
布局决定了视窗(viewport)的大小,它提供了 CSS 样式依赖的上下文,例如视窗的百分比或者单位。
视窗的大小由在文档头部提供的 meta 标签 viewport
决定,若是没有提供,视窗默认宽度是980px。
举例,经常使用于响应设备宽度的视窗设置以下:
<meta name="viewport" content="width=device-width,initial-scale=1">
若是用户使用宽度为1000px的设备访问网页,网页的大小会基于这个单位。一半视窗的大小是500px,10vw会是100px。
最终的步骤是绘制,页面的可见内容会被转化成屏幕上的像素。
绘制过程的耗时取决于 DOM 的大小和应用的样式。某些样式比其余样式须要更多的处理过程。例如:复杂的渐变背景图比简单的填充背景须要消耗更多的处理时间。
为了查看 CRP 过程,咱们能够打开 chrome 的 devTools,它在Timeline 菜单下面(对于新版Chrome ,位于Performance菜单下)。
以咱们上面的 HTML 为例。
<html> <head> <title>Understanding the Critical Rendering Path</title> <link rel="stylesheet" href="style.css"> </head> <body> <header> <h1>Understanding the Critical Rendering Path</h1> </header> <main> <h2>Introduction</h2> <p>Lorem ipsum dolor sit amet</p> </main> <footer> <small>Copyright 2017</small> </footer> <script src="main.js"></script> </body> </html>
打开页面加载过程的Event Log选项 ,咱们能够看到
基于这些信息,咱们能够作出如何优化CRP的决策。