前端性能优化全家桶:从重绘重排到面试连招,一篇搞懂

性能优化这件事,说简单也简单,说复杂也复杂。核心思想一句话:让浏览器少干活,还得干得快

今天这篇文章,我们从最基础的 重绘、重排 开始,聊到 资源加载、JS 执行、框架优化、缓存、网络、首屏渲染 ,再配上 性能指标、工具和面试连招,让你从理论到实战全覆盖。


一、重绘 & 重排:浏览器最怕的"体力活"

浏览器的渲染流程大概是这样的:

布局(Layout) → 绘制(Paint) → 合成(Composite)

两个关键概念:

  • 重绘(Repaint) 样式改变但位置没动,比如颜色、背景。
  • 重排(Reflow) 尺寸或位置发生变化,需要重新计算布局。

口诀:

重排一定会触发重绘,重绘不一定触发重排。重排开销更大!


1. 批量修改 DOM

❌ 不推荐:

js 复制代码
const el = document.getElementById('myEl');
el.style.width = '100px';
el.style.height = '100px';
el.style.margin = '10px';

✅ 推荐:

js 复制代码
el.style.cssText = 'width: 100px; height: 100px; margin: 10px;';
// 或者直接通过类名
el.className = 'my-class';

2. 使用文档碎片

批量添加节点用 document.createDocumentFragment,只触发一次渲染:

js 复制代码
const fragment = document.createDocumentFragment();
for (let i = 0; i < 10; i++) {
  const el = document.createElement('div');
  fragment.appendChild(el);
}
document.body.appendChild(fragment);

3. 脱离文档流后再修改

js 复制代码
const el = document.getElementById('myEl');
el.style.display = 'none';
// 批量修改
el.style.display = 'block';

4. 缓存布局信息

避免重复触发重排:

js 复制代码
// ❌ 每次循环都会触发重排
for (let i = 0; i < 100; i++) {
  el.style.top = el.offsetTop + 1 + 'px';
}

// ✅ 缓存 offsetTop
let top = el.offsetTop;
for (let i = 0; i < 100; i++) {
  el.style.top = ++top + 'px';
}

5. 用 transform 代替 top/left

js 复制代码
// ❌ 会触发布局
el.style.left = '100px';

// ✅ 只触发重绘
el.style.transform = 'translateX(100px)';

二、资源加载优化

少加载、不阻塞、格式更高效:

  • 图片懒加载

    html 复制代码
    <img loading="lazy" src="xxx.jpg">
  • 路由懒加载 / 代码分割

    js 复制代码
    const Home = React.lazy(() => import('./Home'));
  • 资源预加载

    html 复制代码
    <link rel="dns-prefetch" href="//cdn.example.com">
    <link rel="preload" href="/main.css">
    <link rel="prefetch" href="/next-page.js">
  • WebP 格式图片:小一半体积,质量无损。

  • 字体图标库:减少几十个 HTTP 请求。


三、JS 执行优化

  • 防抖、节流:减少高频事件触发次数。
  • Web Worker:让复杂计算不堵主线程。
  • requestAnimationFrame:动画更丝滑。
  • requestIdleCallback:浏览器闲时干活,React Fiber 就用它实现调度。

四、框架层优化

React/Vue 项目常见套路:

  • memo / useMemo / useCallback 避免不必要渲染。
  • 按需加载组件库,如 shadcn-uiantd
  • 列表渲染合理使用 key,减少 Diff 计算。

五、缓存策略

缓存是性能优化的"性价比王者"。

  • 强缓存(不发请求)

    http 复制代码
    Cache-Control: max-age=3600
    Expires: Wed, 21 Oct 2025 07:28:00 GMT
  • 协商缓存(发请求,返回 304)

    http 复制代码
    Last-Modified / If-Modified-Since
    ETag / If-None-Match
  • 本地缓存

    • localStorage
    • sessionStorage
    • cookie

六、网络优化

  • CDN 加速:资源离用户更近。

  • Gzip 压缩:资源小,加载快。

  • HTTP/2 多路复用:一个连接跑多请求。

  • DNS 预解析

    html 复制代码
    <link rel="dns-prefetch" href="//cdn.example.com">

