前端性能优化手段

5 阅读6分钟

前端性能优化手段


一、网络层优化

减少请求数量

✅ 合并 CSS / JS 文件

✅ 雪碧图(CSS Sprite)合并小图标

✅ 图标使用 SVG / IconFont 代替图片

✅ 接口合并,减少 HTTP 请求

⚠️ 注意:HTTP/2 下,"合并文件"的收益大幅降低

HTTP/2 多路复用允许在单个 TCP 连接上并行发送多个请求,请求头也经过 HPACK 压缩,每次请求的额外开销极小。 因此在 HTTP/2 环境下,反而推荐拆分资源(细粒度缓存,更新一个文件不影响其他文件的缓存)。

场景HTTP/1.1HTTP/2
并发请求受浏览器限制(约 6 个)单连接无限制并行
合并文件收益很大降低,反而不利于缓存
请求 Header 开销每次完整发送HPACK 压缩,极小

开启 HTTP/2

HTTP/2 是提升网络性能的重要手段,使用前需了解其触发条件:

如何开启:

  1. 服务端配置支持 HTTP/2(以 Nginx 为例):
server {
    listen 443 ssl http2;
    ssl_certificate  /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    ...
}
  1. 浏览器支持(现代浏览器均支持)

一定需要 HTTPS 吗?

  • HTTP/2 协议规范(RFC 7540)允许明文 HTTP/2(h2c),不强制 TLS
  • 所有主流浏览器(Chrome / Firefox / Safari / Edge)均只实现了基于 TLS 的 HTTP/2
  • 结论:Web 前端场景下,HTTP/2 = 必须 HTTPS

减少请求体积

✅ 代码压缩(Gzip / Brotli)

✅ 图片压缩(WebP 格式,体积比 JPG 小 30%)

✅ Tree Shaking 去除未使用代码

✅ 按需引入组件库(如 Element Plus)

缓存策略

✅ 强缓存:Cache-Control: max-age=31536000

✅ 协商缓存:ETag / Last-Modified

✅ 文件名加 hash(content hash),更新才改变文件名

✅ Service Worker 离线缓存

CDN 加速

✅ 静态资源部署 CDN(就近访问)

✅ 第三方库使用 CDN 引入(Vue、React、lodash)


二、资源加载优化

图片优化

✅ 懒加载(loading="lazy" / IntersectionObserver)

