如何提高前端应用的性能?

46 阅读2分钟
# 前端性能优化实战指南

## 1. 资源加载优化

**压缩静态资源**- 使用Webpack的TerserPlugin压缩JS
- 配置image-webpack-loader压缩图片
- 启用Gzip/Brotli压缩

```javascript
// webpack.config.js
module.exports = {
  optimization: {
    minimizer: [new TerserPlugin()],
  },
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'image-webpack-loader',
            options: {
              mozjpeg: { quality: 50 }
            }
          }
        ]
      }
    ]
  }
}

关键优化点

  1. 将CSS放在head,JS放在body底部
  2. 使用preload/prefetch预加载关键资源
  3. 实现代码分割和按需加载

2. 渲染性能优化

减少重排重绘

  • 使用transform代替top/left动画
  • 避免在循环中修改DOM
  • 使用will-change提示浏览器
/* 优先使用GPU加速 */
.animate {
  transform: translateZ(0);
  will-change: transform;
}

虚拟列表实现

function renderVirtualList(items, container, itemHeight) {
  const scrollTop = container.scrollTop;
  const startIdx = Math.floor(scrollTop / itemHeight);
  const endIdx = startIdx + Math.ceil(container.clientHeight / itemHeight);
  
  // 只渲染可见项
  items.slice(startIdx, endIdx).forEach(item => {
    renderItem(item);
  });
}

3. 内存管理

常见内存泄漏场景

  1. 未清除的定时器
  2. DOM引用未释放
  3. 闭包滥用
// 正确清除事件监听
function init() {
  const element = document.getElementById('button');
  element.addEventListener('click', onClick);
  
  // 清除方法
  return () => element.removeEventListener('click', onClick);
}

4. 网络请求优化

请求合并策略

  • 小图片使用雪碧图
  • 接口数据使用GraphQL聚合
  • 配置合理的HTTP缓存
// 请求防抖实现
function debounceFetch(url, params, delay = 300) {
  let timer;
  return () => {
    clearTimeout(timer);
    timer = setTimeout(() => {
      fetch(url, params);
    }, delay);
  };
}

5. 监控体系建立

性能指标采集

// 使用Performance API
const timing = performance.timing;
const loadTime = timing.loadEventEnd - timing.navigationStart;

// 上报关键指标
reportAnalytics({
  FCP: getFirstContentfulPaint(),
  LCP: getLargestContentfulPaint(),
  CLS: getCumulativeLayoutShift()
});

6. 现代API应用

优化技巧

  1. 使用IntersectionObserver实现懒加载
  2. 通过Web Worker处理复杂计算
  3. 利用Service Worker缓存资源
// 图片懒加载实现
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.lazy').forEach(img => {
  observer.observe(img);
});

7. 框架级优化

React优化示例

// 使用React.memo避免不必要的渲染
const MemoComponent = React.memo(({ data }) => {
  return <div>{data}</div>;
});

// 正确使用useMemo/useCallback
function ExpensiveComponent({ items }) {
  const processedItems = useMemo(() => {
    return items.map(heavyProcessing);
  }, [items]);

  return <List items={processedItems} />;
}

8. 构建工具优化

Webpack配置要点

  1. 生产模式启用tree-shaking
  2. 配置持久化缓存
  3. 使用DLLPlugin预编译依赖
// 启用模块联邦实现微前端
new ModuleFederationPlugin({
  name: 'app1',
  filename: 'remoteEntry.js',
  exposes: {
    './Button': './src/Button',
  },
  shared: ['react', 'react-dom']
})

9