2026年3月6日

网站性能优化 - 提升用户体验的关键

网站性能直接影响用户体验和 SEO 排名。本文介绍网站性能优化的各种方法。

性能指标

Core Web Vitals

指标 说明 良好标准
LCP 最大内容绘制 < 2.5s
FID 首次输入延迟 < 100ms
CLS 累积布局偏移 < 0.1

其他指标

指标 说明
FCP 首次内容绘制
TTFB 首字节时间
TTI 可交互时间
TBT 总阻塞时间

测试工具

前端优化

资源压缩

HTML 压缩

<!-- 移除注释、空格、换行 -->
<!DOCTYPE html><html><head><title>Page</title></head><body>Content</body></html>

CSS 压缩

/* 压缩前 */
.container {
    width: 100%;
    padding: 20px;
}

/* 压缩后 */
.container{width:100%;padding:20px;}

JavaScript 压缩

# 使用工具压缩
# UglifyJS
uglifyjs app.js -o app.min.js

# Terser
terser app.js -o app.min.js

代码分割

动态导入

// 按需加载模块
const module = await import('./heavy-module.js');

// React 懒加载
const LazyComponent = React.lazy(() => import('./LazyComponent'));

Webpack 代码分割

// webpack.config.js
module.exports = {
  optimization: {
    splitChunks: {
      chunks: 'all',
      cacheGroups: {
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendors',
          chunks: 'all',
        },
      },
    },
  },
};

图片优化

格式选择

格式 适用场景
WebP 照片、图标(推荐)
AVIF 照片(新格式)
PNG 透明图片
SVG 图标、矢量图
JPEG 照片

图片压缩

# 使用工具压缩
# imagemin
npm install imagemin imagemin-webp

# TinyPNG
# https://tinypng.com/

# Squoosh
# https://squoosh.app/

响应式图片

<picture>
  <source srcset="image.webp" type="image/webp">
  <source srcset="image.jpg" type="image/jpeg">
  <img src="image.jpg" alt="Description" loading="lazy">
</picture>

<!-- 响应式尺寸 -->
<img 
  srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
  sizes="(max-width: 600px) 480px, 800px"
  src="medium.jpg" alt="Description">

懒加载

<!-- 原生懒加载 -->
<img src="image.jpg" loading="lazy" alt="Description">

<!-- JavaScript 懒加载 -->
<img data-src="image.jpg" class="lazy" alt="Description">
// Intersection Observer
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('.lazy').forEach(img => observer.observe(img));

CSS 优化

关键 CSS 内联

<head>
  <style>
    /* 首屏关键 CSS */
    .header { height: 60px; }
    .hero { min-height: 400px; }
  </style>
  <link rel="stylesheet" href="styles.css" media="print" onload="this.media='all'">
</head>

CSS 选择器优化

/* 避免 */
* { box-sizing: border-box; }
div.container div.content p.text { color: red; }

/* 推荐 */
*, *::before, *::after { box-sizing: border-box; }
.text { color: red; }

减少重排重绘

// 批量修改 DOM
const fragment = document.createDocumentFragment();
items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  fragment.appendChild(li);
});
list.appendChild(fragment);

// 使用 transform 代替 top/left
.element {
  transform: translateX(100px);
}

JavaScript 优化

减少主线程阻塞

// 使用 Web Worker
const worker = new Worker('worker.js');
worker.postMessage({ data: heavyData });
worker.onmessage = (e) => {
  console.log(e.data);
};

// 分片处理
function processLargeArray(array, chunkSize) {
  for (let i = 0; i < array.length; i += chunkSize) {
    setTimeout(() => {
      processChunk(array.slice(i, i + chunkSize));
    }, 0);
  }
}

防抖和节流

