美文网首页开发集中营工具癖Web前端之路
前端必读-浏览器加载页面时都做了什么

前端必读-浏览器加载页面时都做了什么

作者: 杨玉杰 | 来源:发表于2017-03-08 20:03 被阅读185次

    当一个浏览器接收到从服务器发来的html页面,在渲染并呈现到屏幕上之前,有很多步骤要做。浏览器渲染页面需要做的一系列行为被称作“关键渲染路径(Critical Rendering Path 简称CRP)”。

    CRP 的知识对于如何提升网站性能是相当有用的。CRP有6个步骤:

    1. 构建DOM树
    2. 构建CSSOM树
    3. 运行JavaScript
    4. 创建渲染树
    5. 生成布局
    6. 绘制页面


      CRP的6个步骤

    构建DOM树

    DOM(Document Object Model)树是一个表示整个解析过的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>  
    

    上面的 HTML 将会被解析成下面的DOM树


    DOM树

    HTML的优点在于它不必等待整个页面加载完成才呈现页面,可以解析一部分,显示一部分。但是像CSS、JavaScript等其他资源会阻止页面渲染。

    构建CSSOM树

    CSSOM(CSS Object Model) 是一个跟DOM相关的样式对象。它跟DOM的表示方法是相似的,但是不论显式声明还是隐式继承,每个节点都存在关联样式。

    In the style.css file from the document mentioned above, we have the folowing styles
    在上面提到的html页面的style.css中的样式如下

    body { font-size: 18px; }
    
    header { color: plum; }  
    h1 { font-size: 28px; }
    
    main { color: firebrick; }  
    h2 { font-size: 20px; }
    
    footer { display: none; }  
    

    它会被构建成下面的CSSOM树


    CSSOM树

    CSS 被认为是 “渲染阻塞资源”,它意味着如果不首先完全解析资源,渲染树是无法构建的。CSS由于它的层叠继承的性质,不能像HTML一样解析一部分,显示一部分。定义在文档后面的样式会覆盖或改写之前定义的样式,因为在整个样式表都被解析之前,如果我们使用了在样式表中较早定义的样式,那错误的样式将被应用。这意味着CSS必须被全部解析之后,才能开始下一步。

    如果CSS文件适用于当前设备的话,仅仅只是会阻塞渲染。<link rel="stylesheet">标签可以使用media属性,用来指定特定样式宽度的特定媒体查询。

    举个例子,如果我们有一个包含媒体属性orientation:landscape的样式,我们使用纵向模式(portrait mode)查看页面,这个资源将不会阻塞渲染。

    CSS 也会导致脚本阻塞。这是因为JavaScript文件必须等待CSSOM被构建后才能运行。

    运行JavaScript

    JavaScript被认为是解析阻塞资源,这意味着HTML的解析会被JavaScript阻塞。

    当解析器解析到 <script> 标签时,无论该资源是内部还是外链的都会停止解析,先去下载资源。这也是为什么,当页面内有引用JavaScript文件时,引用标签要放到可视元素之后了。

    为避免JavaScript解析阻塞,它可以通过设定 async 属性来要求其异步加载。

    <script async src="script.js">
    

    创建渲染树

    渲染树是DOM和CSSOM的结合体,它代表最终会渲染在页面上的元素的结构对象。这意味着它只关注可见内容,对于被隐藏或者CSS属性 display:none 的属性,不会被包含在结构内。

    使用上面例子的DOM和CSSOM,渲染树被创建如下:


    渲染树

    生成布局

    布局决定了浏览器视窗的大小,它提供了上下文依赖的CSS样式,如百分比或窗口的单位。视窗尺寸通常通过 <head> 标签中的 <meta> 中的 viewport 设定来决定。如果不存在该标签,则通常默认为 980px

    例如,最常用的 meta veiwport 的值将会被设置为和设备宽度相符:

    <meta name="viewport" content="width=device-width,initial-scale=1">  
    

    如果用户访问网页的设备宽度为1000px。然后整体视窗尺寸就会基于这个宽度值了,比如 50% 就是500px, 10vw 就是100px 等等。

    绘制页面

    最后,在绘制页面步骤。页面上的所有可见内容都会被转换为像素并呈现在屏幕上。

    具体的绘制时间跟DOM数以及应用的样式有关。有些样式会花费更多的执行时间,比如复杂的渐变背景图片所需要的计算时间远超过简单固定背景色。

    整合所有

    想要看到关键渲染路径的执行流程,可以使用DevTools,在Chrome中,它是根据时间轴展示的。

    举个例子, 上面的页面加入<script>标签

    <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>  
    

    可以看关于页面加载时的事件日志,以下是我们获得的:


    时间轴
    1. Send Request - 发送到index.html的GET请求
    2. Parse HTML and Send Request - 开始解析HTML并构建DOM,然后发送 GET 请求style.css和main.js
    3. Parse Stylesheet - 根据 style.css 创建的CSSOM
    4. Evaluate Script - 执行 main.js
    5. Layout - 基于HTML的元视窗标签,生成布局
    6. Paint - 绘制网页
      基于这些信息,我们可以知道如何优化关键渲染路径。

    原文: Understanding the Critical Rendering Path

    相关文章

      网友评论

      本文标题:前端必读-浏览器加载页面时都做了什么

      本文链接:https://www.haomeiwen.com/subject/qqkigttx.html