跳转到主要内容

前端性能优化实战指南

为什么性能优化很重要

性能优化不仅关乎用户体验,还直接影响业务指标:

  • 📱 移动用户占比增加,慢速网络普遍
  • 💰 性能每提升 100ms,转化率可能提升 1%
  • 🔍 Google 将性能作为 SEO 排名因素
  • 😊 快速的加载速度提升用户满意度

加载性能优化

1. 资源压缩与合并

HTML 压缩

<!-- 压缩前 -->
<!DOCTYPE html>
<html>
  <head>
    <title>我的网站</title>
  </head>
</html>

<!-- 压缩后 -->
<!DOCTYPE html><html><head><title>我的网站</title></head></html>

CSS 压缩

/* 压缩前 */
.header {
  background-color: #ffffff;
  padding: 20px;
}
.nav {
  background-color: #ffffff;
  padding: 20px;
}

/* 压缩后 */
.header,.nav{background-color:#fff;padding:20px}

JavaScript 压缩

使用工具如 Terser、UglifyJS:

// 压缩前
function hello(name) {
  return 'Hello, ' + name;
}

// 压缩后
function hello(n){return'Hello, '+n}

2. 图片优化

选择合适的格式

  • JPEG:适合照片和大尺寸图片
  • PNG:适合透明背景和图标
  • WebP:现代格式,体积更小(推荐)
  • AVIF:最新格式,压缩率更高
<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="图片描述">
</picture>

响应式图片

<img
  src="image-800.jpg"
  srcset="image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w"
  sizes="(max-width: 600px) 400px, 800px"
  alt="响应式图片"
  loading="lazy"
>

懒加载

<img src="placeholder.jpg" data-src="actual-image.jpg" loading="lazy" alt="图片">
// Intersection Observer API
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('img[data-src]').forEach(img => {
  observer.observe(img);
});

3. 代码分割

动态导入

// 路由懒加载
const Home = () => import('./views/Home.vue');
const About = () => import('./views/About.vue');

// 组件懒加载
const HeavyComponent = defineAsyncComponent(() =>
  import('./components/HeavyComponent.vue')
);

Webpack 代码分割

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

4. CDN 加速

使用 CDN 分发静态资源:

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

运行性能优化

1. 减少 DOM 操作

// ❌ 错误示例:频繁操作 DOM
for (let i = 0; i < 1000; i++) {
  document.body.innerHTML += `<div>Item ${i}</div>`;
}

// ✅ 正确示例:批量操作
const fragment = document.createDocumentFragment();
for (let i = 0; i < 1000; i++) {
  const div = document.createElement('div');
  div.textContent = `Item ${i}`;
  fragment.appendChild(div);
}
document.body.appendChild(fragment);

2. 事件委托

// ❌ 为每个元素添加事件监听器
items.forEach(item => {
  item.addEventListener('click', handleClick);
});

// ✅ 使用事件委托
container.addEventListener('click', (event) => {
  if (event.target.matches('.item')) {
    handleClick(event);
  }
});

3. 虚拟滚动

对于长列表,使用虚拟滚动只渲染可见项:

<template>
  <div class="virtual-scroll" @scroll="handleScroll">
    <div :style="{ height: totalHeight + 'px' }">
      <div
        v-for="item in visibleItems"
        :key="item.id"
        :style="{ transform: `translateY(${item.offset}px)` }"
        class="item"
      >
        {{ item.content }}
      </div>
    </div>
  </div>
</template>

4. 防抖和节流

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

// 节流:固定时间执行
function throttle(fn, delay) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

// 使用场景
input.addEventListener('input', debounce(handleInput, 300));
window.addEventListener('scroll', throttle(handleScroll, 100));

缓存策略

1. 浏览器缓存

Cache-Control: max-age=3600
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT

2. Service Worker 缓存

// 注册 Service Worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js');
  });
}

// sw.js
const CACHE_NAME = 'v1';
const ASSETS = [
  '/',
  '/styles/main.css',
  '/scripts/main.js',
  '/images/logo.png'
];

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

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

性能监控

1. Performance API

// 页面加载时间
window.addEventListener('load', () => {
  const perfData = performance.getEntriesByType('navigation')[0];
  console.log('页面加载时间:', perfData.loadEventEnd - perfData.loadEventStart);
});

// 资源加载时间
performance.getEntriesByType('resource').forEach(resource => {
  console.log(`${resource.name}: ${resource.duration}ms`);
});

2. Web Vitals

import { getCLS, getFID, getLCP } from 'web-vitals';

// 最大内容绘制 (LCP)
getLCP(console.log);

// 首次输入延迟 (FID)
getFID(console.log);

// 累积布局偏移 (CLS)
getCLS(console.log);

性能优化检查清单

✅ 加载性能

  • 压缩 HTML、CSS、JavaScript
  • 优化图片格式和大小
  • 实现代码分割和懒加载
  • 使用 CDN 分发静态资源
  • 启用浏览器缓存

✅ 运行性能

  • 减少 DOM 操作
  • 使用事件委托
  • 实现虚拟滚动
  • 应用防抖和节流
  • 避免内存泄漏

✅ 监控和分析

  • 使用 Performance API
  • 监控 Web Vitals
  • 定期进行性能审计
  • 分析真实用户数据

总结

前端性能优化是一个持续的过程:

  • 🚀 加载性能:从请求到渲染的整个流程
  • 运行性能:减少计算和渲染开销
  • 📊 性能监控:持续追踪和分析
  • 🔧 工具辅助:使用 Lighthouse、WebPageTest 等工具

记住:优化无止境,但要平衡性能、功能和开发成本!


希望这篇指南能帮助你构建更快的 Web 应用!