性能优化在前端面试中是非常常见并且难以回答的问题。一般我们回答性能优化主要会围绕着三个方面来回答:
配置优化: 通过调整构建工具(如 Webpack 或 Vite)的配置,比如代码压缩、Tree Shaking 和代码分割,减少打包体积和加载时间。 访问优化: 包括图片懒加载、预加载关键资源,以及优化 DOM 操作,减少渲染阻塞,提升用户体验。 网络优化: 通过减少 HTTP 请求、启用 HTTP/2、使用 CDN 和缓存策略,提升资源加载速度。
其中每一块如果展开说,内容都非常的多。无法通过一篇文章进行描述。
所以,今天咱们主要就针对 网络优化 进行讲解,主要的内容是 如何避免网络负载。
PS:下文核心内容来自
Anna Monus
在DebugBear
发表的10 Steps to Avoid Enormous Network Payloads
正文
避免巨大的网络负载是 Lighthouse 的一个审计指标,它指的是 前端文件通过网络传输的总大小。要通过这个审计,网络负载需要保持在一定的阈值以下。
在现代网站和 Web 应用中,网络负载往往会迅速增长。造成巨大的网络负载可能有多种原因,因此需要实施一个全面的 Web 性能优化流程。这包括:识别特定问题、可视化 HTML 和 CSS 文件、压缩和精简代码、减小字体和图片的体积等等。
在本文中,我们将详细探讨这个优化流程。不过在开始之前,让我们先来了解什么是网络负载,以及当网络负载变得“巨大”时会带来哪些问题。
什么是网络负载?
网络负载 是指页面从自身服务器或第三方服务器通过互联网下载的所有文件(即资源)的总和。
这些资源包括:
HTML 文件 CSS 文件 JavaScript 文件 图片文件 视频文件 字体文件 等等
Lighthouse 在其 Total Byte Weight 脚本的源代码注释中,将网络负载定义为“与‘资源’大致等价”。然而,除了这段注释外,Google 的官方文档中并未提供更详细的定义。
如何查看网络负载?
你可以通过 Chrome DevTools 的 Network(网络)面板 查看页面的资源列表。每个资源都会对应一个网络请求。
例如,下图展示了 Expedia 首页的网络请求列表(网络负载包含 293 个文件,总大小为 5.3 MB):
这个网络负载触发了 Lighthouse 的黄色警告标志,意味着资源优化还有很大的改进空间:
如何优化网络负载?
为了避免“巨大的网络负载”问题,需要减少资源的总大小。可以通过以下三种方式实现:
移除不必要的资源
找出那些对用户体验没有显著影响的资源,并将它们从页面中移除。 例如,未使用的 CSS 和 JavaScript 文件、过大的图片等。
减小资源的下载大小
使用压缩工具(如 Gzip 或 Brotli)压缩 HTML、CSS 和 JavaScript 文件。 优化图片和字体大小,采用现代格式(如 WebP 和 WOFF2)。
延迟加载资源(Lazy Loading)
仅在用户需要某些资源时才进行下载。 例如,使用 loading="lazy"
属性为图片和 iframe 添加懒加载。
注意事项
需要特别注意的是,Lighthouse 记录的是页面初始加载时的网络负载。这意味着报告显示的资源大小是页面首次加载时所有请求的总和。然而,随着用户与页面交互,浏览器可能会根据用户的操作请求新的资源,从而进一步增加网络负载。
因此,在优化时,除了关注初始加载的资源,也需要确保动态加载的资源同样得到合理的优化。
什么时候网络负载会被认为是“巨大”?
根据 Lighthouse 的文档,当网络负载满足以下条件时,就会被认为是“巨大”:
“根据 HTTP Archive 的数据,网络负载的中位数在 1,700 到 1,900 KiB 之间。为了突出最重的网络负载,Lighthouse 会标记那些总网络请求超过 5,000 KiB 的页面。”
不过,需要注意的是,这些数据最后一次更新是在 2019 年(约 5 年前)。在实际测试中,Lighthouse 的报告显示的结果可能会有所不同。而且,官方文档中并没有提供更近期的具体阈值。
实测发现
基于测试、相关文章的研究以及 Lighthouse 源代码的分析,以下是一些有趣的发现:
黄色警告标志的触发条件
当网络负载超过 2,667 KB 时,Lighthouse 会触发黄色警告标志(yellow flag)。 低于这个值,则显示灰色信息标志(grey flag),表示通过。
永远没有绿色标志
奇怪的是,“避免巨大的网络负载”审计从未触发绿色标志(green flag)。即使网络负载极低,Lighthouse 也只显示灰色信息标志。
示例:
下图中,尽管作者的网站网络负载非常轻,仅为 9 KB,Lighthouse 仍然显示灰色标志,而非绿色:
没有红色标志
更奇怪的是,即使网络负载非常高(例如超过 17,000 KB),Lighthouse 也不会触发红色标志(red flag)。它只会显示黄色标志,提示需要优化。
示例:
下图中,Uniqlo 首页的网络负载高达 17,338 KB,但仍然只触发了黄色标志:
如何解读标志?
根据以上实测,可以推断出:
灰色标志:表示通过审计,但仅限于网络负载低于 2,667 KB 的情况。 黄色标志:表示未通过审计,网络负载超过 2,667 KB。 红色标志:不会触发,即使网络负载非常高。
目标是什么?
简单来说:
灰色标志 = 成功:网络负载低于 2,667 KB。 黄色标志 = 失败:网络负载高于 2,667 KB。
因此,优化目标是让网络负载尽可能小,以达到灰色标志的标准。
为什么需要避免巨大的网络负载?
巨大的网络负载会对 Web 性能产生严重影响,不仅会导致页面加载变慢,有时还会引发意外的布局偏移问题。
这种影响主要体现在以下几个方面:
1. 对核心 Web 指标的影响
巨大的网络负载可能会增加以下三个 核心 Web 指标 的得分,从而降低用户体验:
最大内容渲染时间(Largest Contentful Paint, LCP)
当网络负载较重时,关键内容(如首屏内容)需要更长时间才能出现在屏幕上,直接导致 LCP 得分变差。交互到下一次渲染时间(Interaction to Next Paint, INP)
JavaScript 文件下载和编译速度变慢,会拖延交互反馈时间,影响用户的操作流畅性。累计布局偏移(Cumulative Layout Shift, CLS)
如果浏览器需要下载并处理更多文件,不同的布局元素可能会以非线性的顺序出现,导致更多的意外布局偏移。
总结:
网络负载是一个会影响几乎所有其他性能指标的关键度量,因此优化网络负载是提升整体性能的基础。
2. 为什么 Lighthouse 永远不给绿色标志?
Lighthouse 的 "Avoid Enormous Network Payloads" 审计从未给出绿色标志,甚至当页面的网络负载仅为 9 KB 时,仍然只是显示灰色标志。这可能是因为:
网络负载是动态的
网络负载会随着页面交互增加,例如用户滚动或点击触发新的资源加载。因此,这一指标是动态变化的,很难彻底优化到“完美”。影响范围广
网络负载的大小直接或间接地影响了几乎所有其他性能指标,因此即使当前表现较好,也无法“完全满意”。
3. 网络负载的增长趋势
尽管优化网络负载对性能非常重要,但根据 HTTP Archive 的报告,网络负载的中位数在过去几年中持续增长:
桌面端页面的平均重量:从 2018 年 10 月到 2024 年 10 月增长了 73.1% 移动端页面的平均重量:增长了 82.3%
这表明,随着现代 Web 应用和网站变得越来越复杂,网络负载的优化工作也变得更加重要。
4. 如何避免巨大的网络负载?
在了解了网络负载对性能的影响后,接下来我们将探讨 10 个实用步骤,帮助开发者有效地减少网络负载,从而改善页面性能。
1. 分析你的网络负载
优化网络负载的第一步是分析它的结构和大小,从而找到可以优化的地方。你可以通过以下两种方式开始分析:
1.1 使用 Lighthouse 报告
目的:Lighthouse 的 "Avoid Enormous Network Payloads" 审计可以快速判断你的页面是否通过了网络负载的审计,并提供网络负载的整体结构概览。 优点:简单易用,适合快速检查。 局限性:无法深入分析具体的资源或提供更详细的数据。
1.2 使用高级性能分析工具
如果需要更细粒度的洞察,可以使用更高级的 Web 性能分析工具,比如 DebugBear。这些工具可以提供更详细的网络负载信息,例如:
资源的请求瀑布图(Request Waterfall)
请求瀑布图可以显示页面初始加载时浏览器下载的所有资源。以下是一个 Expedia 移动端首页的请求瀑布图(从美国中部数据中心测试):
解读瀑布图:
瀑布图可以帮助你了解网络负载的结构,包括:
每个资源的大小 加载优先级 加载持续时间 加载顺序
通过分析这些信息,你可以:
找到不必要的资源,考虑移除。 针对某些资源进行重构或替换。 将低优先级资源推迟加载(例如图片、非关键 CSS 和 JS)。
1.3 DebugBear 的功能亮点
DebugBear 提供了丰富的分析功能,以下是一些实用的特性:
资源排序:根据请求的优先级、持续时间、大小和下载顺序对资源进行排序。 域名分析:查看浏览器连接的所有第三方域名。 资源过滤:按文件类型(HTML、CSS、脚本、图片、字体等)过滤资源,快速定位目标资源。 HTTP 请求细节检查: 请求头和响应头 请求体内容 请求链(Request Chain) 其他相关信息
这些功能可以帮助你逐一分析每个页面的资源,并为后续的优化提供具体依据。
1.4 优化思路
通过分析网络负载,以下几种优化方法值得尝试:
移除不必要的资源:检查哪些资源是可以完全去掉的。 推迟加载非关键资源:如懒加载图片和脚本。 合并或精简资源:减少资源的体积和数量。 优化第三方资源:检查是否有过多的第三方请求,优先优化它们。
2. 减少 HTML 文件的下载大小
HTML 文件通常是页面中最大的资源之一。例如,在 Expedia 首页,HTML 文件的大小达到 210 KB,需要重点优化。
如何判断 HTML 文件是否过大?
使用 Lighthouse 或 DebugBear 的审计功能,检查文件是否超标(通常基于压缩后的体积)。 分析文件中的具体问题,比如:
内联样式:过多的 <style>
块。内联脚本:嵌入过多的 <script>
内容。
优化方法
分离内联内容
将内联的样式和脚本移至外部文件:
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
启用 HTTP 压缩
在服务器端启用 GZIP 或 Brotli 压缩,进一步减小传输体积。
删除无用内容
检查冗余注释、多余空格和不必要的 meta 标签,减小文件大小。
3. 避免过大的 CSS 文件
在优化 HTML 文件后,下一个优化目标是分析并减少 CSS 文件的大小。由于一个页面可能加载多个 CSS 文件(包括自有域和第三方域),这些文件可能包含许多冗余内容。
常见的 CSS 问题
冗长的选择器:
复杂的 CSS 选择器增加文件体积,例如:
/* 冗长选择器 */
body.home.page .content > .section .title > span {
color: red;
}
/* 简化选择器 */
.title span {
color: red;
}
未使用的样式规则:
项目中未被引用的 CSS 代码。 Base64 编码的嵌入资源:
内嵌的图片或字体会显著增加文件体积,可将它们替换为外部文件。 过长的变量名:
变量命名过长会累积大量不必要的字节数。
优化方法
清理未使用的样式
使用工具如 PurifyCSS 或 UnCSS 检测和移除未被引用的规则。
压缩 CSS 文件
借助 cssnano 或 PostCSS 删除多余空格、注释等内容。
分割与按需加载
通过代码分割技术,将 CSS 文件拆分为仅需加载的部分。例如:
import('./style.css').then(() => console.log('CSS 已加载'));
优化变量命名
将过长的变量名替换为更简短的名称:
/* 冗长变量名 */
--bui_animation_page_transition_enter: var(
--bui_animation_page_transition_enter_duration
) var(--bui_animation_page_transition_enter_timing_function);
/* 简短变量名 */
--anim_enter: var(--anim_dur) var(--anim_time);
4. 压缩文本文件
优化网络负载的一个关键步骤是压缩 HTML、CSS、JavaScript、JSON 等文本文件。通过服务器端压缩,可以显著减少文件体积,加快网页加载速度。
常见的文本压缩算法
GZIP
支持的压缩级别:1 到 9。 优点:几乎所有浏览器都支持。 缺点:压缩效率稍逊于 Brotli 和 Zstandard。
Brotli
支持的压缩级别:1 到 11。 优点:更高的压缩效率,全球浏览器支持率达 97.65% 缺点:部分旧版浏览器可能不支持。
Zstandard
支持的压缩级别:-7 到 22。 优点:超高的压缩效率,适合对性能要求极高的场景。 缺点:浏览器支持率仅 70.41%(Safari 不支持)。
压缩级别的权衡
低压缩级别(如 GZIP 1, Brotli 1, Zstandard -7) 压缩速度更快,但效率较低。 高压缩级别(如 GZIP 9, Brotli 11, Zstandard 22) 压缩效率更高,但需要更多的 CPU 时间。
选择压缩级别需要根据服务器性能和网络传输需求平衡。大多数场景推荐使用中高压缩级别(如 Brotli 6-8)。
如何检查压缩情况
使用工具如 DebugBear 可以检测页面加载的所有资源及其对应的压缩算法:
显示文件所用的压缩方式(如 GZIP、Brotli)。 提示是否存在未压缩的文本文件。
示例:
下图显示 Booking.com 首页的文本文件大多使用 Brotli 压缩:
5. 精简你的 HTML、CSS 和 JavaScript 文件
在压缩文本文件的基础上,进一步对 HTML、CSS 和 JavaScript 文件进行精简(Minify),可以显著减少文件体积。当压缩和精简结合使用时,文件体积的总体减少可以达到 90%
精简与压缩的区别
精简和压缩是两种不同的优化技术,以下是它们的主要区别:
特点 | 压缩(Compression) | 精简(Minification) |
---|---|---|
作用 | 使用 GZIP、Brotli、Zstandard 等算法对文本文件进行编码。 | 移除代码中的多余空格、换行符、分号和注释等冗余内容。 |
执行位置 | 在服务器端编码,浏览器端解码;通过 HTTP Header 协商支持的算法。 | 在构建流程中或上传到服务器前完成,浏览器可直接解析精简文件。 |
输出文件格式 | 不可读,文件后缀通常为 .gz , .br , .zst 等(保留原始扩展名)。 | 可读,文件后缀不变,但通常添加 .min 标识,如 .min.css 。 |
工具 | 服务器端编码器如 GZIP、Brotli、Zstandard。 | 构建工具如 Webpack、Rollup,或独立精简工具如 HTML Minifier。 |
示例对比:
以下为 Bootstrap 精简后的 CSS 文件和 Brotli 压缩后的版本对比:
精简后的 CSS 示例:
.btn.active,.btn.show,.btn:first-child:active,:not(.btn-check)+.btn:active{color:var(--bs-btn-active-color);background-color:var(--bs-btn-active-bg);border-color:var(--bs-btn-active-border-color)}
Brotli 压缩后的字符串:
G8MAAETd1uqH7vTZki+2CyoWEWJ28wKlWnRL8kDaC/z2D/ZID3XDpKTMf8ObWB4nHaaOiV5IhxumqFHOYwD0WCgZwXPz0e3LyNhspfCF9vmf+Y6BA38N7lDhAw==
在上述例子中,Brotli 压缩使文件从 196 字节 减少到 124 字节,体积减少了 36.73% 。对于较大的文本文件,优化效果通常更显著。
6. 减少未使用的 CSS 和 JavaScript
除了压缩和精简,审查并移除未使用的 CSS 和 JavaScript 是进一步降低页面体积的关键步骤。
如何减少未使用的代码
审查未使用的代码
使用 Chrome DevTools 的 Coverage
面板,识别未使用的 CSS 和 JS。借助 DebugBear 等工具,分析未使用代码的比例。
移除未使用的 CSS
使用工具如 PurifyCSS 或 UnCSS 自动移除未使用样式。 按需加载特定页面的样式:
import('./style.css').then(() => {
console.log('样式加载完成');
});
减少未使用的 JavaScript
Tree Shaking:通过模块打包工具(如 Webpack、Rollup)移除未使用的代码。 动态加载:
import('./module.js').then(module => module.init());
优化第三方代码
对于第三方库(如 Bootstrap),避免直接修改其代码,但可以通过代码分割等技术只加载必要部分。
通过以上方法,移除未使用的 CSS 和 JavaScript,可以显著减少页面体积并通过 Lighthouse 审计。
7. 优化图片体积
图片通常占据页面体积的主要部分,因此优化图片的大小和加载策略是减少网络负载的重要步骤。
图片优化方法
避免不必要的大图片
实施响应式图片策略:为同一位置提供多种分辨率的图片,让浏览器根据设备选择最合适的版本。 示例:
<img srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w" sizes="(max-width: 800px) 100vw, 800px" src="medium.jpg" alt="example">
延迟加载屏幕外图片
使用 loading="lazy"
属性,延迟加载用户未访问到的图片。或利用 IntersectionObserver
API 实现更精细的控制:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
document.querySelectorAll('img[src]').forEach(img => observer.observe(img));
使用现代图片格式
使用 WebP 和 AVIF 等新一代图片格式,减少文件体积。 优势:支持度高,压缩率显著优于 JPEG 和 PNG。
8. 优化字体体积
虽然字体文件的体积通常比图片小,但不必要的字体下载或过大的字体文件也会增加网络负载。因此,优化字体体积是减少网络负载的重要步骤。
字体优化方法
优先使用系统字体
如果页面设计不需要自定义字体,使用常见的Web 安全字体(如 Arial、Verdana),它们已经安装在用户的设备上,无需额外下载。
限制字体家族数量
每个页面最多下载两种字体家族,避免加载过多字体样式。
压缩字体文件
使用 WOFF2 格式,这是目前性能最优的字体压缩算法,可显著减少文件体积。
加载所需字符集
针对特定语言或场景加载所需字符集。例如,英语网站仅需加载拉丁字符集,无需包含希腊或阿拉伯字符。
设置 font-display
属性
使用 font-display: fallback
或font-display: optional
,在网络较慢时优先显示系统字体,确保用户体验流畅。
@font-face {
font-family: 'MyFont';
src: url('myfont.woff2') format('woff2');
font-display: fallback;
}
9. 拆分长页面
将较长的页面拆分为更短的页面,可以减少网络负载。你可以审查网站,找出可以分成两三部分的页面,或通过移除侧边栏等方式缩小页面。
较短的页面通常意味着:
更小的 HTML 文件 更少的图片和视频文件 更少的脚本 如果使用代码分割,CSS 和 JavaScript 包也会更小
拆分长页面还可以帮助你改进其他 Lighthouse 审计,例如 避免过多的 DOM 大小 警告。
10. 实现静态资源的浏览器缓存
浏览器缓存可以让返回用户直接从本地加载静态资源(如字体、样式表和脚本),减少服务器请求,提升加载速度。
设置缓存规则
Apache:通过 .htaccess
文件:
ExpiresByType text/css "access plus 1 year"
NGINX:通过 nginx.conf
文件:
location ~* \.(js|css|png|jpg)$ {
expires 1y;
}
优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!
优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、DIY体验、720全景展厅及3D虚拟仿真)、移动端应用(手机站、APP开发)、微信定制开发(微信官网、微信商城、企业微信)、微信小程序定制开发等一系列互联网应用服务。