七、首屏优化

  • SSR(服务端渲染):先把 HTML 渲染好再发给浏览器。
  • 骨架屏:用户看起来更快。
  • HTTP/2 Server Push:首屏资源提前推送。

八、性能测试工具

  • Chrome Performance 定位瓶颈,分析渲染和脚本耗时。
  • Lighthouse 性能、无障碍、SEO 等多维打分。

常见优化建议:

  • 首屏 JS、CSS 体积减小(代码分割)
  • 图片用 WebP
  • 动画尽量用 transform
  • 按需加载组件库

九、核心性能指标

  • FCP(First Contentful Paint) 首次内容绘制时间。
  • LCP(Largest Contentful Paint) 最大内容绘制时间,影响用户"页面加载完毕"的感知。

十、面试高频问题

性能优化在面试里是高频考点,以下是一些常见题型和答题套路。


Q1:重绘和重排的区别?怎么优化?

  • 区别

    • 重绘:样式变化但位置没变。
    • 重排:尺寸或位置改变,需要重新布局。
  • 优化

    • 批量修改 DOM
    • 使用文档碎片
    • 脱离文档流操作
    • 缓存布局信息
    • transform 代替 top/left

Q2:首屏加载优化有哪些方案?

  • 代码分割、懒加载、按需加载
  • Gzip、CDN 加速
  • SSR、骨架屏
  • 强缓存 + 协商缓存组合拳
  • HTTP/2 多路复用

Q3:长列表如何优化?

  • 合理使用 key
  • 虚拟列表技术(react-window
  • 配合 memouseCallback 避免重复渲染

Q4:如何监控和分析性能?

  • 开发阶段:Chrome Performance、Lighthouse
  • 线上阶段:埋点上报 FCP、LCP、CLS;Sentry/ARMS 做监控

Q5:代码优化可以做哪些?

  • 防抖、节流减少高频调用
  • Web Worker 分担计算压力
  • 动画用 requestAnimationFrame
  • 减少无意义的深拷贝或频繁 state 更新

Q6:首页很慢,怎么排查?

  1. 资源问题:JS/CSS 是否太大?图片是否优化?
  2. 网络问题:DNS 解析、CDN 节点延迟。
  3. 渲染问题:同步 JS 阻塞渲染。
  4. 缓存问题:是否未命中缓存。

加分技巧:

答题时用"场景 + 措施 + 效果"的模式:

"项目首页加载慢,排查发现 JS 包 3M,通过 Webpack 分包和懒加载降到 500KB,首屏渲染从 3 秒降到 1.5 秒。"

这样的回答更有说服力!


结语

性能优化不是某个大招,而是一系列"小动作"的积累:

  • 写代码时减少无意义的 DOM 操作
  • 打包部署时合理做缓存和分割
  • 上线后持续监控指标,优化体验

做多了,你会发现,项目从"能跑"到"飞起",就差这些细节。

相关推荐
jvxiao8 分钟前
搭建个人博客系列--(4) 利用Github Actions自动构建博客
前端
袁煦丞20 分钟前
SimpleMindMap私有部署团队脑力风暴:cpolar内网穿透实验室第401个成功挑战
前端·程序员·远程工作
li理26 分钟前
鸿蒙 Next 布局开发实战:6 大核心布局组件全解析
前端
EndingCoder28 分钟前
React 19 与 Next.js:利用最新 React 功能
前端·javascript·后端·react.js·前端框架·全栈·next.js
li理30 分钟前
鸿蒙 Next 布局大师课:从像素级控制到多端适配的实战指南
前端
前端赵哈哈34 分钟前
Vite 图片压缩的 4 种有效方法
前端·vue.js·vite
Nicholas6841 分钟前
flutter滚动视图之ScrollView源码解析(五)
前端
电商API大数据接口开发Cris42 分钟前
Go 语言并发采集淘宝商品数据:利用 API 实现高性能抓取
前端·数据挖掘·api
ITMan彪叔43 分钟前
Nodejs打包 Webpack 中 __dirname 的正确配置与行为解析
javascript·后端
风中凌乱的L1 小时前
vue 一键打包上传
前端·javascript·vue.js