web性能

1. css 动画与Javascript(requestAnimationFrame())动画性能

总结:浏览器可以优化渲染流程。总之,我们总是尽可能通过CSS transition和animation创建动画。若是不得不依赖javascript动画 采用 requestAnimationFrame()

2. dns-prefetch(DNS 预获取)

DNS-prefetch(DNS 预获取) 是尝试在请求资源之前解析域名。这可能是后面要加载的文件,也可能是用户尝试打开的链接目标

句法:


// dns-prefetch 可帮助开发人员掩盖 DNS 解析延迟HTML <link>元素 通过 dns-prefetch 的 rel 属性(rel 属性定义了所链接的资源与当前文档的关系)值提供此功能。然后在 href 属性中指要跨域的域名:
<link rel="dns-prefetch" href="https://fonts.googleapis.com/">

最佳实践 记住三点

一.dns-prefetch 仅对跨域上的DNS查找有效,因此请避免使用它来指向您的站点或域。这是因为,到浏览器看到提示时,您的站点域背后的IP已经被解析。

二.还可以通过 使用HTTP 链接字段将 dns-prefetch(以及其他资源提示)指定为 HTTP 标头


Link: <https://fonts.gstatic.com/>; rel=dns-prefetch

三.考虑将dns-prefetch与preconnect(预连接)提示配对。尽管dns-prefetch仅执行DMS查找,单preconnect会建立与服务器的连接。 如果站点是通过HTTPS服务的,则此过程包括DNS解析,建立TCP连接以及执行TLS握手。将两者结合起来可提供进一步减少 跨域请求的感知延迟的机会。您可以安全地将它们一起使用,如下:


<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="https://fonts.gstatic.com">

配对这些提示的逻辑是因为对 dns-prefetch 的支持比对预连接的支持要好。

3. Lazy loading

**延迟加载(懒加载)**是一种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略。这是一种延迟加载对第一次渲染并不重要的资源来缩短关键渲染路径的长度的方法,可以缩短页面加载时间延迟加载可以在应用程序的不同时刻,发生,但通常会在某些用户交互(例如滚动和导航)上发生。

综述

  • ** 代码拆分** 可以将JavaScript、CSS和HTML分割成小块,以发送最少的代码提供关键信息,以优化页面的加载时间。其余部分可以在需要时加载。


1. Entry point splitting: separates code by entry point(s) in the app
2. Dynamic splitting: separates code where dynamic import() statements are used
  • Javascript 脚本类型模块 任何类型为 type="module"的脚本标签都被视为一个 JavaScript 模块,并且默认情况下会被延迟。

  • CSS, 默认情况CSS 被视为渲染阻塞资源,因此,在 CSSOM 被构造完成之前,浏览器不会渲染任何已处理的内容。CSS 必须很薄,才能尽快交付,建议使用媒体类型和查询实现非阻塞渲染。


<link href="style.css"    rel="stylesheet" media="all">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="print.css"    rel="stylesheet" media="print">
  • Fonts 默认情况 ,字体请求会延迟到构造渲染树之前,这可能会导致文本渲染延迟。


// 可以使用<link rel="preload">, CSS font-display属性和字体加载API来覆盖默认行为和预加载web字体资源。
It is possible to override the default behaviour and preload web font resources using <link rel="preload">, the CSS font-display property, and the Font Loading API.

See also: Element Link
  • Images and iFrames

通常情况下,网页包含许多有助于数据使用和页面加载速度的图像。这些图像大多在屏幕外(非关键),需要用户交互(例如滚动)才能查看它们。

