# Web性能优化

# 浏览器渲染流程和阻塞

# 浏览器渲染流程

通过Chrome的开发者工具 的 performance 的查看event Log,流程有下面这些:

  1. Loading
  2. parseHTML
  3. recalculate style
  4. layout
  5. paint
  6. composite layer

网页请求从 HTML 文件请求开始。服务器返回 HTML -- 响应头和数据。然后浏览器开始解析 HTML,转换收到的数据为 DOM 树。浏览器每次发现外部资源就初始化请求,无论是样式、脚本或者嵌入的图片引用。有时请求会阻塞,这意味着解析剩下的 HTML 会被终止直到重要的资源被处理。浏览器接着解析 HTML,发请求和构造 DOM 直到文件结尾 ,这时开始构造 CSS对象模型。等到 DOM 和 CSSOM 完成之后,浏览器构造渲染树,计算所有可见内容的样式。一旦渲染树完成布局开始,定义所有渲染树元素的位置和大小。完成之后,页面被渲染完成,或者说是绘制到屏幕上。

# 关键渲染路径(The Critical Rendering Path,简称 CRP )

关键渲染路径是指浏览器通过把 HTML、CSS 和 JavaScript 转化成屏幕上的像素的步骤顺序,也就是渲染流程。关键渲染路径包含了 Document Object Model (opens new window)(DOM),CSS Object Model (opens new window)(CSSOM),渲染树和布局。

优化关键渲染路径可以提升首屏渲染时间。理解和优化关键渲染路径对于确保回流和重绘可以每秒 60 帧、确保高性能的用户交互和避免无意义渲染至关重要。

# css 样式引入

  • style 样式(内联样式)

    • HTML 解析器解析

    • 不阻塞 DOM 解析

    • 不阻塞页面渲染

    • 可能会造成页面闪屏

  • link引入(外联样式)

    • CSS 解析器解析
    • 不阻塞 DOM 解析
    • 阻塞页面渲染(解决页面闪屏)
    • 阻塞后续 JS 代码执行

    因为等待获取CSS不会阻塞HTML的解析或者下载,但是它的确阻塞JavaScript,因为JavaScript经常用于查询元素的CSS属性。

# JS 引入

浏览器遇到 JS 就会停下来执行 JS 代码,不管是以script写脚本还会引入脚本文件,这时就会阻塞 DOM 解析、页面渲染和后续 JS 执行。

因为 JS 可操作DOM,所以DOM 解析会受到影响,进而影响页面渲染。

JS引擎 是单线程的,所以会影响后续 JS 执行。

# 阻塞渲染

  • css阻塞

    主要是以 link 方式引入 style 文件,会引发 CSS 阻塞,主要体现:

    • 不阻塞DOM 解析,
    • 阻塞页面渲染,
    • 阻塞后续的 JS 的执行。

    原因:

    因为 CSS 解析器在 CSS 文件完整下载后,就会开始执行 CSS 解析,此时渲染进程就会等待CSS 解析完后才开始渲染页面。但是 不影响 DOM 解析。

    优化:核心是优化 CSS 的传送

    • 使用 CDN 节点进行外部资源加速
    • 压缩 CSS 文件(使用webpack\gulp 等打包工具),减少文件的大小
    • 减少 http 请求,也就是减少请求的文件个数
    • 优化 CSS 样式表,避免写内部样式<p style='..'> ,避免不必要的代码重复
  • JS 阻塞

    • 阻塞 DOM 解析
    • 阻塞页面渲染
    • 阻塞后续 JS执行

    原因:

    因为 JS 可操作DOM,所以当解析器遇到脚本,就会停止解析 HTML,而去执行 JS 脚本,进而影响页面渲染。对于外部脚本,还会强制解析器等待相应资源下载完毕(这可能会产生一次或多次网络往返过程并导致网页的首次呈现时间延迟)。

    JS引擎 是单线程的,所以会影响后续 JS 执行。

    优化:核心是移除会阻止内容呈现的 JS

    • 内嵌javascript

      若 js 脚本较小,则可以内嵌脚本到 HTML,以减少网络请求延迟

    • 异步加载JavaScript

      默认情况下,脚本会让浏览器停止 DOM 解析,为防止 JavaScript 阻止解析器正常运行,对外部脚本使用 HTML async 属性。

      <script async src='....js'></script>

      但是要注意 async下载脚本并不按指定顺序下载,所以加入依赖关系的脚本则慎用 async

    • 延迟加载 JavaScript

      如果某些脚本对于网页初次呈现没什么影响,则可将这部分脚本延迟到网页展示完后加载,这样做有助于减少资源争用并提高性能。使用 HTML defer 属性。defer表示脚本将在 HTML解析完后,但在 DOMContentLoaded 前触发。

      <script defer src='....js'></script>

    # 重排重绘

# Web性能优化

# Web 性能

Web 性能是客观的衡量标准,是用户对加载时间和运行时的直观体验。Web 性能指页面加载到可交互和可响应所消耗的时间,以及页面在交互时的流畅度——滚动是否顺滑?按钮能否点击?弹窗能否快速打开,动画是否平滑?

Web 性能既包括客观的度量如加载时间,每秒帧数和到页面可交互的时间;也包括用户的对页面内容加载时间的主观感觉。

# web 性能关键指标

  • 首屏加载时间

    从用户请求打开新网页到浏览器呈现出首屏内容所用的时间。

  • 完整网页加载时间

    从用户请求打开新网页到浏览器完全呈现出相应网页所用的时间。

# 影响 web性能的因素

  • 阻碍呈现的往返次数:加载阻碍呈现的资源 (opens new window)所需的往返次数,主要是指网络请求次数。
  • 响应大小:响应的总体大小,包括 HTML 主要资源和所有子资源。可通过压缩或者分块减少文件大小。

# 常见 web 性能优化方法

参考:

  1. Google dev | PageSpeed Insights (opens new window)
  2. MDN | Web 性能 (opens new window)
  3. 浏览器怎么工作 (opens new window)
  4. 节流和防抖的区别 (opens new window)