性能优化Skill performance

性能优化技能基于Lighthouse性能审计,专注于提升网站加载速度、运行时效率和资源优化,改善核心Web要素如LCP、FCP和TBT。关键词包括:网站速度优化、性能审计、核心Web要素、缓存策略、图像优化、JavaScript优化、前端开发、Web性能。

前端开发 0 次安装 0 次浏览 更新于 3/21/2026

name: 性能优化 description: 优化网络性能以实现更快加载和更好的用户体验。当被问及“加速我的网站”、“优化性能”、“减少加载时间”、“修复慢加载”、“提高页面速度”或“性能审计”时使用。 license: MIT metadata: author: web-quality-skills version: “1.0”

性能优化

基于Lighthouse性能审计的深度性能优化。专注于加载速度、运行时效率和资源优化。

工作原理

  1. 识别代码和资源中的性能瓶颈
  2. 根据对核心Web要素的影响进行优先级排序
  3. 提供具体的优化方案和代码示例
  4. 使用前后指标测量改进效果

性能预算

资源 预算 理由
总页面大小 < 1.5 MB 3G网络下约4秒加载
JavaScript(压缩后) < 300 KB 解析和执行时间
CSS(压缩后) < 100 KB 渲染阻塞
首屏图像 < 500 KB LCP影响
字体 < 100 KB 防止FOIT/FOUT
第三方资源 < 200 KB 不可控延迟

关键渲染路径

服务器响应

  • TTFB < 800ms。 首字节时间应快速。使用CDN、缓存和高效后端。
  • 启用压缩。 对文本资源使用Gzip或Brotli。优先Brotli(小15-20%)。
  • HTTP/2或HTTP/3。 多路复用减少连接开销。
  • 边缘缓存。 尽可能在CDN边缘缓存HTML。

资源加载

预连接到所需源:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://cdn.example.com" crossorigin>

预加载关键资源:

<!-- LCP图像 -->
<link rel="preload" href="/hero.webp" as="image" fetchpriority="high">

<!-- 关键字体 -->
<link rel="preload" href="/font.woff2" as="font" type="font/woff2" crossorigin>

推迟非关键CSS:

<!-- 关键CSS内联 -->
<style>/* 首屏样式 */</style>

<!-- 非关键CSS -->
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>

JavaScript优化

推迟非必要脚本:

<!-- 解析阻塞(避免) -->
<script src="/critical.js"></script>

<!-- 推迟(首选) -->
<script defer src="/app.js"></script>

<!-- 异步(用于独立脚本) -->
<script async src="/analytics.js"></script>

<!-- 模块(默认推迟) -->
<script type="module" src="/app.mjs"></script>

代码分割模式:

// 基于路由的分割
const Dashboard = lazy(() => import('./Dashboard'));

// 基于组件的分割
const HeavyChart = lazy(() => import('./HeavyChart'));

// 基于功能的分割
if (user.isPremium) {
  const PremiumFeatures = await import('./PremiumFeatures');
}

摇树优化最佳实践:

// ❌ 导入整个库
import _ from 'lodash';
_.debounce(fn, 300);

// ✅ 仅导入所需部分
import debounce from 'lodash/debounce';
debounce(fn, 300);

图像优化

格式选择

格式 使用场景 浏览器支持
AVIF 照片,最佳压缩 92%+
WebP 照片,良好备用 97%+
PNG 透明图形 通用
SVG 图标、Logo、插图 通用

响应式图像

<picture>
  <!-- 现代浏览器使用AVIF -->
  <source 
    type="image/avif"
    srcset="hero-400.avif 400w,
            hero-800.avif 800w,
            hero-1200.avif 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  <!-- WebP备用 -->
  <source 
    type="image/webp"
    srcset="hero-400.webp 400w,
            hero-800.webp 800w,
            hero-1200.webp 1200w"
    sizes="(max-width: 600px) 100vw, 50vw">
  
  <!-- JPEG备用 -->
  <img 
    src="hero-800.jpg"
    srcset="hero-400.jpg 400w,
            hero-800.jpg 800w,
            hero-1200.jpg 1200w"
    sizes="(max-width: 600px) 100vw, 50vw"
    width="1200" 
    height="600"
    alt="英雄图像"
    loading="lazy"
    decoding="async">
</picture>

LCP图像优先级

