前端性能优化:让你的网站快如闪电

前端性能优化:让你的网站快如闪电

用户耐心有限。页面加载超过 3 秒,53% 的用户会选择离开。

性能优化不是锦上添花,而是决定产品成败的关键因素。这篇文章从实战出发,总结了一套可落地的优化方案。


性能指标

首先明确要优化什么:

| 指标 | 全称 | 目标值 |
|------|------|--------|
| FCP | 首次内容绘制 | < 1.8s |
| LCP | 最大内容绘制 | < 2.5s |
| FID | 首次输入延迟 | < 100ms |
| CLS | 累积布局偏移 | < 0.1 |
| TTI | 可交互时间 | < 3.8s |

使用 Lighthouse 或 Web Vitals 库测量这些指标。

1. 资源优化

图片

图片通常是页面最大的资源:

html
<!-- WebP 格式 + 响应式 -->
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="描述" loading="lazy" width="800" height="600">
</picture>

css
/* CSS 中的图片优化 */
.hero {
  background-image: url('hero-small.webp');
}

@media (min-width: 768px) {
  .hero {
    background-image: url('hero-large.webp');
  }
}

代码压缩

javascript
// terser 配置(webpack)
{
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: { drop_console: true },
        },
      }),
    ],
  },
}

2. 缓存策略

浏览器缓存

nginx
# Nginx 缓存配置
location /static/ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

location /images/ {
    expires 30d;
    add_header Cache-Control "public, no-transform";
}

location / {
    expires -1;
    add_header Cache-Control "no-cache";
}

Service Worker

javascript
// 注册 Service Worker
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}

// sw.js - 缓存优先策略
const CACHE_NAME = 'v1';
const urlsToCache = ['/', '/styles.css', '/app.js'];

self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME).then(cache => cache.addAll(urlsToCache))
  );
});

self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request).then(response => {
      return response || fetch(event.request);
    })
  );
});

3. 渲染优化

代码分割

javascript
// React.lazy + Suspense
import React, { lazy, Suspense } from 'react';

const HeavyComponent = lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <Suspense fallback={<div>加载中...</div>}>
      <HeavyComponent />
    </Suspense>
  );
}

// webpack 动态导入
const LazyPage = () => import('./pages/Dashboard');

关键 CSS 内联

html
<!DOCTYPE html>
<html>
<head>
  <style>
    /* 首屏关键 CSS 直接内联 */
    .header { display: flex; align-items: center; }
    .hero { min-height: 60vh; }
  </style>
  <!-- 非关键 CSS 异步加载 -->
  <link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
</head>

4. 网络优化

HTTP/2 多路复用

nginx
# Nginx 启用 HTTP/2
server {
    listen 443 ssl http2;
    server_name example.com;
    
    # HTTP/2 下不需要做域名散列
    # 所有资源通过同一个连接传输
}

预加载关键资源

html
<!-- 预加载关键资源 -->
<link rel="preload" href="font.woff2" as="font" crossorigin>
<link rel="preload" href="hero.webp" as="image">
<link rel="preconnect" href="https://api.example.com">

<!-- 预获取下一页 -->
<link rel="prefetch" href="/next-page">

5. JavaScript 优化

javascript
// 1. 防抖与节流
function debounce(fn, delay = 300) {
  let timer;
  return (...args) => {
    clearTimeout(timer);
    timer = setTimeout(() => fn(...args), delay);
  };
}

function throttle(fn, limit = 100) {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      fn(...args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

// 2. 虚拟列表
function VirtualList({ items, itemHeight, containerHeight }) {
  const [scrollTop, setScrollTop] = useState(0);
  const visibleCount = Math.ceil(containerHeight / itemHeight);
  const startIndex = Math.floor(scrollTop / itemHeight);
  
  return (
    <div onScroll={e => setScrollTop(e.target.scrollTop)}>
      <div style={{ height: items.length * itemHeight }}>
        <div style={{ transform: `translateY(${startIndex * itemHeight}px)` }}>
          {items.slice(startIndex, startIndex + visibleCount + 2).map(item => (
            <div key={item.id} style={{ height: itemHeight }}>{item.content}</div>
          ))}
        </div>
      </div>
    </div>
  );
}

6. 性能监控

javascript
// Web Vitals 收集
import { onLCP, onFID, onCLS } from 'web-vitals';

function sendToAnalytics(metric) {
  const body = JSON.stringify({
    name: metric.name,
    value: metric.value,
    rating: metric.rating,
    url: location.href
  });
  
  // 发送到分析服务
  navigator.sendBeacon('/analytics', body);
}

onLCP(sendToAnalytics);
onFID(sendToAnalytics);
onCLS(sendToAnalytics);

优化检查清单


  • [ ] 图片使用 WebP/AVIF 格式并懒加载

  • [ ] CSS/JS 文件已压缩和代码分割

  • [ ] 静态资源设置长效缓存

  • [ ] 关键 CSS 内联,非关键 CSS 异步加载

  • [ ] 字体使用 font-display: swap

  • [ ] 开启 HTTP/2 或 HTTP/3

  • [ ] 使用 CDN 分发静态资源

  • [ ] 减少不必要的 JavaScript

  • [ ] 监控 Core Web Vitals

  • 性能优化不是一次性工作,而是一个持续迭代的过程。先用 Lighthouse 找出瓶颈,然后针对性优化,最后用数据验证效果。

    推荐指数:⭐⭐⭐⭐⭐

    检测工具:https://pagespeed.web.dev/

    💬 评论区 (0)

    暂无评论,快来抢沙发吧!