介绍
移动网络性能不再是次要问题。由于移动流量占全球网络流量的 60% 以上,并且在新兴市场中增长迅速,因此网站在移动设备上的性能特征直接影响用户保留率、转化率和搜索排名。用户期望快速、流畅的体验 - 53% 的人会放弃加载时间超过 3 秒的网站。本文涵盖了 2024 年优化移动 Web 性能的关键技术,从网络感知加载到触摸事件优化和 Core Web Vitals。
网络条件和自适应加载
移动网络与有线连接有着根本的不同。它们遭受更高的延迟、数据包丢失和可变吞吐量的困扰。即使 5G 推出,采用率仍然不平衡,新兴市场的许多用户依赖 3G 或速度较慢的 4G 连接。 网络信息 API 允许您在运行时检测这些条件:
const connection = navigator.connection;
if (connection) {
const effectiveType = connection.effectiveType; // "slow-2g" | "2g" | "3g" | "4g"
const isSlow = effectiveType === "slow-2g" || effectiveType === "2g";
if (isSlow) {
// Serve low-resolution images, disable animations
loadLowQualityAssets();
}
}
当用户通过浏览器设置启用数据保护模式时,Save-Data 标头和 navigator.connection.saveData 属性也可用于自适应策略。将这些 API 与负责任的预取相结合(使用 <link rel="preconnect"> 表示关键来源,使用 rel="prefetch" 表示预测导航),从而在不浪费带宽的情况下提供快速体验。
Service Worker 支持离线优先的缓存策略,这在移动设备上尤其有价值。使用 Workbox 等库来实现 API 响应的 stale-while-revalidate 和静态资产的缓存优先。通过 HTTP/2 和 HTTP/3,多路复用可减少多个连接的开销,从而使高延迟移动网络上的资产交付更加高效。
设备内存感知
具有 2-4 GB RAM 的低端移动设备很常见,尤其是在发展中市场。 设备内存 API 允许您查询设备的可用 RAM 并相应地调整应用程序的资源使用情况:
const deviceMemory = navigator.deviceMemory; // 0.25, 0.5, 1, 2, 4, 8
if (deviceMemory < 4) {
// Disable heavy animations, reduce bundle size
disableExpensiveFeatures();
}
在缓存大型资源之前使用 navigator.storage.estimate() 以避免填满设备的存储空间。对于内存监控,performance.measureUserAgentSpecificMemory() API(在基于 Chromium 的浏览器中提供)有助于检测内存压力并防止内存不足崩溃。最佳实践包括避免使用大型内存数据结构、流式传输大型数据集而不是缓冲它们,以及实现无限滚动的分页。
触摸事件和滚动性能
触摸交互是移动设备上的主要输入机制。优化触摸处理程序对于实现 60 FPS 体验至关重要。最有影响力的更改是将 passive 标志添加到触摸事件侦听器:
document.addEventListener("touchstart", handler, { passive: true });
document.addEventListener("touchmove", handler, { passive: true });
这告诉浏览器处理程序不会调用 preventDefault(),允许滚动继续进行而无需等待处理程序 - 将每帧的帧时间缩短 10–30 毫秒。
同样,使用 touch-action CSS 属性禁用交互式元素上的双击缩放,这消除了旧版浏览器上的 300 毫秒的点击延迟:
| CSS 属性 | 效果 |
|---|---|
| 占位符_0 | 禁用双击缩放,启用即时点击 |
| 占位符_0 | 仅限于垂直平移 |
| 占位符_0 | 禁用所有浏览器触摸手势 |
指针事件 API 为鼠标、触摸和笔输入提供统一的接口。结合 pointer: fine 和 pointer: coarse 媒体查询,您可以根据输入类型定制命中目标和手势处理。始终为触摸处理程序每帧预算 16 毫秒 - 通过在写入之前读取布局属性和批量 DOM 突变来避免布局抖动。
响应式图像和自适应加载
在大多数移动网站上,图像是页面重量的最大贡献者。 <picture> 元素与 srcset 和 sizes 结合使用,可以实现艺术方向和分辨率切换:
<picture>
<source srcset="hero.avif" type="image/avif" />
<source srcset="hero.webp" type="image/webp" />
<img
src="hero.jpg"
srcset="hero-375.jpg 375w, hero-768.jpg 768w, hero-1280.jpg 1280w"
sizes="(max-width: 768px) 100vw, 50vw"
loading="lazy"
fetchpriority="high"
decoding="async"
alt="Hero image"
/>
</picture>
请注意,使用 loading="lazy" 表示离屏图像,使用 fetchpriority="high" 优先考虑首屏英雄图像,使用 decoding="async" 从主线程卸载解码。图像 CDN 可以自动协商最佳格式(WebP、AVIF)、调整视口图像大小并应用质量优化。
除了图像之外,还可以使用 bundle splitting 按路由进行代码分割,使用 React.lazy / Suspense 进行组件级分割,并使用 CSS 中的 content-visibility: auto 跳过渲染离屏部分。像 TanStack Virtual 这样的虚拟滚动库仅渲染长列表中的可见项目,从而大大减少 DOM 大小和内存使用量。
移动核心网络生命力
Core Web Vitals 为移动用户体验提供了标准化的测量框架:
| 公制 | 好目标 | 移动挑战 |
|---|---|---|
| LCP(最大内容涂料) | < 2.5 秒 | 英雄图像在慢速网络上加载,字体渲染延迟 |
| INP(与下一个绘画的交互) | < 200 毫秒 | 繁重的主线程、缓慢的事件处理程序、布局抖动 |
| CLS(累积布局偏移) | < 0.1 | 动态广告加载、字体交换、无尺寸图像 |
对于 LCP,建立与图像 CDN 的预连接,在主图像上设置 fetchpriority="high",使用响应式图像,并确保字体使用 font-display: optional 以防止阻塞。对于 INP,应用被动事件侦听器、反跳输入处理程序、使用 yield 或 setTimeout 分解长任务(>50 毫秒),并使用 navigator.scheduling.isInputPending() 在输入挂起时让出。对于 CLS,请始终在图像上设置显式 width 和 height,对响应式容器使用 aspect-ratio CSS,并使用 min-height 为广告等动态内容预留空间。
测试移动性能
仅在模拟设备上进行测试是不够的。使用 Lighthouse Mobile 和节流 CPU 和网络模拟作为基准,但始终在真实设备上进行验证。 WebPageTest 提供在实际移动设备上的测试,并通过视频捕获进行逐帧分析。 Chrome DevTools 提供具有网络和 CPU 限制(6 倍减速)的设备模拟。
对于生产监控,请从 Chrome 用户体验报告 (CrUX) 和真实用户监控 (RUM) 工具收集现场数据。 web-vitals npm 包可以轻松测量生产中的 LCP、INP、CLS、FCP 和 TTFB。最后,在 CI 中强制执行性能预算——如果捆绑包大小或性能指标超过定义的阈值,自动检查就会失败。
结论
移动性能优化需要整体方法:网络感知、内存感知加载、流畅的触摸交互和响应式图像。基于设备功能的自适应加载(将网络信息 API 与设备内存 API 相结合)是为当今网络上的各种移动设备提供服务的关键。专注于 Core Web Vitals(LCP、INP、CLS)作为您的测量框架,并始终在真实设备上进行测试以捕获真实世界的性能特征。

