Web 网页性能优化
Web 网页性能及性能优化
一、Web 性能
Web
性能是 Web
开发的一个重要方面,侧重于网页加载速度以及对用户输入的响应速度
通过优化网站来改善性能,可以在为用户提供更好的体验
网页性能既广泛又非常深入
1. 为什么性能这么重要?
1. 性能关乎留住用户
性能对于任何在线业务都至关重要
与加载速度缓慢、让人感觉运行缓慢的网站相比,加载速度快并能及时响应用户输入的网站能更好地吸引并留住用户
2. 性能能提高转化次数
性能会对网站用户是否会浏览应用产生重大影响
3. 性能关乎用户体验
随着网页开始加载,用户会等待一段时间,等待内容显示。在此之前,就谈不上用户体验
快速连接会让这种体验一闪而过。而如果连接速度较慢,用户就不得不等待
性能是打造良好用户体验的基本要素
当网站发送大量代码时,浏览器必须使用用户流量套餐中的兆字节流量下载应用
尤其是移动设备的 CPU
性能和内存有限。这可能会导致糟糕的性能条件,而且考虑到人们了解人类的行为,用户只能容忍网站上的不利条件长达很长的时间,然后才会放弃网站
2. 网页核心指标
2.1. 指标类型:
-
感知加载速度:网页可以多快地加载网页中的所有视觉元素并将其渲染到屏幕上
-
加载响应速度:页面加载和执行组件快速响应用户互动所需的任何
JavaScript
代码的速度 -
运行时响应速度:网页在加载后对用户互动的响应速度
-
视觉稳定性:页面上的元素是否会以用户意想不到的方式发生偏移,是否可能会干扰用户的互动?
-
流畅性:过渡和动画是否以一致的帧速率渲染,并在一种状态之间流畅地流动?
2.2. 要衡量的指标:
-
FCP(First Contentful Paint)
:从网页开始加载到网页内容的任何部分呈现在屏幕上所用的时间 -
LCP(Largest Contentful Paint)
:从网页开始加载到屏幕上呈现最大的文本块或图片元素所用的时间 -
INP(Interaction to Next Paint)
:与网页进行的每次tap
、click
或键盘互动的延迟时间,并根据交互的数量选择页面中最差的交互延迟作为单个代表性值来描述页面的总体响应性 -
TBT(Total Blocking Time)
:从FCP
到可交互时间 (TTI
) 之间的总时长 -
CLS(Cumulative Layout Shift)
:从页面开始加载到其生命周期状态更改为隐藏期间发生的所有意外布局偏移的累计分数 -
TTFB(Time to First Byte)
:网络使用资源的第一个字节响应用户请求所花费的时间 -
FID(First Input Delay)
:用户首次与网页互动(即,点击链接、点按按钮或使用由JavaScript
提供支持的自定义控件)到浏览器实际能够开始处理事件处理脚本以响应相应互动的时间
2.3. Web 页面性能衡量指标-以用户为中心的性能指标
Web
页面性能衡量指标-以用户为中心的性能指标
二、性能优化
1. HTML 页面性能优化
每个网站都是从请求 HTML
文档开始的,该请求对网站的加载速度有着重大影响
要想构建可快速加载的网站,第一步就是要及时从服务器接收网页 HTML
的响应
当在浏览器的地址栏中输入网址时,浏览器会向服务器发送 GET
请求进行检索
网页的第一个请求针对的是 HTML
资源,因此,确保 HTML
以最短延迟快速到达是关键性能目标
1.1. 尽量减少重定向
在请求资源时,服务器可能会做出一个重定向响应,该重定向可以是永久重定向(301 Moved Permanently
响应)或临时重定向(302 Found
响应)
重定向会降低网页加载速度,因为它需要浏览器在新位置发出额外的 HTTP
请求来检索资源。重定向有两种类型:
- 完全发生在源站内的同源重定向。这些类型的重定向完全由项目控制,因为管理它们的逻辑完全位于的
Web
服务器上 - 由其他源启动的跨域重定向。这些类型的重定向通常无法控制
1.2. 缓存 HTML 响应
缓存 HTML
响应很困难,因为响应可能包含指向其他关键资源(例如 CSS
、JavaScript
、图片和其他资源类型)的链接。这些资源的文件名中可能包含唯一指纹,该指纹会根据文件的内容而变化
但是较短的缓存生命周期(而不是不缓存)具有诸多优势:
-
允许在
CDN
中缓存资源,减少从源服务器传送的请求数量 -
在浏览器中传送资源,从而重新验证资源而不是再次下载此
-
可以将缓存资源的适当时间设置为合适的分钟数
缓存 HTML
的一种方法是使用 ETag
或 Last-Modified
响应标头
ETag
(也称为实体标记)标头是一个标识符,用于唯一标识所请求资源,通常使用资源内容的哈希值:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
每当资源发生变化时,都必须生成新的 ETag
值。在后续请求中,浏览器会通过 If-None-Match
请求标头发送 ETag
值。如果服务器上的 ETag
与浏览器发送的 ETag
匹配,服务器会返回 304 Not Modified
响应,浏览器则会使用缓存中的资源。虽然这仍然会导致网络延迟,但 304 Not Modified
响应比整个 HTML
资源小得多
但是,重新验证资源的新鲜度涉及的网络延迟也本身也是一个缺点,需自行决定以这种方式缓存 HTML
的额外工作是否值得,或者最好是谨慎操作,不必费心缓存 HTML
内容。
1.3. 测量服务器响应时间
如果响应未缓存,则服务器的响应时间在很大程度上取决于的托管服务提供商和后端应用堆栈
与动态网页相比,提供动态生成的响应(例如从数据库获取数据)的网页的 TTFB
可能更高,无需在后端投入大量计算时间即可立即提供
1.4. 压缩
基于文本的响应(例如 HTML
、JavaScript
、CSS
和 SVG
图片)应进行压缩,以减小通过网络传输时的大小,从而加快其下载速度。最常用的压缩算法是 gzip
和 Brotli
。Brotli
比 gzip
提高了约 15% 到 20%。
- 尽可能使用
Brotli
,所有主流浏览器都支持Brotli
,但如果网站有大量用户在旧版浏览器中使用,请确保将gzip
用作后备选项,因为任何压缩都比不进行压缩要好。 - 文件大小至关重要。非常小的资源(小于 1
KiB
)压缩得不太好,有时甚至根本压缩不到。任何类型的数据压缩的效果都取决于能够使用压缩算法找到更多可压缩数据位的大量数据。文件越大,压缩效果就越好 - 了解动态压缩和静态压缩。动态压缩和静态压缩是确定何时应压缩资源的不同方法
- 动态压缩会在请求资源时压缩资源,有时甚至在每次请求资源时压缩资源。
- 静态压缩消除了压缩本身涉及的延迟时间,在使用动态压缩的情况下,这可能会增加服务器响应时间。
JavaScript
、CSS
和SVG
图片等静态资源应静态压缩,而HTML
资源应动态压缩。
1.5. CDN
CDN
是分布式服务器网络,服务器从源服务器缓存资源,反过来再从物理上更靠近用户的边缘服务器传送资源。在距离用户较近时,可以缩短往返时间 (RTT
),而 HTTP/2
或 HTTP/3
、缓存和压缩等优化技术则可以让 CDN
更快地提供内容,而不是从源服务器提取内容。在某些情况下,使用 CDN
可以显著改善网站的 TTFB
。
2. 关键渲染路径
关键渲染路径是网页性能中的一个概念。
关键渲染路径是指网页开始在浏览器中呈现之前所涉及的步骤。为了呈现网页,浏览器需要 HTML
文档本身以及呈现该文档所需的所有关键资源。
2.1. 渐进式渲染
网络是自然分布的。与客户端和 APP 不同,浏览器不能依赖于拥有呈现页面所需的所有资源的网站。因此,浏览器非常擅长渐进式呈现页面。原生应用通常有一个安装阶段,然后是运行阶段。然而,对于网页和网络应用来说,这两个阶段之间的界限就不那么明显了。
2.2. 关键渲染路径
浏览器需要知道它应该等待的最小资源数量,以避免呈现明显不正常的体验。
另一方面,浏览器也不应该等待超过必要的时间才向用户显示一些内容。浏览器在执行初始呈现之前所采取的步骤序列称为关键渲染路径。
呈现路径涉及以下步骤:
-
通过
HTML
构建文档对象模型 (DOM
) -
通过
CSS
构建CSS
对象模型 (CSSOM
) -
应用任何会更改
DOM
或CSSOM
的JavaScript
-
通过
DOM
和CSSOM
构建渲染树 -
在页面上执行样式和布局操作,看看哪些元素适合显示
-
在内存中绘制元素的像素
-
如果有任何像素重叠,则合成像素
-
以物理方式将所有生成的像素绘制到屏幕上
只有在完成所有这些步骤后,用户才会在屏幕上看到内容
这一呈现过程会发生多次。初始渲染会调用此流程,但随着更多会影响网页渲染的资源可用,浏览器将会重新运行此流程(或许只是其中的一部分),以更新用户看到的内容。关键渲染路径侧重于之前为初始渲染概述的流程,并依赖于执行初始渲染所需的关键资源
2.3. 关键渲染路径上有哪些资源?
浏览器需要等待一些关键资源下载完毕,然后才能完成初始渲染。这些资源包括:
HTML
的一部分<head>
元素中阻塞渲染的CSS
<head>
元素中的阻塞渲染的JavaScript
关键在于浏览器以流式方式处理 HTML
。浏览器一旦获取网页 HTML
的任何部分,就会开始对其进行处理。然后,浏览器就可以(并且通常确实)决定先呈现网页,然后再接收网页的其余部分 HTML
3. 优化资源加载
网页加载时,其 HTML
中会引用许多资源,通过 CSS
提供网页的外观和布局,并通过 JavaScript
提供互动性。
3.1. 渲染阻塞
CSS
是一种阻塞渲染的资源,因为它会阻止浏览器渲染任何内容,直至构建了 CSS
对象模型 (CSSOM
)。浏览器会阻止呈现,以防止出现非样式内容闪烁 (FOUC
)
渲染阻塞未必是不可取的,但需要通过对 CSS
进行优化来最大限度地缩短其持续时间
3.2. 预加载扫描器
3.2.1. 什么是预加载扫描程序?
预加载扫描程序的角色是推测性,也就是说,它会检查原始标记,以便查找资源,以便在主要 HTML
解析器发现之前抓取相应资源
预加载扫描程序是一种浏览器优化,采用辅助 HTML
解析器的形式,可扫描原始 HTML
响应,以找出并推测性地提取资源,然后主 HTML
解析器才会发现这些资源
为了充分利用预加载扫描器,服务器发送的 HTML
标记中应包含关键资源。预加载扫描器无法发现以下资源加载模式:
- 由
CSS
使用background-image
属性加载的图片。这些图片引用位于CSS
中,预加载扫描器无法发现这些引用 - 动态加载的脚本,采用
<script>
元素标记(使用JavaScript
注入DOM
)或使用动态import()
加载的模块 - 使用
JavaScript
在客户端上呈现的HTML
CSS
@import
声明
这些资源加载模式都是后来发现的资源,请尽可能避免,如果无法避免此类模式,可以使用 preload 提示来避免资源发现延迟
3.3. CSS
CSS
决定了网页的呈现方式和布局,CSS
是一种阻止呈现的资源,因此优化 CSS
可能会对整体网页加载时间产生重大影响
3.3.1. 缩减大小
缩减 CSS
文件大小可缩减 CSS
资源的文件大小,从而缩短下载速度。这主要是通过从 CSS
源文件中移除内容(例如空格和其他不可见字符)并将结果输出到新优化的文件来实现的:
/* Heading 1 */
h1 {font-size: 2em;color: #000000;
}/* Heading 2 */
h2 {font-size: 1.5em;color: #000000;
}
/* Minified CSS: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
就最基本的形式而言,CSS
缩减是一种有效的优化,可以提高网站的 FCP
,在某些情况下或许甚至是 LCP
3.3.2. 移除未使用的 CSS
在呈现任何内容之前,浏览器需要先下载并解析所有样式表。完成解析所需的时间还包括当前网页上未使用的样式。如果使用的打包器将所有 CSS
资源合并到一个文件中,那么的用户下载的 CSS
可能会比呈现当前网页所需的数量多
如需发现当前网页未使用的 CSS
,可以使用 Chrome
开发者工具中的 coverage
移除未使用的 CSS
会产生双重效果:除了缩短下载时间之外,还可以优化渲染树的构建,因为浏览器需要处理的 CSS
规则更少
3.3.3. 避免使用 CSS @import 声明
CSS
中的 @import
声明允许从样式表中导入外部 CSS
资源
可以使用 <link rel="stylesheet">
元素替换 @import
3.3.4. 内嵌关键 CSS
关键 CSS
是指渲染在初始窗口中可见的内容所需的样式。初始窗口的概念有时称为“首屏”。网页上的其余内容将保持未设置样式,而其余的 CSS
将异步加载。
但其缺点是,内嵌大量 CSS
会导致初始 HTML
响应的字节增多。由于 HTML
资源通常无法缓存很长时间(甚至根本无法缓存),因此对于可能在外部样式表中使用同一 CSS
的后续网页,系统不会缓存内联的 CSS
需测试和衡量网页的性能
3.4. JS
加载过多的 JavaScript
可能会导致网页在网页加载期间响应缓慢,甚至可能导致响应速度问题减慢互动速度
3.4.1. 阻止呈现的 JS
加载不带 defer
或 async
属性的 <script>
元素时,浏览器会阻止解析和呈现,直到脚本下载、解析并执行完毕。同样,内联脚本也会阻止解析器,直到解析和执行脚本。
3.4.2. async 与 defer
async
和 defer
允许加载外部脚本,而不会阻止 HTML
解析器,而具有 type="module"
的脚本(包括内嵌脚本)会自动延迟。不过,async
和 defer
之间存在一些差异
- 使用
async
加载的脚本会在下载后立即解析和执行 - 使用
defer
加载的脚本会在 HTML 文档解析完成时执行,这与浏览器的DOMContentLoaded
事件同时发生 async
脚本可能会不按顺序执行defer
脚本则会按照它们在标记中出现的顺序执行
使用 type="module"
属性加载的脚本会处于延迟状态,而使用 JavaScript
将 <script>
标记注入 DOM
中加载的脚本则像 async
脚本
3.4.3. 客户端渲染
应避免使用 JavaScript
来呈现任何关键内容或网页的 LCP
元素。这称为客户端渲染,是一种在单页应用 (SPA
) 中广泛使用的技术
3.4.3.1. LCP 元素
-
<img>
元素(第一帧呈现时间用于GIF
或动画PNG
等动画内容) -
<svg>
元素内的<image>
元素 -
<video>
元素(系统会使用视频的海报图片加载时间或第一帧显示时间,以较早者为准) -
一个元素,带有使用
url()
函数(而不是CSS
渐变)加载的背景图片 -
包含文本节点或其他内嵌级文本元素子元素的块级元素
3.4.4. 缩减大小
与 CSS
类似,缩减 JavaScript
大小可缩减脚本资源的文件大小。 这可以加快下载速度,使浏览器能够更快地继续解析和编译 JavaScript
的过程
缩减 JavaScript
的大小比缩减其他资源更进一步。缩减 JavaScript
的大小时,不仅会去除空格、制表符和注释等内容,而且源 JavaScript
中的符号也会被缩短
// Unuglified JavaScript source code:
export function injectScript () {const scriptElement = document.createElement('script');scriptElement.src = '/js/scripts.js';scriptElement.type = 'module';document.body.appendChild(scriptElement);
}
// Uglified JavaScript production code:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
4. 通过资源提示协助浏览器
资源提示是 HTML
中提供的一系列功能,可以帮助浏览器尽早加载资源,甚至可以采用更高的资源优先级来加载资源
资源提示可以告知浏览器如何加载资源并确定资源优先级,从而帮助开发者进一步缩短网页加载时间。初始资源提示(例如 preconnect
和 dns-prefetch
)是最先引入的资源提示。随着时间的推移,preload
和 Fetch Priority API
相继提供了额外的功能
资源提示会指示浏览器提前执行某些操作,这些操作可以提高加载性能。资源提示可以执行操作,例如执行早期 DNS
查找、提前连接到服务器,甚至在浏览器通常发现资源之前提取资源。
资源提示可以在 HTML
中指定(通常在 <head>
元素早期),也可以设置为 HTTP
标头
4.1. preconnect
preconnect
提示用于与另一个来源(要从其中提取关键资源)建立连接
<link rel="preconnect" href="https://example.com">
使用 preconnect
即表示预计浏览器计划在不久的将来连接到特定的跨源服务器,并且浏览器应尽快打开该连接,最好是在等待 HTML
解析器或预加载扫描程序执行此操作之前打开
如果网页上有大量跨源资源,请对当前网页最至关重要的资源使用 preconnect
preconnect
的常见用例是 Google Fonts
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
crossorigin
属性用于指示是否必须使用跨域资源共享 (CORS
) 提取资源。使用 preconnect
提示时,如果从来源下载的资源使用 CORS
(例如字体文件),则需要将 crossorigin
属性添加到 preconnect
提示中
4.2. dns-prefetch
虽然尽早打开与跨源服务器的连接可以显著缩短初始网页加载时间,但同时与多个跨源服务器建立连接可能不合理或不可行。如果担心可能过度使用了 preconnect
,可以使用 dns-prefetch
提示来使用开销大大降低的资源提示
dns-prefetch
不会与跨源服务器建立连接,而只是提前为其执行 DNS
查找。在将域名解析为其底层 IP
地址时,会发生 DNS
查询
虽然在设备和网络层级设置 DNS
缓存层有助于使此过程从总体上加快,但仍然需要一些时间
<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
DNS
查找的费用相当低廉,并且由于费用相对较小,在某些情况下,它们可能比 preconnect
更适合
4.3. preload
preload
指令用于提前请求呈现网页所需的资源
<link rel="preload" href="/lcp-image.jpg" as="image">
preload
指令应仅限于后期发现的关键资源
最常见的用例包括字体文件、通过 @import
声明提取的 CSS
文件,或可能是 LCP
候选对象的 CSS background-image
资源
如果使用 preload 下载由 <img> 元素指定的图片,该图片会根据用户窗口的不同而有所不同
与 preconnect
类似,如果要预加载 CORS
资源(例如字体),则 preload
指令也需要 crossorigin
属性
如果未添加 crossorigin
属性(或者为非 CORS
请求添加该属性),则浏览器会下载两次资源,浪费带宽,本来可以本该花在其他资源上
<link rel="preload" href="/font.woff2" as="font" crossorigin>
如果 preload
指令的 <link>
元素中缺少 as
属性,该指令中指定的资源会下载两次
4.4. prefetch
prefetch
指令用于针对可能会用于未来导航的资源发起低优先级请求
<link rel="prefetch" href="/next-page.css" as="style">
此指令基本上遵循与 preload
指令相同的格式,只有 <link>
元素的 rel
属性使用 prefetch
值
与 preload
指令不同,prefetch
主要是推测性的
鉴于 prefetch 的推测性,使用它的这一潜在缺点是,如果用户没有转到最终需要预提取资源的页面,那么用于提取资源的数据就可能不会被使用。
4.5. Fetch Priority API
可以通过其 fetchpriority
属性使用 Fetch Priority API
来提高资源的优先级。可以将该属性与 <link>
、<img>
和 <script>
元素一起使用。
<div class="gallery"><div class="poster"><img src="img/poster-1.jpg" fetchpriority="high"></div><div class="thumbnails"><img src="img/thumbnail-2.jpg" fetchpriority="low"><img src="img/thumbnail-3.jpg" fetchpriority="low"><img src="img/thumbnail-4.jpg" fetchpriority="low"></div>
</div>
4.5.1. 值
high
low
auto
4.5.2. 兼容
5. 图片加载性能
图片代表了当今许多网页上传输的大部分数据
图片通常是网络上最庞大且最普遍的资源,在大多数情况下,优化图片意味着通过减少发送的字节数来减少网络时间,但也可以通过传送适合用户设备大小的图片,从而优化发送给用户的字节数
可以使用 <img>
或 <picture>
元素或 CSS background-image
属性将图片添加到网页中
5.1. 图片大小
使用图片资源时,可以执行的第一项优化是以正确的尺寸显示图片
在不考虑其他变量的情况下,在 500 x 500 像素容器中显示的图片的最佳大小为 500 x 500 像素。例如,使用 1000 像素的方形图片意味着图片大小将根据需要翻倍
选择合适的图片大小涉及许多变量,这使得在任何情况下选择适当的图片大小的任务都非常复杂
5.1.1. srcset
<img>
元素支持 srcset
属性,该属性可让指定浏览器可能会使用的可能图片来源的列表
指定的每个图片来源都必须包含图片网址,以及宽度或像素密度描述符
<imgalt="An image"width="500"height="500"src="/image-500.jpg"srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>
5.1.2. sizes
借助 sizes
属性,可以指定一组来源尺寸,其中每个来源尺寸都由媒体条件和值组成
sizes
属性用于描述图片的预期显示尺寸(以 CSS
像素为单位)
与 srcset
宽度描述符结合使用时,浏览器可以选择哪种图片来源最适合用户的设备
<imgalt="An image"width="500"height="500"src="/image-500.jpg"srcset="/image-500.jpg 500w, /image-1000.jpg 1000w, /image-1500.jpg 1500w"sizes="(min-width: 768px) 500px, 100vw"
>
如果没有 sizes
属性,srcset
宽度描述符将不起作用。同样,如果省略 srcset
宽度描述符,sizes
属性也不会执行任何操作
5.2. 文件格式
浏览器支持多种不同的图片文件格式。与 PNG
或 JPEG
相比,新型图片格式(例如 WebP
和 AVIF
)可提供更好的压缩效果,从而缩小图片文件大小,从而缩短下载时间。通过以现代格式提供图片,可以缩短资源的加载时间,从而降低 Largest Contentful Paint (LCP)
速度。
5.2.1. WebP
WebP
是一种受到广泛支持的格式,适用于所有新型浏览器
WebP
的压缩效果通常比 JPEG
、PNG
或 GIF
更好,既能提供有损压缩,也提供无损压缩。即使在使用有损压缩时,WebP
也支持 Alpha
通道透明度,而 JPEG
编解码器没有此功能
5.2.2. AVIF
AVIF
是一种较新的图片格式,虽然没有 WebP
那么广泛支持,但它的跨浏览器支持相当得心应
AVIF
同时支持有损压缩和无损压缩,并且在某些情况下,与 JPEG
相比,测试的节省幅度超过了 50%。AVIF
还提供广色域 (WCG
) 和高动态范围 (HDR
) 功能
5.3. 压缩
涉及图像时,有两种压缩类型:
- 有损压缩
- 无损压缩
5.3.1. 有损压缩
有损压缩的工作原理是通过量化降低图片准确性,并且可能会使用色度子采样舍弃其他颜色信息
有损压缩在噪声和颜色多样的高密度图像上最有效
有损压缩可应用于 JPEG
、WebP
和 AVIF
图片
使用有损压缩时,请务必确认压缩的图片是否符合的质量标准
5.3.2. 无损压缩
无损压缩可以通过在不丢失数据的情况下压缩图片来减小文件大小
无损压缩根据与相邻像素之间的差异来描述像素
无损压缩适用于 GIF
、PNG
、WebP
和 AVIF
图片格式
压缩时,没有适用于所有情况的通用设置。建议的方法是尝试使用不同的压缩级别,直到在图片质量和文件大小之间找到适当的折衷方案为止
5.4. Picture 元素
<picture>
元素可让更灵活地指定多个候选图片
<picture><source type="image/avif" srcset="image.avif"><source type="image/webp" srcset="image.webp"><imgalt="An image"width="500"height="500"src="/image.jpg">
</picture>
当在 <picture>
元素中使用 <source>
元素时,可以添加对 AVIF
和 WebP
图片的支持,但如果浏览器不支持现代格式,则回退到更兼容的旧图片格式
<source>
元素还支持 media
、srcset
和 sizes
属性。与前面的 <img>
示例类似,这些变量会向浏览器指示要在不同窗口上选择哪个图片
<picture><sourcemedia="(min-resolution: 1.5x)"srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"sizes="(min-width: 768px) 500px, 100vw"><imgalt="An image"width="500"height="500"src="/image-500.jpg">
</picture>
窗口宽度(像素) | 1 DPR | 1.5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000.jpg |
480 | 500.jpg | 500.jpg | 1000.jpg | 1500.jpg |
560 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
<picture><sourcemedia="(min-width: 560px) and (min-resolution: 1.5x)"srcset="/image-1000.jpg 1000w, /image-1500.jpg 1500w"sizes="(min-width: 768px) 500px, 100vw"><sourcemedia="(max-width: 560px) and (min-resolution: 1.5x)"srcset="/image-1000-sm.jpg 1000w, /image-1500-sm.jpg 1500w"sizes="(min-width: 768px) 500px, 100vw"><imgalt="An image"width="500"height="500"src="/image-500.jpg">
</picture>
窗口宽度(像素) | 1 DPR | 1.5 DPR | 2 DPR | 3 DPR |
---|---|---|---|---|
320 | 500.jpg | 500.jpg | 500.jpg | 1000-sm.jpg |
480 | 500.jpg | 500.jpg | 1000-sm.jpg | 1500-sm.jpg |
560 | 500.jpg | 1000-sm.jpg | 1000-sm.jpg | 1500-sm.jpg |
1024 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
1920 | 500.jpg | 1000.jpg | 1000.jpg | 1500.jpg |
5.5. 延迟加载
可以使用 loading
属性告知浏览器在图片显示在窗口中时延迟加载图片
让浏览器可以优先使用渲染窗口中已有的关键内容所需的资源
eager
:默认行为,eager
告诉浏览器当处理<img>
标签时立即加载图片lazy
:告诉用户代理推迟图片加载直到浏览器认为其需要立即加载时才去加载
5.6. decoding
decoding
属性会告知浏览器应如何解码图片
async
:会告知浏览器,图片可以异步解码,有可能缩短呈现其他内容的时间sync
:会告知浏览器,同步解码图像,此图片应与其他内容同时呈现auto
:允许浏览器决定什么最适合用户
6. 视频加载性能
图片并不是网络上常见的唯一媒体类型。视频是网页上常用的另一种媒体类型
6.1. 视频源文件
处理媒体文件时,在操作系统中识别的文件(.mp4
、.webm
等)称为容器。一个容器包含一个或多个数据流。在大多数情况下,这是指视频和音频流
可以使用编解码器压缩每个流。例如,video.webm
可以是 WebM
容器,其中包含使用 VP9
压缩的视频流和使用 Vorbis
压缩的音频流
压缩视频文件的一种方法需要使用 FFmpeg
:
ffmpeg -i input.mov output.webm
6.2. 多种形式
使用视频文件时,如果浏览器不支持所有现代格式,那么指定多种格式可以作为后备选项
<video><source src="video.webm" type="video/webm"><source src="video.mp4" type="video/mp4">
</video>
MP4
可用作旧版浏览器的后备方案
6.3. poster 属性
视频的海报图片是使用 <video>
元素上的 poster
属性添加的,该属性会在开始播放前向用户提示视频内容可能是什么:
<video poster="poster.jpg"><source src="video.webm" type="video/webm"><source src="video.mp4" type="video/mp4">
</video>
6.4. 自动播放
autoplay
在必须立即播放时使用
GIF
动画可能会非常大,特别是当它有许多包含复杂细节的帧时。动画 GIF
会消耗数兆字节的数据并不罕见,这会大量消耗带宽,以更好地用于更关键的资源
通常应该避免使用动画图片格式,因为 <video>
等效项对于此类媒体的效率要高得多
具有指定 autoplay
属性的 <video>
元素会立即开始下载,即使这些元素位于初始窗口之外也是如此
通过结合使用 poster
属性与 Intersection Observer API
,可以将页面配置为仅在视频位于窗口内时下载
6.5. preload
可以使用 <video>
元素的 preload
属性来影响为视频资源下载的内容:
- 设置
preload="none"
可告知浏览器不应预加载任何视频内容 - 设置
preload="metadata"
仅提取视频元数据,例如视频时长,可能还有一些其他粗略信息
如果要加载用户需要开始播放的视频,则最好设置 preload="none"
7. 优化网页字体
网络字体是网络上的常用资源
网络字体会影响网页在加载时和呈现时的性能
较大的字体文件可能需要一段时间才能下载完毕,并且会对 First Contentful Paint (FCP)
产生负面影响,而不正确的 font-display
值则可能会导致不必要的布局偏移,进而导致网页的 Cumulative Layout Shift (CLS)
7.1. @font-face
@font-face {font-family: "Open Sans";src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}
上述代码段定义了一个名为 Open Sans
的 font-family
,并告知浏览器在哪里可以找到相应的网页字体资源。为了节省带宽,浏览器在确定当前页面的布局需要网页字体之前,不会下载该字体
7.2. preload
如果的 @font-face
声明是在外部样式表中定义的,浏览器只有在下载该样式表之后才能开始下载这些声明。这使得网络字体资源被延迟发现,但有一些方法可以帮助浏览器更快地发现网络字体
可以使用 preload
指令发起对网页字体资源的提前请求。preload
指令可让网页字体在网页加载初期被检测到,浏览器会立即开始下载这些字体,无需等待样式表完成下载和解析
preload
指令不会等到网页上需要相应字体时再执行
<link rel="preload" as="font" href="/fonts/OpenSans-Regular-webfont.woff2" crossorigin>
请谨慎使用 preload
指令。过度使用 preload
指令可能会中断其他关键资源的带宽
字体属于 CORS
资源,预加载字体时必须指定 crossorigin
属性,即使这些字体是自托管的字体也是如此
7.3. 自行托管网页字体
可以通过自行托管网页字体来消除对第三方连接的需要。在大多数情况下,自托管网络字体比从跨源下载字体更快。如果打算自行托管网页字体,请检查的网站是否使用了内容分发网络 (CDN
)、HTTP/2
或 HTTP/3
,并为网站所需的网页字体设置正确的缓存标头
7.4. 仅使用 WOFF2
WOFF2
获得了广泛的浏览器支持和最佳压缩效果,比 WOFF
高出 30%。文件缩小可加快下载速度。WOFF2
格式通常是现代浏览器实现完全兼容性所需的唯一格式
只有在需要支持旧版浏览器时,才可能需要使用其他格式(例如 WOFF
、EOT
和 TTF
)。 如果不需要支持旧版浏览器,则没有理由依赖 WOFF2
以外的网页字体格式
7.5. 设置网页字体子集
网络字体通常包含各种不同的字形,需要这些字形来表示不同语言中使用的各种字符。如果的网页仅以一种语言(或使用单一字母表)提供内容,可以通过子集内嵌来减小网页字体的大小。此操作通常通过指定数字或 Unicode
码位范围来实现
子集是原始网页字体文件中包含的减少的字形集。例如,的网页可能会提供部分拉丁字符,而不是提供所有字形。根据所需的子集,移除字形可以显著减小字体文件的大小
7.6. 字体渲染
浏览器发现并下载某种网页字体后,就可以进行渲染了。默认情况下,在下载使用网页字体的任何文本之前,浏览器都会阻止其渲染。可以使用 font-display CSS
属性调整浏览器的文本渲染行为,并配置在网页字体完全加载之前应显示(或不显示)哪些文本
7.6.1. block
font-display
的默认值为 block
。使用 block
时,浏览器会阻止呈现使用指定网页字体的任何文本。不同浏览器的行为会略有不同
7.6.2. swap
swap
是使用最广泛的 font-display
值。swap
不会阻止渲染,并且会在交换成指定的网页字体之前立即以后备方式显示文本。这样,就可以立即显示内容,而无需等待网络字体下载完成
7.6.3. fallback
font-display
的 fallback
值在 block
和 swap
之间折衷。与 swap
不同,浏览器会阻止字体渲染,但只能在很短的时间内交换回退文本。不过,与 block
不同的是,阻塞期极短
7.6.4. optional
optional
是最严格的 font-display
值,仅在 100 毫秒内下载时才会使用网页字体资源
如果某种网页字体的加载用时超过该时长,便不会在网页上使用,因此浏览器会使用后备字体进行当前导航,同时在后台下载该网页字体并将其存放在浏览器缓存中
7.6.5. auto
8. 代码拆分 JavaScript
有些资源对网页的初始加载并不重要。JavaScript
就是这样一种资源,可通过称为代码拆分的技术推迟到需要时
这样一来,可以通过减少带宽和 CPU
争用来提高性能,这是提高初始网页加载速度和启动期间的输入响应速度的关键因素
加载大型 JavaScript
资源会显著影响网页速度。将 JavaScript
拆分为较小的区块并仅下载网页在启动期间正常运行所必需的内容,可以极大地提高网页的加载响应能力,进而提高网页的互动到下一次绘制 (INP
)
8.1. 通过代码拆分,减少启动期间的 JavaScript 解析和执行
Lighthouse
会在 JavaScript
执行时间超过 2 秒时发出警告,并在执行时间超过 3.5 秒时失败
在网页生命周期的任何时间点,过度的 JavaScript
解析和执行都是潜在的问题,因为如果用户与网页互动的时间与负责处理和执行 JavaScript
的主线程任务运行的时间一致,则有可能会增加互动的输入延迟时间
可以使用 Chrome
开发者工具中的覆盖率工具(coverage
)进一步确定页面加载期间未使用页面的 JavaScript
的哪些部分。
代码拆分是一项可以减少页面初始 JavaScript
载荷的实用技术。它可让将 JavaScript
软件包拆分为两部分:
- 网页加载时所需的
JavaScript
无法在任何其他时间加载 - 可在稍后时间点加载(最常见的是用户与页面上的指定互动元素互动时)的其余
JavaScript
8.2. import()
可以使用动态 import()
语法完成代码拆分。此语法与在启动期间请求指定 JavaScript
资源的 <script>
元素不同,该语法可在网页生命周期的后期请求 JavaScript
资源
动态 import()
是一种类似于函数的表达式,可让动态加载 JavaScript
模块。 它是一种异步操作,可用于导入模块以响应互动或需要加载其他模块的其他任何条件。动态 import()
与静态import
语句不同,后者会立即导入模块,并且要求父模块及其所有依赖项都得到解析和执行,然后才能运行
document.querySelectorAll('#myForm input').addEventListener('blur', async () => {const { validateForm } = await import('/validate-form.mjs');validateForm();
}, { once: true });
9. 延迟加载 <iframe>元素
<iframe>
元素可能会占用大量带宽和 CPU
处理时间
与其他类型的资源相比,<iframe>
元素消耗的带宽通常更多。对于 <iframe>
元素,加载和渲染其中的页面可能会消耗相当多的额外处理时间
9.1. <iframe> 元素的 loading 属性
所有主流浏览器也都支持 <iframe>
元素上的 loading
属性
loading
属性的值及其行为与使用 loading
属性的 <img>
元素相同:
eager
为默认值lazy
会延迟加载<iframe>
元素的HTML
及其子资源,直到该元素与窗口之间的距离在预定义的距离以内
9.2. JavaScript 延迟加载
使用 Intersection Observer API
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Lazy Load Images</title><style>.spacer {height: 100vh;}.lazy {width: 100%;height: auto;display: block;}</style>
</head>
<body><div class="spacer"></div><img class="lazy" data-src="https://via.placeholder.com/600x400" alt="Lazy Image 1"><div class="spacer"></div><img class="lazy" data-src="https://via.placeholder.com/600x400" alt="Lazy Image 2"><div class="spacer"></div><img class="lazy" data-src="https://via.placeholder.com/600x400" alt="Lazy Image 3"><div class="spacer"></div>
</body>
</html>
<script>
// 回调函数,当目标元素的可见性发生变化时调用
const lazyLoad = (entries, observer) => {entries.forEach(entry => {if (entry.isIntersecting) {const img = entry.target;img.src = img.getAttribute('data-src');img.onload = () => img.removeAttribute('data-src');observer.unobserve(img);}});
};// IntersectionObserver 配置
const options = {root: null, // 默认是窗口rootMargin: '0px',threshold: 0.1 // 目标元素进入窗口 10% 时触发回调
};// 创建 IntersectionObserver 实例
const observer = new IntersectionObserver(lazyLoad, options);
// 观察所有具有 'lazy' 类的图片
document.querySelectorAll('img.lazy').forEach(img => observer.observe(img));
</script>
-
root
:用作窗口的元素,用于检查目标的可见性,如果未指定或为 null,则默认为浏览器窗口。 -
rootMargin
:根周围的边距 -
threshold
:一个数字或一个数字数组,表示目标可见度达到多少百分比时,观察器的回调就应该执行。如果只想在能见度超过 50% 时检测,可以使用 0.5 的值。如果希望每次能见度超过 25% 时都执行回调,则需要指定数组 [0, 0.25, 0.5, 0.75, 1]。默认值为 0(这意味着只要有一个像素可见,回调就会运行)。值为 1.0 意味着在每个像素都可见之前,阈值不会被认为已通过。
10. 预提取、预渲染和 Service Worker 预缓存
虽然许多性能涉及到可以采取哪些措施来优化和消除不必要的资源,但建议先加载一些资源才是需要用到的,这似乎有点自相矛盾。不过,在某些情况下,可以提前加载某些资源
10.1. prefetch
可以使用 <link rel="prefetch">
资源提示提前提取资源(包括图片、样式表或 JavaScript
资源)。prefetch
提示用于告知浏览器在不久的将来可能需要某个资源
指定 prefetch
提示后,浏览器可能会以最低优先级发起对该资源的请求,以避免与当前页面所需的资源发生争用
预提取资源可以改善用户体验,因为用户无需等待近期所需的资源下载完毕,因为可以在需要时立即从磁盘缓存中检索这些资源
<head><link rel="prefetch" as="script" href="/date-picker.js"><link rel="prefetch" as="style" href="/date-picker.css">
</head>
还可以通过在指向某个 HTML
文档时指定 as="document"
属性来预提取网页及其所有子资源
<link rel="prefetch" href="/page" as="document">
在基于 Chromium
的浏览器中,可以使用 Speculation Rules API
预提取文档。推测规则定义为包含在网页的 HTML
中的 JSON
对象,或通过 JavaScript
动态添加:
<script type="speculationrules">
{"prefetch": [{"source": "list","urls": ["/page-a", "/page-b"]}]
}
</script>
10.2. prerender
除了预提取资源之外,还可以提示浏览器在用户导航到某个网页之前预呈现该网页
这种做法几乎可以即时加载网页,因为系统会在后台提取和处理网页及其资源。当用户导航到相应页面后,系统会将该页面置于前台
Speculation Rules API
支持预渲染:
<script type="speculationrules">
{"prerender": [{"source": "list","urls": ["/page-a", "page-b"]}]
}
</script>
10.3. Service Worker 预缓存
还可以使用 Service Worker
推测性地预提取资源
Service Worker
预缓存可以使用 CacheAPI
提取和保存资源,这样浏览器无需访问网络即可使用 Cache API
处理请求
Service Worker
预缓存使用一种非常有效的 Service Worker
缓存策略,称为“仅缓存”策略。这种模式非常有效,因为将资源放入 Service Worker
缓存后,可在收到请求时几乎即时提取这些资源
如需使用 Service Worker
预缓存资源,可以使用 Workbox
Workbox
使用预缓存清单来确定应预缓存的资源,预缓存清单是一个文件和版本控制信息列表,可作为要预缓存的资源的可信来源
[{url: 'script.ffaa4455.js',revision: null
}, {url: '/index.html',revision: '518747aa'
}]
上述代码是一个示例清单,其中包含 script.ffaa4455.js
和 /index.html
这两个文件。如果资源在文件本身中包含版本信息(称为文件哈希),则 revision
属性可以保留为 null
,因为文件已进行版本控制(例如,上述代码中 script.ffaa4455.js
资源的 ffaa4455
属性)。
设置后,Service Worker
可用于预缓存静态页面或其子资源,以加快后续页面导航的速度
workbox.precaching.precacheAndRoute(['/styles/product-page.ac29.css','/styles/product-page.39a1.js',
]);
Service Worker
使用的 Cache
接口和 HTTP
缓存并不相同
Cache
接口是由 JavaScript
控制的高层级缓存,而 HTTP
缓存是由 Cache-Control
标头控制的低层级缓存
与使用资源提示或推测规则预提取或预呈现资源类似,Service Worker
预缓存会消耗网络带宽、存储空间和 CPU
建议仅预缓存可能会使用的资源,并在预缓存清单中指定过多的资源
11. Web Worker
用户在浏览器中看到的大部分内容都在称为主线程的单个线程上完成。不过,在某些情况下,可以启动新线程来执行计算开销很大的工作,以便主线程可以处理面向用户的重要任务。执行此操作的 API
称为 Web Worker API
JavaScript
通常被描述为一种单线程语言。这是指主线程,这是浏览器执行在浏览器中看到的大部分工作的单个线程。其中包括编写脚本、某些类型的渲染工作、HTML
和 CSS
解析以及其他类型的面向用户的工作来改善用户体验等
就 JavaScript
而言,通常只能在主线程上执行工作,但可以在 JavaScript
中注册和使用其他线程。允许在 JavaScript
中实现多线程的功能称为 Web Workers API
11.1. Web Worker 启动方式
实例化 Worker
类
const myWebWorker = new Worker('/my-web-worker.js');
11.2. Web Worker 的限制
与在主线程上运行的 JavaScript
不同,Web Worker
无法直接访问 window上下文
,并且对其提供的 API
的访问受到限制。Web Worker
受到以下限制条件的约束:
Web Worker
无法直接访问DOM
Web Worker
可以通过消息传递流水线与window
上下文进行通信,这意味着Web Worker
可以通过某种方式间接访问DOM
Web Worker
的作用域是self
,而不是window
Web Worker
范围_确实_可以访问JavaScript
基元和构造,以及fetch
等API
和相当多的其他API
11.3. Web Worker 如何与 window 通信
Web Worker
可以通过消息传递流水线与主线程的 window
上下文进行通信。利用此流水线,可以将数据传送到主线程和 Web
工作器以及从主线程和 Web
工作器传输数据。如需将数据从 Web Worker
发送到主线程,需要在 Web Worker
的上下文 (self
) 中设置 message
事件
// my-web-worker.js
self.addEventListener("message", () => {// Sends a message of "Hellow, window!" from the web worker:self.postMessage("Hello, window!");
});
然后,在主线程上 window
上下文的脚本中,可以使用另一个 message
事件接收来自网页工作器线程的消息:
// scripts.js
// Creates the web worker:
const myWebWorker = new Worker('/js/my-web-worker.js');
// Adds an event listener on the web worker instance that listens for messages:
myWebWorker.addEventListener("message", ({ data }) => {// Echoes "Hello, window!" to the console from the worker.console.log(data);
});
三、总结
- 本文概述了性能以及性能的重要性
- 罗列了性能优化的点
- 希望对大家有帮助
引用
- performance
- web performance
相关文章:
Web 网页性能优化
Web 网页性能及性能优化 一、Web 性能 Web 性能是 Web 开发的一个重要方面,侧重于网页加载速度以及对用户输入的响应速度 通过优化网站来改善性能,可以在为用户提供更好的体验 网页性能既广泛又非常深入 1. 为什么性能这么重要? 1. 性能…...
JDBC-MySQL
JDBC-MySQL 1.JDBC 操作步骤1.1 DriverManager1.2.Connection对象1.3 Statement1.4 PreparedStatement 1.JDBC 操作步骤 public void quickStart() throws ClassNotFoundException, SQLException {//1、注册驱动 (确认要使用哪个数据库)Class.forName(&…...
MySQL经典练习50题(上)(解析版)
所有笔记、生活分享首发于个人博客 想要获得最佳的阅读体验(无广告且清爽),请访问本篇笔记 MySQL经典练习50题(上) 创建数据库和表 -- 建 表 -- 学 生 表 CREATE TABLE Student( s_id VARCHAR(20), s_name VARCHAR(2…...
每日一题33:数据统计之广告效果
一、每日一题 返回结果示例如下: 示例 1: 输入: Ads 表: ------------------------- | ad_id | user_id | action | ------------------------- | 1 | 1 | Clicked | | 2 | 2 | Clicked | | 3 | 3 | Viewed…...
52、有边数限制的最短路
有边数限制的最短路 题目描述 给定一个n个点m条边的有向图,图中可能存在重边和自环, 边权可能为负数。 请你求出从1号点到n号点的最多经过k条边的最短距离,如果无法从1号点走到n号点,输出impossible。 注意:图中可…...
Spring boot实现基于注解的aop面向切面编程
Spring boot实现基于注解的aop面向切面编程 背景 从最开始使用Spring,AOP和IOC的理念就深入我心。正好,我需要写一个基于注解的AOP,被这个注解修饰的参数和属性,就会被拿到参数并校验参数。 一,引入依赖 当前sprin…...
MySQL之查询性能优化(四)
查询性能优化 MySQL客户端/服务器通信协议 一般来说,不需要去理解MySQL通信协议的内部实现细节,只需要大致理解通信协议是如何工作的。MySQL客户端和服务器之间的通信协议是"半双工"的,这意味着,在任何一个时刻&#…...
定时任务详解
文章目录 定时任务详解JDK自带第三方任务调度框架java有哪些定时任务的框架为什么需要定时任务定时任务扫表的方案有什么缺点Quartzxxl-jobxxl-job详解 elastic-job 定时任务详解 在定时任务中,操作系统或应用程序会利用计时器或定时器来定期检查当前时间是否达到了…...
OnlyOffice DocumentServer 8.0.1编译破解版本(¥100)
OnlyOffice DocumentServer 8.0.1编译破解版本(¥100) 破解20人数限制 更换中文字体 修改源码,根据业务自定义服务 根据源码在本机启动项目,便于开发 将编译好的服务打包docker镜像运行 提供各种docker镜像包&…...
Android 应用权限
文章目录 权限声明uses-permissionpermissionpermission-grouppermission-tree其他uses-feature 权限配置 权限声明 Android权限在AndroidManifest.xml中声明,<permission>、 <permission-group> 、<permission-tree> 和<uses-permission>…...
MATLAB 匿名函数
定义匿名函数定义匿名函数的基本语法如下:示例示例 1:简单数学运算示例 2:字符串操作示例 3:作为参数传递 匿名函数的高级用法使用函数句柄定义多输出函数使用局部变量使用嵌套匿名函数 注意事项 匿名函数( Anonymous…...
Java 新手入门:基础知识点一览
Java 新手入门:基础知识点一览 想要踏入 Java 的编程世界?别担心,这篇文章将用简单易懂的表格形式,带你快速了解 Java 的基础知识点。 一、Java 是什么? 概念解释Java一种面向对象的编程语言,拥有跨平台、…...
三维模型轻量化工具:手工模型、BIM、倾斜摄影等皆可用!
老子云是全球领先的数字孪生引擎技术及服务提供商,它专注于让一切3D模型在全网多端轻量化处理与展示,为行业数字化转型升级与数字孪生应用提供成套的3D可视化技术、产品与服务。 老子云是全球领先的数字孪生引擎技术及服务提供商,它专注于让…...
小程序CI/CD之自动化打包预览并钉钉通知发布进程
小程序打包方式分为两种:手动打包、自动打包 那如何实现 自动打包 呐?我们今天就来聊一聊! 首先,很重要,看 官方文档 这里提到今天我们要聊的“主角” miniprogram-ci miniprogram-ci 是从微信开发者工具中抽离的关于…...
C++使用QtHttpServer开发服务端Server的Http POST接口和客户端Client示例
Client HTTP POST 假设http://127.0.0.1:8888/post/是一个能够接受POST请求的路径,我们想要向它提交一段json数据,用Qt可以这样实现: Suppose we want to make an HTTP POST with json body to http://127.0.0.1:8888/post/. QCoreApplica…...
计算机基础(8)——音频数字化(模电与数电)
💗计算机基础系列文章💗 👉🍀计算机基础(1)——计算机的发展史🍀👉🍀计算机基础(2)——冯诺依曼体系结构🍀👉ἴ…...
手搓单链表(无哨兵位)(C语言)
目录 SLT.h SLT.c SLTtest.c 测试示例 单链表优劣分析 SLT.h #pragma once#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef int SLTDataType;typedef struct SListNode {SLTDataType data;struct SListNode* next; }SLTNode;//打印…...
代码随想录算法训练营第18天|二叉树
513. 找树左下角的值 最左边的结点的特性 1.只能是叶子结点, 2.必须考虑是最底层,所以要考虑树的深度 3.同样的深度考虑左子树 考虑迭代法,层序遍历 递归优点难搞的 /*** Definition for a binary tree node.* function TreeNode(val, left, righ…...
使用tftpd更新开发板内核
我们升级内核可以通过原厂提供的升级软件来进行,比如瑞芯微的RKDevTool.exe,只不过这种方式必须通过指定的OTG升级口,还得借助按键进入loader模式后才可以。 其实还可以利用一些通用的工具来进行升级,比如tftpd工具。 下载地址p…...
MySQL数据库整体知识点简述
目录 第一章:数据库系统概述 第二章:信息与数据模型 第3章 关系模型与关系规范化理论 第四章——数据库设计方法 第六-七章——MySQL存储引擎与数据库操作管理 第九章——索引 第10章——视图 第11章——MySQL存储过程与函数 第12章——MySQL 触…...
深入理解MySQL索引下推优化
在MySQL中,索引的使用对于查询性能至关重要。然而,即使有合适的索引,有时查询性能仍然不尽如人意。索引下推(Index Condition Pushdown,ICP)是一项能够进一步优化查询性能的技术。本文将详细讲解索引下推的…...
论文降重技巧:AI工具如何助力论文原创性提升?
论文降重一直是困扰各界毕业生的“拦路虎”,还不容易熬过修改的苦,又要迎来降重的痛。 其实想要给论文降重达标,我有一些独家秘诀。话不多说直接上干货! 1、同义词改写(针对整段整句重复) 这是最靠谱也是…...
el-date-picker的使用,及解决切换type时面板样式错乱问题
这里选择器的类型可以选择日月年和时间范围,根据类型不同,el-date-picker的面板也展示不同,但是会出现el-date-picker错位,或者面板位置和层级等问题。 源代码: <el-selectv-model"dateType"placeholder&…...
Flutter 中的 ToggleButtonsTheme 小部件:全面指南
Flutter 中的 ToggleButtonsTheme 小部件:全面指南 Flutter,作为由 Google 开发的跨平台 UI 框架,为开发者提供了丰富的组件来构建现代化的应用程序。ToggleButtons 是 Material Design 组件库中的一个组件,它允许用户从一组选项…...
新手教程之使用LLaMa-Factory微调LLaMa3
文章目录 为什么要用LLaMa-Factory什么是LLaMa-FactoryLLaMa-Factory环境搭建微调LLaMA3参考博文 为什么要用LLaMa-Factory 如果你尝试过微调大模型,你就会知道,大模型的环境配置是非常繁琐的,需要安装大量的第三方库和依赖,甚至…...
Java函数笔记
1. Statement.executeQuery 和 Statement.executeUpdate 作用: 用于执行SQL查询和更新操作。 问题: 容易导致SQL注入攻击。 解决方法: 使用PreparedStatement进行参数化查询。 // 不安全的做法 Statement stmt connection.createStat…...
Maven实战: 从工程创建自定义archetype
在上一节中(创建自定义archetype)我们手动创建了一个项目模板,经过5步能创建出一个项目模板,如果我有一个现成的项目,想用这个项目作为模板来生成其他项目呢?Maven提供了基于项目生成archetype模板的能力,我们分3步来讲…...
初识JAVA中的包装类,时间复杂度及空间复杂度
目录: 一.包装类 二.时间复杂度 三.空间复杂度 一.包装类: 在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java 给每个基本类型都对应了一个包装类型。 1 基本数据类型和对应的包装类 &am…...
RapidMiner如何利用Hugging Face中的模型实现更有趣的事
RapidMiner Studio最新发布的功能更新,重点是嵌入Hugging Face和Open AI,Hugging face中含有大量的可用模型,包含翻译、总结、文本生成等等强大的模型,Open AI更不必说了,生成界的鼻祖。那么今天主要介绍一下RapidMine…...
Vue3 自定义Hooks函数的封装
1、如何理解vue3中的自定义hooks 在Vue 3中,自定义hooks允许开发者封装和重用逻辑代码。自定义hooks是使用Composition API时创建的函数,这些函数可以包含任意的组合逻辑,并且可以在多个组件之间共享。 自定义hooks通常遵循这样的命名约定&…...
java企业网站源码/百度图片识别
某电商平台公布的5月份热销手机排名显示,苹果的iPhone12、iPhone11霸占热销榜前两名,安卓手机的销量均落后于iPhone,而iPhone11仅是一款4G手机,显示出安卓手机即使支持5G也无法与苹果抗衡。某电商的这份数据显示,5月份…...
wordpress做css/ui培训
意甲冠军: 给k(1<k<10^15),先询问k 大只包含数字5和6的数目是多少 实例 1那是,5 ,3那是,55 。4那是,56 思考: 首先,我们可以找到。有许多2这是头号,有两个数字4个月…...
建怎样的网站挣钱快/seo综合查询软件排名
前言 不收费,也不需要下载任何工具,web项目就能打包成APP,支持在线和离线,APP名称、LOGO、横竖屏、启动页、引导页等都可以自己设置,非常灵活,并且可以上架到应用市场。 操作指南 1.创建应用 注册中控易动…...
java 网站开发实例/自动点击器软件
作者/Simba IBM资深商业分析师。 IT老兵。 终生学习者。 欢迎回来,本篇从一个基本概念——留存谈起。面试的时候“留存”也是大概率会被问到的一个问题,如果想确认自己的回答怎么样,我们一起探讨一下。本文约4000字,读完需要10…...
腾讯有服务器如何做网站/江苏搜索引擎优化公司
2019独角兽企业重金招聘Python工程师标准>>> 1.用composer安装toplan/laravel-sms composer require toplan/laravel 2.在config/app.php文件中修改别名 3.生成两个文件或者从其他项目拿过来 拿过来也行: 4.控制器引入 use PHPMailer\PHPMailer\PHPMaile…...
东莞网站建设58/百度框架户开户渠道
1:继承的定义: Java继承是面向对象的最显著的一个特征。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。 2:关键字: extends :继承 3:格式形…...