1.提升HTML性能的注意事项
1.1尽量减少重定向
重定向会降低网页加载速度,因为浏览器需要在新位置发出额外的HTTP请求才能完成检索资源。
有两种重定向:
- 来源内发生的同源重定向,由自己控制
- 由其他来源发起的跨源重定向,不受控制(广告、网址缩短服务和其他第三方服务经常使用跨源重定向)
多次重定向例子:广告链接到 HTTP 网页,而该网页又重定向到其 HTTPS 等效网页;或者跨源重定向到达服务器来源,但随后触发同源重定向。
1.2缓存HTML响应
缓存的好处:
- 允许在 CDN 中缓存资源(从而减少从源服务器提供服务的请求数量)
- 在浏览器中允许重新验证资源,而不是再次下载资源
HTML 缓存方法是使用 ETag 或 Last-Modified 响应标头
每当资源发生更改时,都必须生成新的 ETag 值。在后续请求中,浏览器会通过 If-None-Match 请求标头发送 ETag 值。如果服务器上的 ETag 与浏览器发送的 ETag 一致,服务器会返回 304 Not Modified 响应,浏览器会使用缓存中的资源。
1.3衡量服务器响应时间
如果用户在实际环境中遇到 TTFB 缓慢的问题,您可以使用 Server-Timing 响应标头来公开有关服务器上花费的时间的信息:
arduino
Server-Timing: auth;dur=55.5, db;dur=220
使用 Navigation Timing API 从实际用户那里收集这些数据,并进行分析以了解用户是否遇到延迟。Navigation Timing API 是浏览器提供的一套标准接口,专门用来精准测量网页从点击链接到加载完成的全过程耗时。
Navigation Timing API 核心流程与指标
当你输入 URL 并按下回车,浏览器会经历一系列复杂的步骤。Navigation Timing API 记录了每一个关键节点的时间戳(以毫秒为单位):
这些时间点按照发生的先后顺序排列:
navigationStart: 整个导航流程的起点。redirectStart / End: 如果发生了重定向,记录重定向的起止时间。fetchStart: 浏览器准备好通过 HTTP 请求去获取文档的时间点。domainLookupStart / End: DNS 查询的起止时间。connectStart / End: TCP 连接建立的时间(如果是 HTTPS,还包括 SSL 握手时间)。requestStart / responseEnd: 请求发出去到服务器返回最后一个字节的时间。domInteractive: 浏览器解析完 HTML 结构,DOM 树构建完成的时间点。loadEventEnd: 页面及其所有资源(图片、脚本)全部加载完成的时间点。
1.4压缩
HTML、JavaScript、CSS 和 SVG 图片等基于文本的响应应进行压缩,以减小其通过网络传输的大小,从而更快地下载。最常用的压缩算法是 gzip 和 Brotli。Brotli 比 gzip 提高了大约 15% 到 20%。
大多数网站托管会自动设置压缩,如果可以自行配置,可以考虑以下步骤:
- 尽可能使用 Brotli,务必使用 gzip 作为后备方案
- **文件大小很重要。**非常小的资源(小于 1 KiB)压缩效果不佳,有时甚至根本无法压缩。文件越大,压缩效果越好;不过,大型资源(例如 JavaScript 和 CSS)在浏览器解压缩后,需要花费更多时间进行解析和评估
- 了解动态压缩与静态压缩。动态压缩和静态压缩是两种不同的方法,用于确定何时 应压缩资源。动态压缩会在请求资源时 压缩资源,有时也会在每次请求资源时压缩资源。另一方面,静态压缩会提前压缩文件,因此在发出请求时无需执行压缩。静态压缩消除了压缩本身带来的延迟,而动态压缩可能会增加服务器响应时间。JavaScript、CSS 和 SVG 图片等静态资源应进行静态压缩,而 HTML 资源(尤其是为已通过身份验证的用户动态生成的 HTML 资源)应进行动态压缩。
1.5内容分发网络CDN
CDN是一个分布式服务器网络,可缓存源服务器中的资源,然后通过离用户更近的边缘服务器提供这些资源。由于地理位置上更靠近用户,因此可缩短往返时间 (RTT),而 HTTP/2 或 HTTP/3、缓存和压缩等优化措施可让 CDN 比从源服务器提取内容更快地传送内容。
2.了解关键路径
关键渲染路径是指网页开始在浏览器中渲染之前所涉及的步骤,也就是输入HTML到页面渲染的步骤。
2.1渐进式渲染
在使用前安装的原生应用不同,浏览器无法依赖于网站是否具有呈现网页所需的所有资源。因此,浏览器非常擅长以渐进的方式呈现网页。
了解关键渲染路径有助于提高 Web 性能,因为这样可以确保不会过度阻塞初始网页渲染。
2.2关键渲染路径
渲染路径包括以下步骤:
- 从 HTML 构建文档对象模型 (DOM)。
- 从 CSS 构建 CSS 对象模型 (CSSOM)。
- 应用会更改 DOM 或 CSSOM 的任何 JavaScript。
- 从 DOM 和 CSSOM 构建渲染树。
- 在页面上执行样式和布局操作,以查看哪些元素适合放置在哪里。
- 绘制内存中元素的像素。
- 如果像素有重叠,则合成像素。
- 将所有生成的像素实际绘制到屏幕上。