✅ 预加载关键图片(<link rel="preload">

✅ 响应式图片(srcset 按屏幕分辨率加载)

✅ 使用 WebP / AVIF 现代格式

✅ 小图转 base64 内联(< 4KB)

SVG + SVGO 与 WebP 的选择

这两者适用于不同场景,不能互相替代:

格式适用场景压缩工具兼容性
SVG图标、Logo、插画、需要缩放的矢量图SVGO(可减少体积 30%~60%)✅ 极好,IE9+ 全支持
WebP照片、截图、复杂位图(替代 JPG/PNG)原生格式即压缩,比 JPG 小 25%~35%✅ 现代浏览器;❌ IE 不支持

WebP 兼容性详情:

浏览器支持情况
Chrome✅ 17+
Firefox✅ 65+
Safari✅ 14+(2020年)
Edge
IE❌ 完全不支持

选择原则:

  • 图标 / Logo / 插画 → SVG + SVGO 压缩
  • 照片 / 背景图 / 复杂图片 → WebP(搭配 <picture> 标签做降级兼容)

WebP 降级方案:

<picture>
  <source srcset="image.webp" type="image/webp" />
  <img src="image.jpg" alt="降级为 JPG" />
</picture>

JS 优化

✅ 不阻塞 HTML 解析

<!-- defer:HTML 解析完再执行,保持顺序 -->
<script defer src="app.js"></script>

<!-- async:下载完立即执行,不保证顺序 -->
<script async src="analytics.js"></script>

✅ 路由懒加载(动态 import)

✅ 组件异步加载

✅ 第三方库按需引入

CSS 优化

✅ 关键 CSS 内联到 (首屏样式)

✅ 非关键 CSS 异步加载

✅ 减少 @import(会阻塞渲染)


三、渲染性能优化

减少重排重绘

回流 / Reflow / Layout 是同一个概念

三个名词来自不同的引擎,本质完全相同

名词来源
Reflow(回流)早期 Gecko(Firefox)引擎术语
Layout(布局)Blink(Chrome)/ WebKit 引擎术语,DevTools 中显示的名称
重排中文通用翻译
回流的准确定义

回流是指浏览器重新计算页面中元素的几何信息(位置、尺寸)并重新布局的过程。

触发条件(不止是尺寸变化,以下情况均会触发):

触发原因典型属性 / 操作
元素尺寸变化width / height / padding / margin / border
元素位置变化top / left / position
内容变化文字内容改变、图片尺寸改变
DOM 结构变化增删节点、移动节点
读取布局属性offsetWidth / scrollTop / getBoundingClientRect()
视口变化浏览器窗口 resize
字体变化font-size / font-family

⚠️ 特别注意:在循环中读取 offsetWidth 等布局属性,会强制浏览器在每次循环中同步执行 Layout,性能极差(强制同步布局)。

渲染流水线与性能代价
JS → Style → Layout(回流)→ Paint(重绘)→ Composite(合成)
              ↑ 越靠前触发,代价越大
操作触发阶段性能代价
width / displayLayout + Paint + Composite最高 ❌
color / background-colorPaint + Composite中等 ⚠️
transform / opacity只触发 Composite最低 ✅

💡 动画优化原则:尽量只触发 Composite(合成),即使用 transformopacity 做动画,利用 GPU 加速。

减少回流示例:

// ❌ 分散修改,触发多次回流
el.style.width = "100px";
el.style.height = "100px";
el.style.margin = "10px";

// ✅ 批量修改(className / cssText)
el.className = "new-style";
// 或者
el.style.cssText = "width:100px; height:100px; margin:10px";

✅ 使用 transform / opacity 做动画(不触发重排)

✅ 使用 will-change 提示浏览器开启 GPU 加速

✅ 避免频繁读取 offsetWidth / scrollTop 等布局属性

✅ 使用 position: absolute/fixed 脱离文档流

虚拟列表(大数据渲染)

✅ 只渲染可视区域的列表项

✅ 库:vue-virtual-scroller、vue3-virtual-scroll-list

// 核心思路
const visibleCount = Math.ceil(containerHeight / itemHeight);
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = startIndex + visibleCount;
const visibleList = list.slice(startIndex, endIndex);

四、代码层优化

JS 优化

// ✅ 防抖:输入框搜索
const search = debounce((val) => fetchData(val), 300);

// ✅ 节流:scroll / resize 事件
const handleScroll = throttle(() => updateUI(), 100);

// ✅ 使用 Web Worker 处理耗时计算(不阻塞主线程)
const worker = new Worker("./heavy-task.js");
worker.postMessage(data);
worker.onmessage = (e) => console.log(e.data);

// ✅ requestAnimationFrame 替代 setTimeout 做动画
requestAnimationFrame(() => updateAnimation());

Vue 优化

✅ v-for 必须加 key

✅ v-if 和 v-show 合理使用

✅ 大组件异步加载(defineAsyncComponent)

✅ computed 缓存计算结果

✅ 合理使用 keep-alive 缓存组件

✅ 避免在模板中写复杂表达式

✅ 长列表使用 v-memo / Object.freeze 冻结

// 冻结不需要响应式的大数据
this.list = Object.freeze(largeList);

五、构建优化(Webpack / Vite)

// vite.config.js
export default {
  build: {
    rollupOptions: {
      output: {
        // 分包策略
        manualChunks: {
          "vue-vendor": ["vue", "vue-router", "pinia"],
          "ui-vendor": ["element-plus"],
        },
      },
    },
    // 开启压缩
    minify: "terser",
    // 小于 4KB 转 base64
    assetsInlineLimit: 4096,
  },
};

✅ 路由分包,按需加载

✅ 公共库单独打包(vendor chunk)

✅ 生产环境去除 console.log

✅ 开启 Gzip/Brotli 压缩


六、用户体验层优化

✅ 骨架屏(Skeleton)代替白屏等待

✅ Loading 状态反馈

✅ 预渲染(SSG)/ 服务端渲染(SSR)提升首屏

✅ 关键资源 DNS 预解析

<link rel="dns-prefetch" href="//cdn.example.com" />
<link rel="preconnect" href="//api.example.com" />

七、性能优化总览

分类关键手段
网络CDN、缓存、Gzip、减少请求
资源图片懒加载/压缩、JS defer/async、按需加载
渲染减少重排重绘、GPU加速、虚拟列表
代码防抖节流、Web Worker、Vue computed
构建Tree Shaking、分包、代码压缩
体验骨架屏、SSR/SSG、预加载

性能优化的核心原则:

  1. 减少资源体积
  2. 减少请求次数
  3. 加快请求速度
  4. 减少渲染工作量
  5. 提升用户感知体验