// 防抖
function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 节流
function throttle(fn, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      fn.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

字体优化

字体加载策略

/* font-display */
@font-face {
  font-family: 'MyFont';
  src: url('font.woff2') format('woff2');
  font-display: swap;
}

预加载字体

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

子集化字体

# 使用 pyftsubset
pyftsubset font.ttf --output-file=font-subset.woff2 \
  --subset-file=characters.txt \
  --flavor=woff2

网络优化

减少请求数

合并文件

<!-- 合并 CSS -->
<link rel="stylesheet" href="bundle.css">

<!-- 合并 JS -->
<script src="bundle.js"></script>

内联小资源

<!-- 内联小 SVG -->
<svg>...</svg>

<!-- 内联小 CSS -->
<style>.btn{color:red}</style>

缓存策略

强缓存

# Nginx 配置
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

协商缓存

location ~* \.(html)$ {
    etag on;
    add_header Cache-Control "no-cache";
}

CDN 加速

CDN 配置

<!-- 静态资源使用 CDN -->
<link rel="stylesheet" href="https://cdn.example.com/css/style.css">
<script src="https://cdn.example.com/js/app.js"></script>

第三方库 CDN

<!-- unpkg -->
<script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>

<!-- jsDelivr -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>

预加载预连接

<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="//cdn.example.com">

<!-- 预连接 -->
<link rel="preconnect" href="https://cdn.example.com">

<!-- 预加载 -->
<link rel="preload" href="critical.css" as="style">
<link rel="preload" href="font.woff2" as="font" crossorigin>

<!-- 预获取 -->
<link rel="prefetch" href="next-page.html">

<!-- 预渲染 -->
<link rel="prerender" href="next-page.html">

服务器优化

HTTP/2 和 HTTP/3

# Nginx 开启 HTTP/2
listen 443 ssl http2;

# 开启 HTTP/3 (QUIC)
listen 443 quic reuseport;
add_header Alt-Svc 'h3=":443"; ma=86400';

Gzip/Brotli 压缩

# Gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml;

# Brotli 压缩(需要模块)
brotli on;
brotli_types text/plain text/css application/json application/javascript;

服务器缓存

Nginx FastCGI 缓存

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=php:100m inactive=60m;

location ~ \.php$ {
    fastcgi_cache php;
    fastcgi_cache_valid 200 10m;
    add_header X-Cache-Status $upstream_cache_status;
}

Nginx 代理缓存

proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;

location / {
    proxy_cache my_cache;
    proxy_cache_valid 200 1h;
}

数据库优化

查询优化

-- 使用索引
CREATE INDEX idx_user_email ON users(email);

-- 避免 SELECT *
SELECT id, name FROM users WHERE status = 1;

-- 使用 EXPLAIN 分析
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

连接池配置

# MySQL 连接池
max_connections: 100
wait_timeout: 28800
interactive_timeout: 28800

监控与分析

性能监控

// Performance API
const timing = performance.timing;
const metrics = {
  dns: timing.domainLookupEnd - timing.domainLookupStart,
  tcp: timing.connectEnd - timing.connectStart,
  ttfb: timing.responseStart - timing.requestStart,
  download: timing.responseEnd - timing.responseStart,
  domReady: timing.domContentLoadedEventEnd - timing.navigationStart,
  load: timing.loadEventEnd - timing.navigationStart,
};

// Web Vitals
import { getCLS, getFID, getLCP } from 'web-vitals';
getCLS(console.log);
getFID(console.log);
getLCP(console.log);

错误监控

// 错误捕获
window.onerror = function(msg, url, line, col, error) {
  console.log({ msg, url, line, col, error });
};

// Promise 错误
window.addEventListener('unhandledrejection', function(event) {
  console.log(event.reason);
});

优化清单

前端

  • 压缩 HTML/CSS/JS
  • 图片优化和懒加载
  • 代码分割
  • 关键 CSS 内联
  • 字体优化
  • 减少重排重绘

网络

  • 启用 HTTP/2
  • 启用 Gzip/Brotli
  • 配置缓存策略
  • 使用 CDN
  • 预加载关键资源

服务器

  • 优化服务器配置
  • 启用服务器缓存
  • 数据库优化
  • 负载均衡

总结

网站性能优化是一个持续的过程:

  1. 测量:使用工具分析性能
  2. 优化:针对瓶颈进行优化
  3. 监控:持续监控性能指标
  4. 迭代:不断改进优化

性能优化能显著提升用户体验和 SEO 排名,值得投入精力。