<p><img src="https://oscimg.oschina.net/oscnet/up-be5b8f87aa918c521a814c20392d03adc7d.png" alt=""></p>
在当今的 Web 生态中,性能即功能。用户期望网站加载瞬间完成,交互无比流畅。搜索引擎(尤其是 Google)也将核心 Web 指标 (Core Web Vitals) 等性能因素作为排名的重要依据。一个缓慢的网站会直接导致用户流失、转化率下降和品牌形象受损。
这份前端性能检查清单旨在为你提供一个系统性的框架,帮助你识别、诊断并修复影响网站速度的关键瓶颈。它涵盖了从基础测量到高级优化的各个环节。请将此清单视为一个持续改进的起点,而非一次性的任务。
📊 第一部分:测量与监控 (Measurement & Monitoring)
- 定义关键性能指标 (KPIs):
- 核心 Web 指标 (Core Web Vitals):
- LCP (Largest Contentful Paint, 最大内容绘制): < 2.5 秒 (良好)。测量主要内容加载时间。
- FID (First Input Delay, 首次输入延迟): < 100 毫秒 (良好)。测量页面可交互性。
- CLS (Cumulative Layout Shift, 累计布局偏移): < 0.1 (良好)。测量视觉稳定性。
- 其他重要指标:
- TTFB (Time to First Byte, 首字节时间): 服务器响应速度。
- FCP (First Contentful Paint, 首次内容绘制): 用户看到任何内容的时间。
- TTI (Time to Interactive, 可交互时间): 页面完全可交互的时间。
- TBT (Total Blocking Time, 总阻塞时间): FCP 和 TTI 之间主线程被阻塞的总时长。
- 页面加载总时间: 从导航开始到所有资源加载完毕。
- 页面大小 (Page Weight): HTML、CSS、JS、图片、字体等所有资源的总字节数。
- 请求数: 页面加载过程中发起的 HTTP 请求总数。
- 选择合适的测量工具:
- 实验室工具 (Lab Tools): 在受控环境下模拟测试。
- Lighthouse (Chrome DevTools, PageSpeed Insights, WebPageTest, CLI): 综合性能、可访问性、最佳实践、SEO 审计。
- WebPageTest: 功能强大的深度测试,支持多地点、多浏览器、自定义网络条件(如 3G/4G)、视频捕获、瀑布图分析。强烈推荐!
- Chrome DevTools Performance Tab: 详细分析运行时性能(脚本、渲染、绘制)、记录并分析用户交互。
- Chrome DevTools Network Tab: 分析资源加载顺序、大小、时间、请求瀑布流。
- React Profiler / Vue DevTools: 分析框架组件的渲染性能。
- 真实用户监控 (RUM – Real User Monitoring): 捕获真实用户在各种设备和网络条件下的体验。
- CrUX (Chrome User Experience Report): Google 提供的真实用户核心 Web 指标数据。
- 商业 RUM 工具: New Relic, Datadog RUM, Dynatrace, Sentry, SpeedCurve, Akamai mPulse 等。
- 自建 RUM: 使用 web-vitals JS 库收集数据并发送到你自己的分析平台。
- Google Analytics: 通过配置可追踪部分性能事件。
- 建立性能预算 (Performance Budgets):
- 为关键指标(如 LCP、CLS、页面总大小、JS/CSS 总大小、图片总大小、请求数)设定具体的、可衡量的上限目标。
- 将预算集成到 CI/CD 流程中,在 PR 合并或部署前自动检查预算是否超支。
- 使用工具如 bundlesize、Lighthouse CI、Webpack Performance Hints 等来强制执行预算。
- 持续监控:
- 定期(如每天/每周)运行实验室测试(尤其是在关键用户路径上)。
- 持续收集和分析 RUM 数据,关注核心 Web 指标达标率(Good / Needs Improvement / Poor)。
- 设置性能告警(例如,当 LCP 中位数超过 3 秒或 CLS 超过 0.15 时触发警报)。
- 监控性能随时间的变化趋势,识别回归点。
⚙ 第二部分:核心优化策略 (Core Optimization Strategies)
🧩 资源加载 (Resource Loading)
- 最小化关键渲染路径:
- 识别渲染首屏内容所必需的资源(关键 CSS、关键 JS、关键图片/字体)。
- 优先加载这些关键资源。
- 延迟加载非关键资源 (Lazy Loading):
- 图片和 iframe: 使用原生 loading=”lazy” 属性。
- JavaScript: 使用 async 或 defer 属性加载非关键脚本。动态 import() 代码分割。
- 组件/内容: 使用 Intersection Observer API 或框架特性(如 React lazy + Suspense, Vue defineAsyncComponent)实现按需加载。
- 资源预加载/预连接 (Preloading/Prefetching/Preconnecting):
- : 强制浏览器高优先级获取后续页面渲染必需的资源(如关键字体、首屏大图、关键路由的 JS)。
- : 提前建立与重要第三方源的连接(DNS 查找、TCP 握手、TLS 协商)。
- : 提前解析第三方源的 DNS。
- : 低优先级获取用户未来可能需要的资源(如下一页面的资源)。谨慎使用。
- 优化资源加载优先级:
- 确保 HTML 中资源的顺序合理(关键 CSS 放 ,非关键 JS 放底部或异步加载)。
- 使用 fetchpriority=”high” 提示浏览器优先加载关键资源(如图片)。
📦 JavaScript 优化
- 代码分割 (Code Splitting):
- 利用 Webpack、Rollup、Vite、Parcel 等打包工具的代码分割功能。
- 基于路由分割:每个路由加载所需的代码块。
- 基于组件分割:延迟加载非首屏组件。
- 使用动态 import() 语法。
- 减少/最小化 JavaScript:
- Tree Shaking: 移除未使用的导出代码(确保使用 ES 模块语法)。
- Minification (压缩): 使用 Terser 等工具移除空白、注释、缩短变量名。
- 移除死代码 (Dead Code Elimination): 删除永远不会执行的代码。
- 避免大型库/框架的膨胀: 评估依赖项的成本,考虑轻量级替代方案或仅导入所需部分(如 lodash-es 的按需导入)。
- 优化 JavaScript 执行:
- 避免长任务 (Long Tasks): 将复杂任务拆分成小块,使用 setTimeout、requestIdleCallback 或 Web Workers 在主线程外执行。
- 优化启动时间: 延迟执行非关键初始化逻辑。
- 使用高效的算法和数据结构。
- 减少 DOM 操作: 批量更新,使用 DocumentFragment,避免强制同步布局 (Layout Thrashing)。
- 利用 Web Workers: 将密集型计算(如图像处理、复杂排序)移出主线程。
- 优化事件处理: 使用事件委托,避免高频事件(如 scroll, resize, mousemove)上的繁重操作,合理使用防抖 (Debounce) 和节流 (Throttle)。
- 谨慎使用第三方脚本:
- 审计和精简: 定期审查所有第三方脚本(分析、广告、跟踪器、小工具),移除不必要的。
- 延迟加载: 使用 async/defer 加载非关键第三方脚本。
- 寻找更轻量的替代品。
- 考虑自托管: 对于关键库(如 Google Analytics),在可行的情况下自托管以控制加载。
- 使用 rel=”preconnect” 或 rel=”dns-prefetch” 优化连接。
- 设置资源提示 (fetchpriority) 和 crossorigin 属性。
- 考虑使用 iframe 沙盒隔离性能影响大的脚本。
🎨 CSS 优化
- 最小化/压缩 CSS:
- 使用 CSSNano、csso、PostCSS 插件等工具进行压缩。
- 移除未使用的 CSS(使用 PurgeCSS、UnCSS 或类似工具,注意动态生成类名的处理)。
- 优化 CSS 交付:
- 内联关键 CSS: 将渲染首屏内容所需的最小 CSS 直接内联在 HTML 的 中。使用工具(如 Critical, Penthouse)自动化提取。
- 异步加载非关键 CSS:
- 方法 1: 使用 + noscript 回退。
- 方法 2: 使用 media=”print” 加载,然后在 onload 后切换为 media=”all”。
- 避免 @import: 在 CSS 文件中使用 @import 会阻塞渲染。使用 标签替代。
- 优化 CSS 选择器与结构:
- 避免过于复杂或深层嵌套的选择器(如 .header .nav ul li a .icon)。
- 优先使用类选择器 (Class),ID 选择器效率高但复用性差且权重高。
- 减少不必要的通配符 (*) 和属性选择器的使用。
- 遵循 BEM 等命名方法论有助于保持选择器简洁和低特异性。
🖼 图片与媒体优化
- 选择合适的格式:
- JPEG: 适用于照片和色彩丰富的图像(有损压缩)。
- PNG: 适用于需要透明度的图像(无损或有损如 PNG-8)。
- WebP: 强烈推荐! 在保持或接近同等质量下,通常比 JPEG 和 PNG 小 25-35%。现代浏览器广泛支持。
- AVIF: 下一代格式,压缩率比 WebP 更高(尤其在高质量下),但编码解码更慢,兼容性仍在增长。
- SVG: 适用于图标、徽标和简单图形(矢量,无限缩放无损)。
- GIF: 仅用于简单动画,其他情况用视频替代(MP4/WebM)。
- 压缩与优化:
- 始终使用工具压缩图像! 即使选择了现代格式。
- 工具推荐:Squoosh (在线), ImageOptim (Mac), RIOT (Windows), Sharp (Node.js), libvips, imagemin 插件。
- 调整质量设置以平衡视觉保真度和文件大小。
- 移除元数据 (EXIF, XMP 等)。
- 响应式图片:
- 使用
元素和 srcset / sizes 属性。 - 为不同屏幕尺寸和分辨率(1x, 2x, 3x)提供不同尺寸(宽度)的图片源。
- 结合现代格式:
。
- 延迟加载 (Lazy Loading):
- 使用 loading=”lazy” 属性(对
和
- 为不支持原生延迟加载的浏览器提供 JavaScript polyfill(但通常不再必需)。
- 尺寸属性 (Dimensions):
- 始终为
和
- 这可以显著减少 CLS(布局偏移),因为浏览器在图片加载前就能预留正确空间。
- 使用 CSS 控制最终渲染尺寸(width: 100%; height: auto;)。
- 考虑 CDN 的图像优化:
- 利用 Cloudflare, Cloudinary, Imgix, Akamai Image Manager 等 CDN 提供的实时图像转换、优化和格式转换功能。
🔤 字体优化
- 精简字体使用:
- 评估是否真的需要多个字重和变体。限制使用的字重(如 Regular, Bold)和字符集(如 &subset=latin)。
- 考虑系统字体栈作为性能友好的备选方案。
- 字体加载策略:
- : 对关键 Web 字体使用预加载:。
- font-display 策略:
- font-display: swap;: 最常用。 先显示后备字体,Web 字体加载后立即交换。可能导致 FOIT (Flash of Invisible Text) 或 FOUT (Flash of Unstyled Text),但通常可接受。
- font-display: optional;: 仅在短时间内可用时才使用 Web 字体,否则永久使用后备字体。适合非关键字体或对 FOIT/FOUT 零容忍的场景。
- 内联小图标字体 (如果使用): 考虑将小图标字体转换为 SVG sprite 并内联,减少请求。
- 本地存储 (Local Storage):
- 使用 localStorage 或 IndexedDB 缓存已加载的字体文件,避免重复下载(需要实现缓存逻辑)。
🔗 网络优化 (Network Optimizations)
- 启用 HTTP/2 或 HTTP/3:
- HTTP/2 支持多路复用 (Multiplexing)、头部压缩 (HPACK)、服务器推送 (Server Push – 谨慎使用),显著提升资源加载效率。
- HTTP/3 (基于 QUIC) 在弱网环境下表现更优(减少队头阻塞,更快连接建立)。优先使用支持 HTTP/3 的主机和 CDN。
- 启用压缩:
- Brotli (br): 首选! 比 Gzip 压缩率更高(尤其对文本资源)。确保服务器配置支持 Brotli。
- Gzip (gzip): 广泛支持,作为 Brotli 的备选方案。确保服务器为文本资源(HTML, CSS, JS, SVG, JSON 等)启用了 Gzip。
- 利用浏览器缓存:
- 为静态资源(图片、字体、CSS、JS)设置强缓存(Cache-Control: max-age=31536000, immutable – 一年)。
- 为带有哈希指纹的文件名设置 immutable,防止重新验证。
- 为 HTML 文档设置合适的协商缓存(Cache-Control: no-cache 或较短的 max-age 配合 ETag/Last-Modified)。
- 使用 CDN (Content Delivery Network):
- 将静态资源(和动态内容)分发到全球边缘节点,减少用户到资源的物理距离和延迟。
- 提供 DDoS 防护、智能缓存、HTTP/2/3 支持、Brotli 压缩、图像优化等附加功能。
- 优化 TLS/SSL:
- 使用现代、快速的加密套件。
- 启用 OCSP Stapling 减少握手延迟。
- 考虑使用 TLS 1.3,其握手速度更快。
🧱 渲染性能 (Rendering Performance)
- 优化关键渲染路径 (CRP):
- 最小化关键资源数量、大小和往返次数 (RTTs)。
- 优先加载关键 CSS(内联),延迟加载非关键 CSS 和 JS。
- 减少重排 (Reflow) 与重绘 (Repaint):
- 批量 DOM 操作: 使用 documentFragment 或在脱离文档流的元素上操作,然后一次性插入。
- 避免强制同步布局 (Layout Thrashing): 避免在读取布局属性(如 offsetWidth, offsetHeight, getComputedStyle())后立即写入样式,这会导致浏览器强制提前计算布局。应先批量读取,再批量写入。
- 使用 transform 和 opacity 做动画: 这些属性通常由合成器 (Compositor) 线程处理,不会触发主线程的 Layout 和 Paint,效率极高。优先使用 CSS Transitions/Animations。
- 使用 will-change 属性: 谨慎使用以提示浏览器对即将变化的元素进行优化(如 will-change: transform;)。
- 使用 content-visibility: auto;: 现代 CSS 属性,延迟屏幕外内容的渲染,显著提升初始加载和滚动性能(注意对可访问性和 CLS 的影响)。
- 优化 JavaScript 动画:
- 优先使用 CSS 动画。
- 如果必须用 JS,务必使用 requestAnimationFrame() 而非 setTimeout/setInterval。
- 考虑高性能的 JS 动画库(如 GSAP)。
- 虚拟化长列表 (Virtualization):
- 对于渲染大量列表项(数千行)的场景,使用”虚拟滚动”技术(如 React react-window / react-virtualized, Vue vue-virtual-scroller)。只渲染当前视口可见的项。
🛠 框架与库特定优化 (Framework-Specific – 以 React 为例)
- 避免不必要的渲染:
- 使用 React.memo() 包裹函数组件,仅在 props 浅比较变化时渲染。
- 类组件中使用 shouldComponentUpdate() 进行精细控制。
- 确保传递给子组件的回调函数(尤其作为 prop 时)使用 useCallback 进行记忆化,避免因父组件渲染导致子组件不必要的渲染(如果子组件用了 React.memo)。
- 记忆化复杂计算:使用 useMemo。
- 优化状态更新:
- 将状态提升到合理的位置,避免不必要的向下传递。
- 使用 Context API 时,确保 Provider 的值稳定(使用 useMemo 包裹对象)或将不同状态拆分成多个 Context,避免无关更新导致所有消费者重渲染。
- 考虑使用状态管理库(如 Redux, Zustand, Jotai)进行更精细的更新控制。
- 代码分割 & 延迟加载组件:
- 使用 React.lazy(() => import(‘./MyComponent’)) 和
实现组件的动态导入和延迟加载。
- 分析工具:
- 使用 React DevTools Profiler 组件识别渲染瓶颈。
- 使用 why-did-you-render 库检测不必要的组件渲染。
📱 移动端特定优化
- 网络感知优化:
- 使用 Network Information API (navigator.connection) 检测用户网络类型(慢速 2G/3G/4G/5G/WiFi)和设备内存,动态调整资源加载策略(如低网速下加载更低分辨率图片)。
- 考虑为慢速网络用户提供”精简模式”。
- 触控与滚动优化:
- 确保点击目标大小足够(至少 44x44px),间距合适。
- 监听 touchstart/touchend 而非 click 以更快响应(注意无障碍)。
- 使用 { passive: true } 选项添加 touch 和 wheel 事件监听器,提高滚动流畅度(element.addEventListener(‘touchstart’, handler, { passive: true });)。
- 避免在滚动容器上使用 overflow: hidden,这通常会禁用原生弹性滚动 (bounce) 并可能引入卡顿。
- 电池与 CPU 考虑:
- 减少后台任务、动画和轮询的频率。
- 优化复杂的计算,使用 Web Workers。
🔍 SEO 与性能
- 服务器端渲染 (SSR) / 静态站点生成 (SSG):
- SSR (如 Next.js, Nuxt.js, Angular Universal): 在服务器生成完整 HTML 发送给客户端,改善首屏加载速度(尤其是 TTFB、FCP、LCP)和 SEO。注意水合 (Hydration) 成本。
- SSG (如 Next.js, Gatsby, Hugo, Eleventy): 在构建时预渲染所有页面为静态 HTML,提供最佳性能(极快加载)和安全性。适合内容相对固定的站点。
- 增量静态再生 (ISR – Next.js) / 按需重新验证: SSG 的增强,允许在构建后更新或添加页面。
- 流式 SSR:
- 将 HTML 内容分成多个块 (chunks) 逐步发送到浏览器,允许浏览器在接收到整个页面之前就开始渲染内容,显著改善 LCP 和 TTI 感知。Next.js 等框架支持。
🧪 测试与验证
- 在不同环境和条件下测试:
- 设备: 多种真实设备(高/中/低端手机、平板、桌面)。
- 网络: 模拟慢速网络(3G, 甚至 2G – 使用 DevTools 或 WebPageTest)。
- 位置: 测试不同地理区域的访问速度(使用 WebPageTest 的多地点测试)。
- 浏览器: 主要浏览器(Chrome, Firefox, Safari, Edge)及其版本。
- 测试用户旅程 (User Journeys):
- 不要只测首页。测量关键业务路径的性能(如产品详情页 -> 加入购物车 -> 结账流程)。
- 无障碍 (Accessibility) 与性能:
- 许多性能优化(如语义化 HTML、合理的加载顺序)也有益于无障碍。确保优化措施不会损害无障碍性(如延迟加载内容应能被屏幕阅读器正确访问)。
🎯 结论
前端性能优化是一个持续的旅程,而非一劳永逸的目标。这份清单为你提供了全面的视角和具体的行动项。
关键步骤:
- 测量 (Measure): 使用实验室工具和 RUM 确定基线性能。
- 设定目标 (Set Goals): 基于核心 Web 指标和业务需求定义性能预算。
- 分析 (Analyze): 使用工具(Lighthouse, WebPageTest, DevTools)找出瓶颈。
- 优化 (Optimize): 根据清单中的策略,优先处理影响最大的瓶颈(通常是图片、JS、网络请求)。
- 监控与迭代 (Monitor & Iterate): 持续监控性能,建立告警,防止回归,并不断寻找新的优化机会。
拥抱性能文化,将性能考量融入开发的每个阶段(设计、开发、测试、部署),你的用户(和搜索引擎)将会感谢你!开始行动吧,优化你的网站,赢得速度之战!💪
写在最后
译者按: 本文翻译自 Crystallize 的技术博客,原作者提供了非常全面且实用的前端性能优化思路。在实际项目中,务必根据自身应用的特点和用户群体,有侧重地选择和实施这些策略,并通过工具量化优化效果。性能优化永无止境,保持关注新技术(如 Partytown, Islands Architecture)和最佳实践的演进。
版权声明: 本文翻译自 Crystallize 博客文章 “Frontend Performance Checklist“,版权归原作者所有。中文翻译内容仅供学习和交流。
</div>
维权提醒:如果你或身边的朋友近五年内因投顾公司虚假宣传、诱导交费导致亏损,别放弃!立即联系小羊维权(158 2783 9931,微信同号),专业团队帮你讨回公道! 📞立即免费咨询退费
未经允许不得转载:紫竹林-程序员中文网 » 前端性能优化终极清单:提升你的网站速度与用户体验