Loading 属性 The loading attribute on an ](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/img) element (or the [`loading`](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/iframe#attr-loading) attribute on an [) can be used to instruct the browser to defer loading of images/iframes that are off-screen until the user scrolls near them.


<img src="image.jpg" alt="..." loading="lazy">
<iframe src="video-player.html" title="..." loading="lazy"></iframe>
4. Performance Monitoring: RUM vs synthetic monitoring

综合监控真实用户监控 (RUM) 是两种监视和提供 Web 性能见解的方法。

5. 优化启动性能

一个软件应用开发中经常被忽视的方面--即便在那些专注于性能优化的软件中--就是启动时的表现。你的应用需要花费多长时间启动?当应用加载时是否会卡住用户设备或浏览器?这会让用户担心你的应用崩溃了,或者哪里出错了。花时间确保你的应用能够更好地启动总是一个好主意。

更好的启动

异步启动,不需要启动所有的代码在主线程中唯一一个事件处理函数中运行,让应用在后台线程创建一个 Web worker ,做尽可能多的工作(比如,获取和处理数据)。

给应用添加:无响应页面 或 加载缓慢的提醒。你应该显示几种界面,比如进度条,这样用户可以在应用启动时知道他们需要等待多长时间。

异步化

关于如何构建你的启动过程,使得其尽可能异步执行,这里有些建议。(不论是新应用还是移植的):

  • 启动时在需要异步执行的脚本标签上使用 deferasync 属性。这会允许 HTML 解析器更高效地处理文档。

  • 如果你需要解码资源文件(比如,解码 JPEG 文件并将其转换为原始纹理数据,以便随后在 WebGL 中使用),最好在 workers 里做这件事。

  • 当处理浏览器支持的数据格式时(例如,解析图像数据),使用设备或浏览器内置的解码器而不是运行你自己的或者使用 or using one from the original codebase。预先提供的那个基本上一定会快得多,并且能够减小你的应用的启动体积。另外,浏览器可以自动并行化这些解码器的工作。

  • 所有能并行的数据处理都应该并行化。不要一团接一团地处理数据,如果可能的话,同时处理它们!

  • 在你启动的 HTML 文件中,不要包含不会在关键路径下出现的脚本或样式表。只在需要时加载他们。

  • 不要强迫 Web 引擎构建不需要的 DOM,一种简单的“hack”的方式是把你的 HTML 留在文档里,但是在外层包裹注释。


<div id="foo"><!--
  <div> ...
--></div>
  • 当文档的一部分需要被渲染时,加载被注释的 HTML


foo.innerHTML = foo.firstChild.nodeValue;

你能通过异步的方式做的事越多,应用就能更好的利用多核处理器。

  • 我究竟要异步化什么程度?

最好记住大多数浏览器,在你的代码阻塞主线程太长时间--大约10秒左右的时候,就会抱怨。理想 情 况下,你不会在任何地方阻塞那么长时间,但是只要你把时间保持在这之下,就不会有问题。不过要记住,如果有人有个比你更旧更慢的电脑,他们或许会比你经历更长的等待!

其他建议

除了异步化之外,还有一些其他的事情,可以帮助你改善应用启动时间。这是其中的一部分:

  • 下载时间

一定要记住用户需要花多少时间下载你游戏的数据。如果你的游戏非常大,很受欢迎,或者需要频繁的重下内容,你应该考虑买个速度越快越好托管服务器。你还应该考虑压缩数据,尽可能缩小其体积。

  • GPU 因素

编译着色器,以及将纹理传输到 GPU 会占用时间,特别是在比较复杂的游戏中。尽管这也会发生在本地 (非 Web ) 游戏中,但还是会很恼人。不要不告诉用户游戏实际上还在启动中就这么做。

  • 数据大小

尽力优化游戏数据的体积,小一些的文件下载和处理都比大文件快。

  • 主观因素

你可以在启动过程中做一些事情来使用户专注于其上,这会让时间看起来过得更快些。就游戏而言,可以考虑播放一些背景音乐或者显示漂亮的启动画面;在运算执行期间,更新你的进度提示,改变显示内容,或者做任何你想做的事情:这有助于用户知晓应用正在做一些工作,而不是一声不吭地呆在那儿

6. 关键渲染路径

关键渲染路径是浏览器将HTML,CSS和Javascript转换为屏幕上的像素所经历的步骤序列。优化关键渲染路径可提高渲染性能。关键渲染路径包含了 文档对象模型(DOM),CSS 对象模型 (CSSOM),渲染树和布局。

优化关键渲染路径可以缩短首次渲染的时间。了解和优化关键渲染路径对于确保重排和重绘可以每秒 60 帧的速度进行,以确保高效的用户交互并避免卡顿是很重要的。

理解CRP :Web性能包含了服务器的请求和响应、加载、执行脚本、渲染、布局和绘制每个像素到屏幕上。

  • 网页请求从HTML文件请求开始。服务器返回HTML--响应头和数据

  • 浏览器开始解析HTML,转换收到的数据为DOM树。浏览器每次发现外部资源就初始化请求,无论是样式、脚本或者嵌入的图片引用。有时请求会阻塞,这意味着解析剩下的HTML会被终止知道重要的资源被处理。浏览器接着解析HTML,发请求和构造DOM直到文件结尾

  • 这时开始构造CSS对象模型。

  • 等到DOM和CSSOM完成后,浏览器构造渲染树,计算所有可见内容的样式。

  • 一旦渲染树完成布局开始,订阅所有渲染树的位置和大小。完成后页面被渲染完成

文本对象模型:DOM构建是增量的,使用时在满足需求的情况下,尽可能精简DOM树

CSS对象模型:避免重复的样式,可以使用压缩和使用媒体查询来异步处理 CSS 为非阻塞的请求。

渲染树:渲染树包括了内容和样式:DOM 和 CSSOM 树结合为渲染树。

布局:一旦渲染树被构建,布局变成了可能。布局取决于屏幕的尺寸。布局这个步骤决定了在哪里和如何在页面上放置元素,决定了每个元素的宽和高,以及他们之间的相关性。节点数越多,布局就需要更长的时间。为了减小布局事件的频率和时长,批量更新或者避免改动盒模型属性。

绘制:最后一步是将像素绘制在屏幕上。一旦渲染树创建并且布局完成,像素就可以被绘制在屏幕上。加载时,整个屏幕被绘制出来。之后,只有受影响的屏幕区域会被重绘,浏览器被优化为只重绘需要绘制的最小区域。绘制时间取决于何种类型的更新被附加在渲染树上。绘制是一个非常快的过程,所以聚焦在提升性能时这大概不是最有效的部分,重点要记住的是当测量一个动画帧需要的时间需要考虑到布局和重绘时间。添加到节点的样式会增加渲染时间,但是移除样式增加的 0.001ms 或许不能让你的优化物有所值。记住先测量。然后你可决定它的优化优先级。

优化CRP :提升页面加载速度需要通过被加载资源的优先级、控制它们加载的顺序和减少这些资源的提交入手。性能提示包含

  • 1通过异步、延迟加载或者消除非关键资源来减少关键资源的请求数量。

  • 2优化必须请求数量和每个请求的文件体积

  • 3通过区分关键资源的优先级来优化被加载关键资源的顺序,来缩短关键路径长度。

参考博客

综述:关键渲染路径最重要的,它使得网站优化有规律可循。需要关注3个指标:

  1. 关键字节数

  1. 关键文件数

  1. 关键路径长度

7. 渲染页面:浏览器的工作原理

页面内容快速加载和流畅的交互时用户希望得到的Web体验,因此,开发者应力争实现这两个目标

导航 用户通过在地址栏输入一个 URL、点击一个链接、提交表单或者是其他的行为。Web 性能优化的目标之一就是缩短导航完成所花费的时间

DNS查询 对于一个 web 页面来说导航的第一步是要去寻找页面资源的位置。如果导航到 Example Domain,HTML 页面被定位到 IP 地址为 93.184.216.34 的服务器。如果以前没有访问过这个网站,就需要进行 DNS 查询。

TCP握手 一旦获取到服务器 IP 地址,浏览器就会通过 TCP“三次握手” (en-US)与服务器建立连接。这个机制的是用来让两端尝试进行通信——在浏览器和服务器通过上层协议 HTTPS 发送数据之前,可以协商网络 TCP 套接字连接的一些参数。

TLS 协商 为了在 HTTPS 上建立安全连接,另一种握手是必须的。更确切的说是 TLS 协商,它决定了什么密码将会被用来加密通信,验证服务器,在进行真实的数据传输之前建立安全连接。

响应 一旦我们建立了到 web 服务器的连接,浏览器就代表用户发送一个初始的 HTTP GET 请求,对于网站来说,这个请求通常是一个 HTML 文件。一旦服务器收到请求,它将使用相关的响应头和 HTML 的内容进行回复。

TCP 慢启动/14KB 规则 第一个响应数据包是 14KB 大小的。这是慢启动的一部分,慢启动是一种均衡网络连接速度的算法。慢启动逐渐增加发送数据的数量直到达到网络的最大带宽。

拥塞控制 当服务器用 TCP 数据包来发送数据时,客户端通过返回确认帧来确认传输。由于硬件和网络条件,连接的容量是有限的。如果服务器太快地发送太多的包,它们可能会被丢弃。这意味着,将不会有确认帧的返回。服务器把它们当做确认帧丢失。拥塞控制算法使用这个发送包和确认帧流来确定发送速率。

解析 一旦浏览器收到数据的第一块,它就可以开始解析收到的信息。“解析”是浏览器将通过网络接收的数据转换为 DOMCSSOM 的步骤,通过渲染器把 DOM 和 CSSOM 在屏幕上绘制成页面。

构建DOM树 我们描述五个步骤在关键渲染路径这篇文章中。

* **第一步是处理 HTML 标记并构造 DOM 树。**HTML 标记包括开始和结束标记,以及属性名和值。如果文档格式良好,则解析它会简单而快速。 DOM 节点的数量越多,构建 DOM 树所需的时间就越长。

预加载扫描器 浏览器构建 DOM 树时,这个过程占用了主线程。当这种情况发生时,预加载扫描仪将解析可用的内容并请求高优先级资源,如 CSS、JavaScript 和 web 字体。多亏了预加载扫描器,我们不必等到解析器找到对外部资源的引用来请求它。它将在后台检索资源,以便在主 HTML 解析器到达请求的资源时,它们可能已经在运行,或者已经被下载。预加载扫描仪提供的优化减少了阻塞。


<link rel="stylesheet" src="styles.css"/>
<script src="myscript.js" async></script>
<img src="myimage.jpg" alt="image description"/>
<script src="anotherscript.js" async></script>

Copy to Clipboard

在这个例子中,当主线程在解析 HTML 和 CSS 时,预加载扫描器将找到脚本和图像,并开始下载它们。为了确保脚本不会阻塞进程,当 JavaScript 解析和执行顺序不重要时,可以添加 async 属性或 defer 属性。

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

构建CSSOM树

  • 第二步是处理 CSS 并构建 CSSOM 树

CSS 对象模型和 DOM 是相似的。DOM 和 CSSOM 是两棵树。它们是独立的数据结构。浏览器将 CSS 规则转换为可以理解和使用的样式映射。浏览器遍历 CSS 中的每个规则集,根据 CSS 选择器创建具有父、子和兄弟关系的节点树。

其他过程

JavaScript编译当 CSS 被解析并创建 CSSOM 时,其他资源,包括 JavaScript 文件正在下载(借助预加载扫描器)。JavaScript 被解释、编译、解析和执行。脚本被解析为抽象语法树。一些浏览器引擎使用抽象语法树并将其传递到解释器中,输出在主线程上执行的字节码。这就是所谓的 JavaScript 编译。

构建辅助功能树浏览器还构建辅助设备用于分析和解释内容的辅助功能(accessibility)树。无障碍对象模型(AOM)类似于 DOM 的语义版本。当 DOM 更新时,浏览器会更新辅助功能树。辅助技术本身无法修改无障碍树。

在构建 AOM 之前,屏幕阅读器(screen readers (en-US))无法访问内容。

渲染

渲染步骤包括样式、布局、绘制,在某些情况下还包括合成。在解析步骤中创建的 CSSOM 树和 DOM 树组合成一个 Render 树,然后用于计算每个可见元素的布局,然后将其绘制到屏幕上。在某些情况下,可以将内容提升到它们自己的层并进行合成,通过在 GPU 而不是 CPU 上绘制屏幕的一部分来提高性能,从而释放主线程。

Style

* 第三步是将 DOM 和 CSSOM 组合成一个 Render 树,计算样式树或渲染树从 DOM 树的根开始构建,遍历每个可见节点

Layout

  • 第四步是在渲染树上运行布局以计算每个节点的几何体。布局是确定呈现树中所有节点的宽度、高度和位置,以及确定页面上每个对象的大小和位置的过程。 *回流是对页面的任何部分或整个文档的任何后续大小和位置的确定。*构建渲染树后,开始布局。第一次确定节点的大小和位置称为布局。随后对节点大小和位置的重新计算称为回流。

绘制

  • **最后一步是将各个节点绘制到屏幕上,第一次出现的节点称为 first meaningful paint (en-US)。**在绘制或光栅化阶段,浏览器将在布局阶段计算的每个框转换为屏幕上的实际像素。

为了确保平滑滚动和动画,占据主线程的所有内容,包括计算样式,以及回流和绘制,必须让浏览器在 16.67 毫秒内完成。

绘制可以将布局树中的元素分解为多个层。将内容提升到 GPU 上的层(而不是 CPU 上的主线程)可以提高绘制和重新绘制性能。

分层确实可以提高性能,但是它以内存管理为代价,因此不应作为 web 性能优化策略的一部分过度使用。

Compositing

当文档的各个部分以不同的层绘制,相互重叠时,必须进行合成,以确保它们以正确的顺序绘制到屏幕上,并正确显示内容。

交互

一旦主线程绘制页面完成,你会认为我们已经“准备好了”,但事实并非如此。如果加载包含 JavaScript(并且延迟到 onload 事件激发后执行),则主线程可能很忙,无法用于滚动、触摸和其他交互。

Time to Interactive (en-US)(TTI)是测量从第一个请求导致 DNS 查询和 SSL 连接到页面可交互时所用的时间——可交互是 First Contentful Paint (en-US) 之后的时间点,页面在 50ms 内响应用户的交互。如果主线程正在解析、编译和执行 JavaScript,则它不可用,因此无法及时(小于 50ms)响应用户交互。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值