<!-- 首屏LCP图像:急切加载,高优先级 -->
<img 
  src="hero.webp" 
  fetchpriority="high"
  loading="eager"
  decoding="sync"
  alt="英雄">

<!-- 非首屏图像:懒加载 -->
<img 
  src="product.webp" 
  loading="lazy"
  decoding="async"
  alt="产品">

字体优化

加载策略

/* 系统字体堆栈作为备用 */
body {
  font-family: '自定义字体', -apple-system, BlinkMacSystemFont, 
               'Segoe UI', Roboto, sans-serif;
}

/* 防止不可见文本 */
@font-face {
  font-family: '自定义字体';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap; /* 或对非关键使用optional */
  font-weight: 400;
  font-style: normal;
  unicode-range: U+0000-00FF; /* 子集到拉丁文 */
}

预加载关键字体

<link rel="preload" href="/fonts/heading.woff2" as="font" type="font/woff2" crossorigin>

可变字体

/* 一个文件替代多个权重 */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Variable.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-display: swap;
}

缓存策略

Cache-Control头

# HTML(短或无缓存)
Cache-Control: no-cache, must-revalidate

# 带哈希的静态资源(不可变)
Cache-Control: public, max-age=31536000, immutable

# 无哈希的静态资源
Cache-Control: public, max-age=86400, stale-while-revalidate=604800

# API响应
Cache-Control: private, max-age=0, must-revalidate

Service Worker缓存

// 静态资源的缓存优先策略
self.addEventListener('fetch', (event) => {
  if (event.request.destination === 'image' ||
      event.request.destination === 'style' ||
      event.request.destination === 'script') {
    event.respondWith(
      caches.match(event.request).then((cached) => {
        return cached || fetch(event.request).then((response) => {
          const clone = response.clone();
          caches.open('static-v1').then((cache) => cache.put(event.request, clone));
          return response;
        });
      })
    );
  }
});

运行时性能

避免布局抖动

// ❌ 强制多次重排
elements.forEach(el => {
  const height = el.offsetHeight; // 读取
  el.style.height = height + 10 + 'px'; // 写入
});

// ✅ 批量读取,然后批量写入
const heights = elements.map(el => el.offsetHeight); // 所有读取
elements.forEach((el, i) => {
  el.style.height = heights[i] + 10 + 'px'; // 所有写入
});

防抖昂贵操作

function debounce(fn, delay) {
  let timeout;
  return (...args) => {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn(...args), delay);
  };
}

// 防抖滚动/调整大小处理程序
window.addEventListener('scroll', debounce(handleScroll, 100));

使用requestAnimationFrame

// ❌ 可能导致卡顿
setInterval(animate, 16);

// ✅ 与显示刷新同步
function animate() {
  // 动画逻辑
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

虚拟化长列表

// 对于超过100项的列表,仅渲染可见项
// 使用库如react-window、vue-virtual-scroller或原生CSS:
.virtual-list {
  content-visibility: auto;
  contain-intrinsic-size: 0 50px; /* 估计项高度 */
}

第三方脚本

加载策略

// ❌ 阻塞主线程
<script src="https://analytics.example.com/script.js"></script>

// ✅ 异步加载
<script async src="https://analytics.example.com/script.js"></script>

// ✅ 延迟到交互时加载
<script>
document.addEventListener('DOMContentLoaded', () => {
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      const script = document.createElement('script');
      script.src = 'https://widget.example.com/embed.js';
      document.body.appendChild(script);
      observer.disconnect();
    }
  });
  observer.observe(document.querySelector('#widget-container'));
});
</script>

外观模式

<!-- 交互前显示静态占位符 -->
<div class="youtube-facade" 
     data-video-id="abc123" 
     onclick="loadYouTube(this)">
  <img src="/thumbnails/abc123.jpg" alt="视频标题">
  <button aria-label="播放视频">▶</button>
</div>

测量

关键指标

指标 目标 工具
LCP < 2.5s Lighthouse, CrUX
FCP < 1.8s Lighthouse
Speed Index < 3.4s Lighthouse
TBT < 200ms Lighthouse
TTI < 3.8s Lighthouse

测试命令

# Lighthouse CLI
npx lighthouse https://example.com --output html --output-path report.html

# Web Vitals库
import {onLCP, onINP, onCLS} from 'web-vitals';
onLCP(console.log);
onINP(console.log);
onCLS(console.log);

参考资料

有关核心Web要素的具体优化,请参见核心Web要素