2.2.1关键渲染路径上的资源
浏览器需要等待一些关键资源下载完毕,才能完成初始渲染。这些资源包括:
- HTML 的一部分。
<head>元素中存在阻塞渲染的 CSS。<head>元素中会阻塞渲染的 JavaScript。
浏览器通常会将字体和图片视为在后续网页重新呈现期间填充的内容,因此它们无需延迟初始呈现。
如果未为某些类型的内容预留足够的空间(尤其是在 HTML 中未提供图片尺寸的情况下),则当这些内容稍后加载时,网页的布局可能会发生变化。用户体验的这一方面可通过 Cumulative Layout Shift (CLS) 指标衡量。
2.2.2会阻塞渲染的资源
某些资源被视为非常重要,因此浏览器会暂停网页呈现,直到处理完这些资源。CSS 默认属于此类别。
当浏览器看到 CSS(无论是 <style> 元素中的内嵌 CSS,还是 <link rel=stylesheet href="..."> 元素指定的外部引用资源)时,都会避免在下载并处理该 CSS 之前渲染任何其他内容。CSS 是一种会阻止渲染的资源,因为它会阻止浏览器渲染任何内容,直到构建 CSS 对象模型 (CSSOM) 为止
资源阻止呈现并不一定意味着它会阻止浏览器执行任何其他操作。浏览器会尽可能提高效率,因此当浏览器发现需要下载 CSS 资源时,会请求该资源并暂停呈现 ,但仍会继续处理 HTML 的其余部分,并在此期间寻找其他工作。
2.2.3识别阻塞资源
许多性能审核工具都可以识别渲染和解析阻塞资源。包括WebPageTest和Lighthouse。
只有在资源确实延迟了网页呈现时Lighthouse才会突出显示
上图显示了CSS资源阻塞了FCP。建议将关键的 js/css 内联加载,并将所有非关键的 js/样式延迟加载。
3.优化资源加载
3.1渲染阻塞
浏览器会阻止渲染,以防止出现无样式内容闪烁(FOUC)。就是用户先看到无样式的文本内容,然后CSS加载完毕后渲染出新的样式。
渲染阻塞不一定是不良的,但应通过优化 CSS 来尽可能缩短其持续时间。
3.2解析器阻塞
不含 async 或 defer 属性的 <script> 元素会中断HTML解析器。当解析器遇到 <script> 元素时,浏览器需要先评估并执行脚本,然后再继续解析其余的 HTML。这是有意为之,因为脚本可能会在 DOM 仍在构建期间修改或访问 DOM。
使用外部 JavaScript 文件(不含 async 或 defer)时,解析器会从发现文件时起一直被阻塞,直到文件下载、解析和执行完毕。使用内嵌 JavaScript 时,解析器也会被阻塞,直到内嵌脚本被解析和执行。
会阻塞解析器的 <script> 还必须等待任何正在传输的会阻塞渲染的 CSS 资源到达并被解析,然后浏览器才能执行它。这也是有意为之,因为脚本可能会访问在渲染阻塞样式表中声明的样式(例如,通过使用 element.getComputedStyle() )。
3.3预加载扫描器
是一种浏览器优化功能,以辅助 HTML 解析器的形式存在,用于扫描原始 HTML 响应,以在主 HTML 解析器发现资源之前找到并推测性地提取资源。例如,即使 HTML 解析器在提取和处理 CSS 和 JavaScript 等资源时被阻塞,预加载扫描程序也会允许浏览器开始下载 <img> 元素中指定的资源。
预加载扫描器无法发现以下资源加载模式:
- 通过 CSS 使用
background-image属性加载的图片。这些图片引用位于 CSS 中,无法被预加载扫描器发现。 - 以
<script>元素标记形式注入到 DOM 中的动态加载脚本(使用 JavaScript 或通过 dynamicimport()加载的模块)。 - 使用 JavaScript 在客户端上呈现的 HTML。此类标记包含在 JavaScript 资源中的字符串内,无法被预加载扫描器发现。
- CSS
@import声明。
3.4优化CSS
3.4.1缩小
缩减 CSS 文件大小可减小 CSS 资源的体积,从而加快下载速度。这主要是通过从源 CSS 文件中移除空格和其他不可见字符等内容,并将结果输出到新优化的文件中来实现的:
css
/* 缩小前: */
/* Heading 1 */
h1 {
font-size: 2em;
color: #000000;
}
/* Heading 2 */
h2 {
font-size: 1.5em;
color: #000000;
}
/* 缩小后: */
h1,h2{color:#000}h1{font-size:2em}h2{font-size:1.5em}
3.4.2移除未使用的CSS
在渲染任何内容之前,浏览器需要下载并解析所有样式表。
如果您使用的打包器会将所有 CSS 资源合并到一个文件中,那么您的用户下载的 CSS 可能比渲染当前页面所需的 CSS 多。
如需发现当前网页中未使用的 CSS,可以使用 Chrome 开发者工具中的覆盖率工具。

移除未使用的 CSS 有两点好处:除了缩短下载时间之外,还可以优化渲染树的构建,因为浏览器需要处理的 CSS 规则更少。
3.4.3避免使用 CSS @import 声明
与 HTML 中的 <link> 元素类似,CSS 中的 @import 声明可以从样式表中导入外部 CSS 资源。这两种方法的主要区别在于,HTML <link> 元素是 HTML 响应的一部分,因此比通过 @import 声明下载的 CSS 文件更早被发现。
为了发现 @import 声明,必须先下载 包含该声明的 CSS 文件。这会导致所谓的"请求链",在 CSS 的情况下,这会延迟网页的初始渲染时间。另一个缺点是,使用 @import 声明加载的样式表无法被预加载扫描器发现,因此会成为后期发现的阻塞渲染的资源。
arduino
/* 最好不要这样写: */
@import url('style.css');
/* 在HTML里改成这样: */
<link rel="stylesheet" href="style.css">
<link> 元素允许并发下载样式表,从而缩短总体加载时间,而 @import 声明则会连续下载样式表。
3.4.4内嵌关键 CSS
在文档中内嵌关键样式 <head> 可消除对 CSS 资源的网络请求,并且在用户浏览器缓存未预先填充的情况下,如果操作正确,可以缩短初始加载时间。其余 CSS 可以异步加载,也可以附加到 <body> 元素的末尾。
但是内嵌CSS会导致初试HTML响应的字节数。
3.5优化JavaScript
加载不含 defer 或 async 属性的 <script> 元素时,浏览器会阻止解析和渲染,直到脚本下载、解析和执行完毕。同样,内嵌脚本会阻塞解析器,直到脚本被解析和执行。
3.5.1客户端渲染
由 JavaScript 呈现的标记会绕过预加载扫描器,因为客户端呈现的标记中包含的资源无法被该扫描器发现。这可能会延迟关键资源(例如 LCP 图片)的下载。浏览器仅在脚本执行完毕并将元素添加到 DOM 后才开始下载 LCP 图片。反过来,脚本只有在被发现、下载和解析后才能执行。这称为"关键请求链",应避免出现这种情况。
3.5.1缩小
JavaScript 的缩减比其他资源(例如 CSS)的缩减更进一步。JavaScript 经过精简后,不仅会去除空格、制表符和注释等内容,还会缩短源 JavaScript 中的符号。此过程有时称为"丑化"(uglification)。
javascript
// 压缩前:
export function injectScript () {
const scriptElement = document.createElement('script');
scriptElement.src = '/js/scripts.js';
scriptElement.type = 'module';
document.body.appendChild(scriptElement);
}
// 压缩后:
export function injectScript(){const t=document.createElement("script");t.src="/js/scripts.js",t.type="module",document.body.appendChild(t)}
4.资源提示优化
资源提示可告知浏览器如何加载和确定资源优先级,指示浏览器提前执行某些操作,从而提高加载性能,优化网页加载时间。例如提前执行 DNS 查找、提前连接到服务器,甚至在浏览器通常会发现资源之前就获取资源。
4.1preconnect
preconnect 提示用于建立与另一个来源的连接,可以从该来源提取关键资源。例如,在 CDN 或其他跨源上托管图片或资源:
ini
<link rel="preconnect" href="<https://example.com>">
如果页面上有大量的跨域资源,可以使用**preconnect**。常见用例是字体资源。
ini
<link rel="preconnect" href="<https://fonts.googleapis.com>">
<link rel="preconnect" href="<https://fonts.gstatic.com>" crossorigin>
如果资源是跨域并且不添加**crossorigin** 属性,则下载字体是会打开新连接,而不是重复使用**preconnect** 提示打开的连接。
4.2dns-prefetch
dns-prefetch 不会与跨源服务器建立连接,而只是提前为其执行 DNS 查找。
如果链接会引导用户前往其他网站的情况下,可以使用**dns-prefetch** 。
4.3preload
preload 指令用于针对呈现网页所需的资源发起早期请求:
ini
<link rel="preload" href="/lcp-image.jpg" as="image" fetchpriority="high">
如果 preload 指令的 <link> 元素缺少 as 属性,则该指令中指定的资源会被下载两次。
图片默认优先级较低,而预加载不会改变这一点,所以需要添加**fetchpriority="high"** 属性。
同样,如果资源是跨域,也需要添加**crossorigin** 属性,反之浏览器会下载资源两次。
如果过度使用**preload** 可能会造成带宽争用,从而对网页加载速度产生负面影响。
4.4prefetch
prefetch 指令比较适合用于发起低优先级的资源请求,该资源可能用于未来的导航:
ini
<link rel="prefetch" href="/next-page.css" as="style">
prefetch 在很大程度上是推测性的,因为要为可能发生也可能不发生的未来导航发起资源提取。可以根据网站的模式,参考一些其他运营指标来进行添加。
4.5Fetch Priority API
ini
<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>
默认情况下,系统会以较低的优先级提取图片。布局完成后,如果发现图片位于初始视口内,则优先级会提升为高 优先级。在上面的 HTML 代码段中,fetchpriority 会立即告知浏览器以 High 优先级下载较大的 LCP 图像,而不太重要的缩略图则以较低的优先级下载。
现代浏览器分两个阶段加载资源。第一阶段专用于关键资源,一旦所有阻塞脚本都已下载并执行,第一阶段即会结束。在此阶段,低 优先级资源可能会延迟下载。通过使用 fetchpriority="high" ,可以提高资源的优先级,使浏览器能够在第一阶段下载该资源。
5.图片优化
在大多数情况下,优化图片意味着通过发送更少的字节来缩短网络时间,但也可以通过提供适合用户设备尺寸的图片来优化发送给用户的字节数。
5.1图片大小
在了解优化图片之前先要搞清楚分辨率。2010 年,iPhone 4 发布时,其屏幕分辨率 (640x960) 是 iPhone 3 (320x480) 的两倍。不过,iPhone 4 的屏幕物理尺寸与 iPhone 3 大致相同。以更高分辨率显示所有内容会导致文字和图片明显变小,确切地说,会缩小到之前的一半。而是 1 个像素变成了 2 个设备像素。这称为设备像素比 (DPR)。
如果设备的 DPR 为 2,并且图片显示在 500 像素 x 500 像素的容器中,那么 1000 像素的正方形图片现在就是最佳尺寸。同样,如果设备的 DPR 为 3,则 1500 像素的正方形图片将是最佳尺寸。
5.1.1srcset
可以使用该属性指定浏览器可能使用的一系列可能的图片来源。指定的每个图片来源都必须包含图片网址以及宽度或像素密度描述符。
ini
**<img
alt="An image"
width="500"
height="500"
src="/image-500.jpg"
srcset="/image-500.jpg 1x, /image-1000.jpg 2x, /image-1500.jpg 3x"
>**
上述 HTML 代码段使用像素密度描述符来提示浏览器在 DPR 为 1 的设备上使用 image-500.png ,在 DPR 为 2 的设备上使用 image-1000.jpg ,在 DPR 为 3 的设备上使用 image-1500.jpg。
5.1.2sizes
可以指定一组来源大小,其中每个来源大小都包含媒体条件和值,用于描述图片的预期显示大小(以 CSS 像素为单位)。
ini
<img
alt="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"
>
如果设备的视口宽度超过 768 像素,则以 500 像素的宽度显示图片。在较小的设备上,图片会以 100vw(即整个视口宽度)显示。
浏览器可以将此信息与 srcset 图片来源列表相结合,以找到最佳图片。例如,如果用户使用的是屏幕宽度为 320 像素且 DPR 为 3 的移动设备,则图片会以 320 CSS pixels x 3 DPR = 960 device pixels 的尺寸显示。在此示例中,尺寸最接近的图片将是 image-1000.jpg ,其固有宽度为 1000 像素 (1000w)。
5.2文件格式
WebP 和 AVIF 等现代图片格式的压缩效果可能优于 PNG 或 JPEG,因此可缩减图片文件大小,从而缩短下载时间。
WebP提供有损压缩和无损压缩。即使使用有损压缩,WebP 也支持 Alpha 通道透明度,而 JPEG 编解码器不支持此功能。比PNG、JPEG和GIF具有更好的压缩效果。
AVIF同样支持有损压缩和无损压缩,与 JPEG 相比,AVIF 可节省超过 50% 的空间。还提供广色域 (WCG) 和高动态范围 (HDR) 功能。
5.3压缩
就图片而言,压缩分为两种类型:
- 有损压缩
- 无损压缩
有损压缩通过量化来降低图像准确度,并使用色度二次采样舍弃额外的颜色信息。最适合包含大量噪点和色彩的高密度图片,通常是内容相似的照片或图像。。有损压缩可应用于 JPEG、WebP 和 AVIF 图片。
无损压缩通过压缩图像来减小文件大小,而不会丢失任何数据。无损压缩会根据像素与其相邻像素的差异来描述像素。无损压缩用于 GIF、PNG、WebP 和 AVIF 图片格式。
5.4元素
可以更灵活地指定多个候选图片:
ini
<picture>
<source type="image/avif" srcset="image.avif">
<source type="image/webp" srcset="image.webp">
<img
alt="An image"
width="500"
height="500"
src="/image.jpg">
</picture>
采用这种方法,浏览器会选择匹配的第一个指定的 <source> 元素。如果可以渲染该格式的图片,则使用该图片。否则,浏览器会继续处理下一个指定的 <source> 元素。在上述 HTML 代码段中,AVIF 格式优先于 WebP 格式,如果 AVIF 和 WebP 都不受支持,则回退到 JPEG 格式。
<picture> 元素需要嵌套在 <img> 元素内。alt 、width 和 height 属性是在 <img> 上定义的,无论选择哪个 <source> ,都会使用这些属性。
5.5根据Accept请求表头提供图片
服务器可以使用此信息来提供最佳图片格式,而无需向 HTML 响应添加额外的字节。
csharp
if (request.headers.accept) {
if (request.headers.accept.includes('image/avif')) {
return reply.from('image.avif');
} else if (request.headers.accept.includes('image/webp')) {
return reply.from('image.webp');
}
}
return reply.from('image.jpg');
上面的 HTML 代码段是您可以添加到服务器的 JavaScript 后端以选择和提供最佳图片格式的代码的简化版本。如果请求 Accept 标头包含 image/avif ,则提供 AVIF 图片。否则,如果 Accept 标头包含 image/webp,则提供 WebP 图片。如果不满足以上任一条件,则提供 JPEG 图像。
5.6延迟加载
可以使用 loading 属性告知浏览器在图片出现在视口中时延迟加载。属性值为 lazy 时,浏览器不会下载图片,直到图片位于(或接近)视口中。
5.6解码属性
decoding 属性用于告知浏览器应如何解码图片。有以下三种可能的值:
async会告知浏览器可以异步解码图片,这可能会缩短渲染其他内容的时间。sync会告知浏览器,图片应与其他内容同时呈现。auto(默认)允许浏览器决定最适合用户的设置。
6.优化视频
6.1视频源文件
在操作系统上识别的文件( .mp4 、 .webm 等)称为容器。一个容器包含一个或多个流。在大多数情况下,这会是视频和音频流。
可以使用FFmpeg进行文件压缩:
css
ffmpeg -i input.mov output.webm
处理视频文件时,指定多种格式可作为不支持所有现代格式的浏览器的后备方案。
bash
<video>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
</video>
通过 <video> 元素上的 poster 属性添加,该属性会向用户提示视频内容可能是什么,然后再开始播放:
ini
<video poster="poster.jpg">
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
</video>
6.2自动播放
在 <video> 元素中使用 autoplay 属性开启自动播放:
xml
<!-- 自动播放并且重复播放和静音 -->
<video autoplay muted loop playsinline>
<source src="video.webm" type="video/webm">
<source src="video.mp4" type="video/mp4">
</video>
可以使用 <video> 元素的 preload 属性来影响视频资源的下载内容:
- 将值设置为
preload="none"会告知浏览器不应预加载任何视频内容。 - 设置
preload="metadata"仅提取视频元数据,例如视频时长和其他可能的大致信息。
如果加载的视频需要用户启动播放,那么设置 preload="none" 可能是最理想的情况。
7.优化网页字体
大型字体文件可能需要一段时间才能下载完毕,并会对 First Contentful Paint (FCP) 产生负面影响,而错误的 font-display 值可能会导致不必要的布局偏移,从而影响网页的累积布局偏移 (CLS)。
在样式表中使用 @font-face 声明进行定义字体:
css
@font-face {
font-family: "Open Sans";
src: url("/fonts/OpenSans-Regular-webfont.woff2") format("woff2");
}
7.1下载
使用WOFF2压缩字体压缩效果最好,并且比WOFF提高了30%。
如果网页仅以一种语言提供内容,或者仅使用一种字母表,那么可以通过子集化来减小 Web 字体的尺寸。
7.2字体呈现
可以使用 font-display CSS 属性调整浏览器的文本呈现行为,并配置在网页字体完全加载之前应显示或不应显示哪些文本。
7.2.1block
font-display 的默认值为 block 。使用 block 时,浏览器会阻止渲染使用指定 Web 字体的任何文本。
不同浏览器的行为略有不同。Chromium 和 Firefox 会在最多 3 秒内阻止渲染,然后使用回退。Safari 会无限期地阻止,直到网页字体加载完毕。
7.2.2swap
swap 不会阻止渲染,并且会在换入指定的网络字体之前立即以回退方式显示文本。可以立即显示内容,而无需等待下载网络字体。
swap 的缺点在于,如果后备 Web 字体与 CSS 中指定的 Web 字体在行高、字距调整和其他字体指标方面差异很大,则会导致布局偏移。
7.2.3fallback
font-display 的 fallback 值介于 block 和 swap 之间。与 swap 不同,浏览器会阻止字体的渲染,但仅在很短的时间内换入后备文本。不过,与 block 不同的是,阻塞期非常短。
如果网页字体下载速度很快,则在网页的初始渲染中立即使用网页字体,此时使用 fallback 值效果会很好。不过,如果网络速度较慢,则在阻塞期结束后,系统会先显示后备文本,然后在网络字体到达时将其替换掉。
7.2.4optional
仅当网络字体资源在 100 毫秒内下载完毕时才使用该资源。如果网络字体的加载时间超过此时间,则不会在网页上使用该字体,并且浏览器会在后台下载网络字体并将其放入浏览器缓存中,同时使用当前导航的后备字体。
font-display: optional 可避免 swap 中出现的布局偏移,但如果网页字体在初始网页导航中到达得太晚,部分用户将看不到该字体。
8.拆分JavaScript
加载大型 JavaScript 资源会严重影响网页速度。将 JavaScript 拆分为更小的块,并在启动期间仅下载网页正常运行所需的内容,可以大幅提高网页的加载响应速度,进而提高网页的"与下次绘制的互动时间"(INP)。
因为 JavaScript 是在主线程上解析和编译的,如果此过程耗时过长,互动式网页元素可能无法及时响应用户输入,用户可能会感觉互动严重延迟,甚至完全中断。
您可以使用 dynamic import() 语法来拆分代码。与在启动期间请求给定 JavaScript 资源的 <script> 元素不同,此语法会在网页生命周期的后期请求 JavaScript 资源。
大多数打包工具可以配置为在源代码中遇到动态 import() 调用时,将 JavaScript 捆绑包拆分为更小的块。
如果是导出JavaScript模块,可以使用**.mjs** 扩展程序,V8 可以确保基于模块的 JavaScript 代码的流式编译不会中断。传统的 Web 模式:通常浏览器需要下载完整个 JS 文件 ,才能开始解析(Parsing)和编译(Compilation)。流式编译 打破了这种"等待下载完成"的瓶颈。它允许浏览器在脚本数据还在从网络下载的过程中,边下载边编译。
核心原理:并行处理
传统的加载模式是"串行"的,而流式编译让下载和编译变成了"并行"。
-
传统模式:下载 (100%) → 解析 → 编译 → 执行。
-
流式模式:
- 下载前 10% → 立即开始解析这 10% 。
- 下载到 20% → 编译已解析的部分。
- 当最后一个字节下载完成时,大部分代码可能已经编译好了,几乎可以瞬间执行。
在 Chrome 的 V8 引擎中,流式编译主要依赖于 StreamingProcessor。
- 辅助线程解析:当主线程(Main Thread)忙于处理页面渲染时,V8 会开启一个辅助线程。
- 数据块处理 :只要网络层接收到一个新的数据块(Chunk),辅助线程就开始将其转化为 抽象语法树(AST) 。
- 生成的字节码:在后台直接生成字节码,而不必等整个文件。
9.延迟加载图片和iframe元素
通过在启动期间延迟加载iframe有助于提高网页的INP指标,因为 <iframe> 是一个完全独立的 HTML 文档,具有自己的子资源。虽然 <iframe> 元素可以在单独的进程中运行,但它们通常会与其他线程共享一个进程,这可能会导致网页对用户输入的响应速度变慢。
9.1使用loading属性
"eager"会告知浏览器应立即加载图片,即使图片位于初始视口之外也是如此。这也是loading属性的默认值。"lazy"会延迟加载图片,直到图片位于距离可见视口一定距离内时才加载。此距离因浏览器而异,但通常设置得足够大,以便在用户滚动到相应图片时加载该图片。
在使用延迟加载时要考虑不同的视口大小、宽高比和设备,比如手机和桌面,竖屏方向和横屏方向。避免延迟加载视口中的图片。
延迟加载的图片需要等待浏览器完成布局,才能知道图片的最终位置是否在视口内。这意味着,如果可见视口中的 <img> 元素具有 loading="lazy" 属性,则只有在所有 CSS 下载、解析并应用于网页后,才会请求该元素,而不是在预加载扫描器在原始标记中发现该元素时立即提取该元素。
9.2延迟加载iframe
只要网页上存在位于首屏下方的 <iframe> ,就应强烈考虑对其进行延迟加载(如果它不是必须预先加载的),因为这样做可以显著改善用户体验。
iframe也有loading属性,并且于**<img>**元素相同。
9.3外观模式
外观模式是指在网页加载期间显示图片或其他合适的 HTML 元素,直到用户与之互动为止。用户与元素互动后,将其替换为第三方嵌入内容。
比如网页上的聊天插件,使用 facade模式 可以将第三方"开始聊天"按钮替换为虚假按钮。一旦用户与该占位符进行有意义的互动(例如将指针悬停在上面一段合理的时间,或点击该占位符),当用户需要时,实际的功能性聊天微件就会插入到相应位置。
10.预渲染和预缓存
在网页导航到某个网页之前预渲染该网页,可以实现近乎即时的网页加载。
通过 Speculation Rules API 支持预渲染:
xml
<script type="speculationrules">
{
"prerender": [
{
"source": "list",
"urls": ["/page-a", "page-b"]
}
]
}
</script>
使用 Service Worker 预缓存资源,安装后,预缓存的资源便可在 Service Worker 控制的网站上的任何页面上检索。
预缓存清单是一个文件和版本控制信息列表,可作为要预缓存的资源的"可靠来源"。
vbnet
[{
url:'script.ffaa4455.js',
revision:null
},{
url:'/index.html',
revision:'518747aa'
}]
两个文件:script.ffaa4455.js 和 /index.html 。如果资源本身包含文件中的版本信息(称为文件哈希),则可以将 revision 属性保留为 null ,因为文件已进行版本控制(例如,上述代码中 script.ffaa4455.js 资源的 ffaa4455)。对于无版本资源,可以在构建时为其生成修订版本。
设置完成后,Service Worker 可用于预缓存静态网页或其子资源,以加快后续网页导航速度。
css
workbox.precaching.precacheAndRoute(['/styles/product-page.ac29.css','/styles/product-page.39a1.js',]);
11.Web Worker
11.1Web Worker的限制
与在主线程上运行的 JavaScript 不同,Web Worker 无法直接访问 window 上下文。并且对所提供 API 的访问权有限。网络 worker 受到以下限制条件的约束:
- Web Worker 无法直接访问 DOM。
- Web 工作器可以通过消息传递与
window上下文通信 流水线,这意味着 Web Worker 可以通过某种方式间接访问 DOM。 - Web Worker 的范围是
self,而不是window。 - Web Worker 作用域有权访问 JavaScript 基元和 以及
fetch等 API,以及相当多的 其他 API。
可以使用事件监听来与window通信
WebWork用例:
参考资料: