一、代码优化

1.1 防抖与节流

技术原理应用场景
防抖n 秒内只执行最后一次搜索框输入、表单验证
节流n 秒内只执行一次滚动加载、按钮点击、窗口 resize
// 防抖
function debounce(fn, delay = 300) {
  let timer = null
  return function (...args) {
    if (timer) clearTimeout(timer)
    timer = setTimeout(() => fn.apply(this, args), delay)
  }
}
 
// 节流
function throttle(fn, delay = 300) {
  let lastTime = 0
  return function (...args) {
    const now = Date.now()
    if (now - lastTime >= delay) {
      fn.apply(this, args)
      lastTime = now
    }
  }
}

1.2 避免重排重绘

概念

  • 重排(Reflow):DOM 结构变化导致的重新布局
  • 重绘(Repaint):样式变化但不影响布局

优化方案:

// ❌ 差:多次重排
element.style.width = "100px"
element.style.height = "100px"
element.style.margin = "10px"
 
// ✅ 好:批量修改
element.style.cssText = "width: 100px; height: 100px; margin: 10px;"
 
// ✅ 好:使用 DocumentFragment
const fragment = document.createDocumentFragment()
list.forEach((item) => {
  const li = document.createElement("li")
  li.textContent = item
  fragment.appendChild(li)
})
ul.appendChild(fragment)
 
// ✅ 好:使用 class
element.classList.add("active")
 
// ✅ 好:脱离流操作
element.style.display = "none"
// 修改
element.style.display = "block"

1.3 使用 IntersectionObserver

// 图片懒加载
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)
})

1.4 使用 requestAnimationFrame

// 动画优化
function animate() {
  // 动画逻辑
  requestAnimationFrame(animate)
}
requestAnimationFrame(animate)

1.5 Web Worker

// 主线程
const worker = new Worker("worker.js")
worker.postMessage(data)
worker.onmessage = (e) => console.log(e.data)
 
// worker.js
self.onmessage = (e) => {
  // 耗时计算
  const result = heavyCalculation(e.data)
  self.postMessage(result)
}

二、网络优化

2.1 请求优化

技术说明
请求缓存利用 Cache-Control、ETag 等
取消请求axios cancelToken / AbortController
请求重试指数退避策略
请求合并减少 HTTP 请求次数
并行请求Promise.all()

2.2 压缩与 CDN

// Gzip 配置(Nginx)
// gzip on;
// gzip_types text/plain application/json;
 
// 图片压缩
// - WebP 格式
// - 响应式图片 srcset
// - 懒加载 loading="lazy"

2.3 按需加载

// 路由懒加载
const Home = () => import("@/views/Home.vue")
 
// 组件懒加载
const HeavyComponent = defineAsyncComponent(() => import("./HeavyComponent.vue"))
 
// 第三方库按需引入
import { Button, Input } from "element-ui"
// 而非 import ElementUI from 'element-ui'

三、首屏优化

3.1 优化清单

优化项说明优先级
CDN 加速静态资源走 CDN⭐⭐⭐
Gzip 压缩减小传输体积⭐⭐⭐
SSR 渲染服务端渲染首屏⭐⭐
骨架屏减少用户焦虑⭐⭐
图片懒加载非首屏图片延迟加载⭐⭐⭐
路由懒加载拆分代码包⭐⭐⭐
异步加载非关键资源异步⭐⭐
虚拟滚动长列表优化⭐⭐
Tree-shaking去除未用代码⭐⭐⭐
代码分割拆分 vendor 包⭐⭐⭐

3.2 关键渲染路径优化

HTML → DOM
  ↓
CSS → CSSOM
  ↓
渲染树 → 布局 → 绘制

优化方案:

  1. 关键 CSS 内联
  2. 非关键 CSS 异步加载
  3. 减少 DOM 层级和数量
  4. 使用 GPU 加速(transformwill-change

四、打包优化

4.1 Webpack 优化配置

// 1. 代码分割
optimization: {
  splitChunks: {
    chunks: 'all',
    cacheGroups: {
      vendors: {
        test: /[\\/]node_modules[\\/]/,
        name: 'vendors',
        priority: 10
      }
    }
  }
}
 
// 2. Tree-shaking
// package.json
{
  "sideEffects": false
}
 
// 3. 压缩
optimization: {
  minimize: true,
  minimizer: [
    new TerserPlugin(), // JS 压缩
    new CssMinimizerPlugin() // CSS 压缩
  ]
}

4.2 分析工具

# 打包体积分析
npm install -D webpack-bundle-analyzer
 
# 打包速度分析
npm install -D speed-measure-webpack-plugin

五、事件代理

使用场景

当需要给大量元素绑定相同事件时,使用事件代理可以减少内存消耗

<template>
  <ul @click="handleClick">
    <li v-for="item in list" :key="item.id">
      {{ item.name }}
    </li>
  </ul>
</template>
 
<script setup>
function handleClick(e) {
  // 使用 closest 或 tagName 判断
  const li = e.target.closest("li")
  if (li && e.currentTarget === e.target.closest("ul")) {
    console.log(li.textContent)
  }
}
</script>

六、性能指标

6.1 Core Web Vitals

指标含义目标值
LCP最大内容绘制< 2.5s
FID首次输入延迟< 100ms
CLS累积布局偏移< 0.1

6.2 测量工具

  • Lighthouse
  • Chrome DevTools Performance
  • Web Vitals 扩展

相关链接