360前端星计划学习-优化关键渲染路径

浏览器渲染原理

image

DOM

CSSOM

注意: CSS选择器越详细,匹配工作越多,匹配节点越慢。

RenderTree

  • RenderTree包含了渲染网页所需的节点

  • 无需渲染的节点不会被添加到RenderTree中。 如:<head>,display: none的节点

注意: 因为设置了visibility:hidden的元素虽不可见,但仍然占有空间,仍会被添加到RenderTree

Layout

计算渲染树节点位置大小

Viewport

<meta name="viewport" content="width=device-width">

  • device-width为浏览器的理想视口

  • 在移动端,如果不设置viewport宽度为理想视口,viewport宽度通常为980px,这会导致文字很小,我们需要手动放大阅读。

触发Layout

  • 屏幕旋转

  • 浏览器视窗改变

  • 与大小位置相关的CSS属性改变

Paint

  • 根据background,border,box-shadow等样式,将Layout生成的区域填充为最终将显示在屏幕上的像素

资源对渲染的影响

资源

  • CSS

  • JS

  • Font

  • img

CSS

浏览器会在DOM和CSSOM加载完开始渲染页面

CSS阻塞初次渲染

<style>/* styles here */</style>
<link rel="stylesheet" href="index.css">
  • 通过以上两种方式定义的CSS,均会阻塞初次渲染

  • 浏览器会在解析完CSS后,再进行渲染。这是为了防止样式突变带来的抖动。

  • 通过link标签引入的CSS阻塞的时间可能更长,因为加载它需要一个网络来回时间

media query

<link rel="stylesheet" href="index_print.css" media="print">
  • 此样式表仍会加载

  • 当浏览器环境不匹配媒体查询条件时,该样式表不会阻塞渲染

  • 我们可针对不同媒体环境拆分CSS文件,并为link标签添加媒体查询,避免为了加载非关键CSS资源,而阻塞初次渲染

通过DOM API添加link

var style = document.createElement('link');
style.rel = 'stylesheet';
style.href = 'index.css';
document.head.appendChild(style);
  • 不会阻塞初次渲染

preload

<link rel="preload" href="index_print.css" as="style" onload="this.rel='stylesheet'">
  • rel不是stylesheet,因此不会阻塞渲染

  • preload是resoure hint规范中定义的一个功能

  • resource hint通过告知浏览器提前建立连接或加载资源,以提高资源加载的速度。

  • 浏览器遇到遇到标记为preload的link时,会开始加载它。

  • 当onload事件发生时,将rel改为stylesheet,即可应用此样式
    image

总结

引入CSS资源的方法是否阻塞初次渲染
<link rel="stylesheet" href="index.css" />
通过document.write写入以上标签
通过DOM API插入HTMLLinkElement对象
使用preload方式载入CSS
为link添加media query当媒体查询不匹配时,不会阻塞

JavaScript

Javascript阻塞HTML Parser(解析器)

<-- inline js -->
<script>/* app logics here */</script>

<-- external js -->
<script src="somescript.js"></script>
  • 通过以上两种方式引入js均会阻塞HTML parser,因而会阻塞出现在脚本后面的HTML标记的渲染。

  • 外部script阻塞的时间一般更长,因为可能包含了一个网络来回时间。

  • Javascript可以通过document.write修改HTML文档流,因此在执行js时,浏览器会暂停解析DOM的工作。

CSS阻塞JS

<-- inline js -->
<script>/* app logics here */</script>

<-- external js -->
<script src="somescript.js"></script>
  • 通过以上两种方式引入的JS均会被CSS阻塞

  • 由于这些Javascript可能会读取或修改CSSOM,因此需等待CSSOM构造完成后,它们才能执行

将资源放到文档底部,延迟js执行

<html>
  <head></head>
  <body>
    <h1>世界上最美丽的语言是什么?</h1>
    <button>See answer</button>
    <!-- index.js内容:
      为button标签添加点击事件,点击后,alert答案
     -->
    <script src="index.js"></script>
    <!-- 百度统计代码 -->
    <script src="tongji.js"></script>
  </body>
</html>

使用defer延迟脚本执行

<html>
  <head>
    <!-- index.js内容:
      为button标签添加点击事件,点击后,alert答案
     -->
    <script src="index.js" defer></script>
    <!-- 百度统计代码 -->
    <script src="tongji.js" defer></script>
  </head>
  <body>
    <h1>世界上最美丽的语言是什么?</h1>
    <button>See answer</button>
  </body>
</html>
  • 当script标签拥有defer属性时,该脚本会被推迟到整个HTML文档解析完后,再开始执行

  • 被defer的脚本,在执行时会严格按照在HTML文档中出现的顺序执行

注意: 使用defer时,浏览器会保证脚本按照在文档中出现的顺序执行

使用async异步加载脚本

<html>
  <head>
    <!-- index.js内容:
      document.addEventListener('DOMContentLoaded', function() {
        document.querySelector('p').onclick=function() {
          alert('surprise')
        }
      });    
     -->
    <script src="index.js" async></script>
    <!-- 百度统计代码 -->
    <script src="tongji.js" async></script>
  </head>
  <body>
    <p>Hello World</p>
  </body>
</html>
  • 当script标签拥有async属性时,该脚本不会再阻塞HTML parser。且不会被CSS阻塞。

  • 脚本只要加载完成,便可开始执行。

  • 被async的脚本,在执行时会不会严格按照在HTML文档中出现的顺序执行

  • async适用于无依赖的独立资源

image

总结

引入JS资源的方法是否阻塞文档内容初次渲染
在head中引入外部脚本<script src="index.js"></script>或内联脚本<script>/* app logics */</script>
将脚本放到body底部
为脚本添加defer属性
为脚本添加async属性

Font

Font阻塞内容渲染

  • 浏览器为了避免FOUT(Flash Of Unstyled Text),会尽量等待字体加载完成后,再显示应用了该字体的内容

  • 只有当字体超过一段时间仍未加载成功时,浏览器才会降级使用系统字体。每个浏览器都规定了自己的超时时间

  • 但这也带来了FOIT(Flash Of Invisible Text)问题。内容无法尽快地被展示,导致空白。

img

图片资源不会阻塞首次渲染

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值