前端性能优化汇总

前缀1. 前端性能优化可以从哪些方面入手?

可以归纳为 5 大方向:

  • 加载优化

    • 资源合并:合并 CSS、JS 文件,小图标用雪碧图
    • 内联资源:关键 CSS 内联,小图可转 base64,
    • 懒加载:图片、组件、路由按需加载
    • 浏览器缓存策略:减少重复请求
    • CDN 加速:静态资源走 CDN
    • 使用 HTTP/2:利用多路复用能力
    • 优化首屏加载
    • dns-prefetch --- DNS 预解析
    • preconnect --- 预连接(提前与目标域名完成 DNS 解析 + TCP 握手 + TLS 协商
    • preload --- 预加载(当前页面必备资源)
    • scriptasyncdefer --- 经典但永远重要
  • 渲染优化:优化关键渲染路径、减少重排重绘

    • css优化

      • 选择器优化:避免过深嵌套和复杂选择器
      • 压缩 CSS:移除空格、注释、重复规则
      • 避免 @import :优先使用 link
      • 清理无用 CSS :如 PurgeCSS
      • 合理拆分样式,减少首屏阻塞
      • 避免触发布局抖动的写法
    • javascript优化

      • 代码分割:按页面、路由、功能拆包
      • 动态导入:按需加载模块
      • Tree Shaking:移除未使用代码
      • 压缩混淆:降低文件体积
      • 使用 asyncdefer:避免脚本阻塞渲染
      • 使用 Web Workers:处理计算密集型任务
      • 优化算法和数据结构
      • 避免内存泄漏,清理监听器和定时器, 清理闭包
      • 防抖节流Web Worker
    • react优化

      • React.memo / PureComponent
      • useMemo / useCallback
      • 列表渲染中的稳定 key
      • 代码分割与懒加载 --- React.lazy + import('./') + Suspense
      • 虚拟列表
      • 合理使用 Context 配合 useMemo + useCallback
    • vue优化

      • 避免将不需要响应的大数据对象用 reactive 包裹,可使用 shallowRef / shallowReactive 跳过深层响应式。

      • 对于不变数据用 markRaw 永久标记为非响应式

      • 计算属性 computed

      • v-once:只渲染一次,后续不随响应式数据变化更新,适合纯静态内容。

      • v-memo (Vue 3.2+):类似 React.memo,接收依赖数组,只有依赖变化时才重新渲染。

      • 虚拟列表

      • 组件缓存 ------ <KeepAlive>

      • 列表渲染中的 key

      • 模板编译优化(Vue 内部,但面试可提及)

        • 静态节点提升:模板中的纯静态节点会被提升到渲染函数外,多次渲染复用。
        • 预字符串化:大量静态节点会直接编译成字符串通过 innerHTML 渲染。
        • 动态节点标记与 Block Tree:只追踪可能变化的动态节点,更新时跳过静态内容。
      • 非必要的事件监听、定时器、第三方库引用、闭包,防止内存泄漏。

  • 运行时优化:降低主线程压力、优化长列表和复杂计算

  • 打包工具优化:

    • 入口分割
    • 动态导入 import()
    • 第三方依赖单独拆分
    • 路由级分包
    • Tree Shaking
  • 监控与测试:性能监控、性能测试、性能预算

前缀2.: 什么是前端性能优化?为什么重要?

前端性能优化,是指通过技术手段和工程策略,提升网页加载速度、渲染效率与交互流畅度,从而改善用户体验和业务表现的过程。

为什么重要:

  • 用户体验:页面越快,用户满意度和留存率越高
  • 业务价值:页面加载每变慢 1 秒,转化率可能明显下降
  • SEO 影响:搜索引擎会将页面速度作为排名因素之一
  • 成本优化:减少带宽消耗,降低服务器压力

前缀3. 前端性能优化的核心指标有哪些?

3.1 Core Web Vitals

  • LCP(Largest Contentful Paint,最大内容绘制时间):理想值 < 2.5s
  • FID(First Input Delay,首次输入延迟):理想值 < 100ms
  • CLS(Cumulative Layout Shift,累积布局偏移):理想值 < 0.1

3.2 其他常见指标

  • FCP(First Contentful Paint,首次内容绘制)
  • TTI(Time to Interactive,可交互时间)
  • TTFB(Time to First Byte,首字节时间)
  • FPS(页面帧率)
  • 内存占用、CPU 使用率、错误率


一、加载与网络优化

1.1. 如何减少 HTTP 请求数量?

常见方法:

  • 资源合并:合并 CSS、JS 文件,小图标用雪碧图
  • 内联资源:关键 CSS 内联,小图可转 base64,
  • 懒加载:图片、组件、路由按需加载
  • 浏览器缓存策略:减少重复请求
  • CDN 加速:静态资源走 CDN
  • 使用 HTTP/2:利用多路复用能力

1.2. 什么是浏览器缓存?如何配置?

浏览器缓存是把资源存储在本地,减少重复网络请求的一种机制。

1.2.1 缓存类型

  • 强缓存:Cache-ControlExpires
  • 协商缓存:ETagLast-Modified

1.2.2 常见策略

  • 静态资源长期缓存:带 hash 文件名,长缓存
  • HTML 文件不做强缓存:避免页面内容更新不及时
  • API 接口按业务场景设置短缓存或不缓存
ini 复制代码
# 静态资源长期缓存
Cache-Control: max-age=31536000, immutable

# HTML 文件不缓存
Cache-Control: no-cache

# API 接口短期缓存
Cache-Control: max-age=300

1.3. CDN 的工作原理和优势是什么?

CDN(内容分发网络)会把资源缓存到各地边缘节点,用户从距离最近的节点获取资源。

优势:

  • 降低访问延迟
  • 减轻源站压力
  • 提高可用性和稳定性
  • 节省源站带宽成本

适用场景:

  • CSS、JS、图片等静态资源
  • 视频、音频、大文件
  • 部分可缓存的接口内容

1.4. 什么是 HTTP/2?对性能有什么影响?

HTTP/2 是 HTTP 的升级版本,重点提升传输效率。

主要特性:

  • 多路复用:一个连接可并行传输多个请求
  • 头部压缩:降低请求头开销
  • 二进制分帧:传输更高效
  • 服务器推送:可主动推送资源

性能收益:

  • 减少连接数
  • 降低延迟
  • 减少网络开销
  • 提升带宽利用率

1.5. 什么是预加载与资源提示?

资源提示是浏览器加载优化的重要手段,用于提前建立连接或提前获取资源。

1.5.1 常见类型

. dns-prefetch --- DNS 预解析

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

作用 :提前完成 DNS 查询,把域名解析成 IP。

当浏览器发现这个标签,就会在空闲时间先对指定域名执行 DNS 解析。后续请求该域名下的资源时,可以省掉 DNS 查询这一 RTT(往返时间),通常能节省 20-120ms。

适用场景

  • 页面上可能很快要请求的第三方域名(CDN、统计、API 服务器等)。
  • 不适合滥用:如果域名很多,每个预解析都会消耗一点电量和 CPU,挑重要的 2-3 个即可。

注意事项 :仅解析 DNS,不建立连接。是 preconnect 的轻量版。

1.5.2. preconnect --- 预连接

ini 复制代码
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

作用 :提前与目标域名完成 DNS 解析 + TCP 握手 + TLS 协商 (HTTPS 情况下)。

dns-prefetch 更进一步,直接建立好安全连接。后续请求直接复用这个连接,可以节省 DNS + TCP + TLS 时间(通常 100-300ms)。

适用场景

  • 确定一定会用到的重要第三方资源,如字体文件(Google Fonts)、关键 API、CDN 静态资源。
  • 通常配合 crossorigin:如果资源请求需要跨域(如字体需要 crossorigin="anonymous"),preconnect 也要加上同样的 crossorigin 属性,否则连接不会复用。

注意:每个连接会占用浏览器和服务器端资源(特别是 HTTP/1.1 只有 6 个并发连接)。只对 2-3 个最重要的域名使用,用完后可能不会立即关闭,保留一段时间,所以要节制。

1.5.3. preload --- 预加载(当前页面必备资源)

ini 复制代码
<link rel="preload" href="fonts/critical.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="hero.jpg" as="image" media="(min-width: 600px)">

作用 :告诉浏览器:"这个资源 本页马上就需要 ,请以高优先级尽早下载"。

适合那些在正常解析中较晚才会被发现的关键资源(如 CSS 中的字体、首屏大图、JS 动态加载的脚本)。preload 会提升资源的加载优先级,并且不会阻塞 window.onload

必须设置 as 属性 :明确资源类型(style, script, font, image, fetch 等),否则浏览器无法正确处理优先级与安全策略。

典型使用

  • 字体文件(通常写在 CSS 中,CSS 下载解析后才发请求,太晚了)。
  • 首屏大图。
  • 动态导入的关键 JavaScript 块。

常见陷阱 :如果 preload 的资源在 3 秒内未被使用(没有匹配的 <script><img> 或 CSS 使用),控制台会报警告,且浪费带宽。不要滥用。


1.5.4. prefetch --- 预获取(未来页面可能用)

ini 复制代码
<link rel="prefetch" href="next-page.js" as="script">
<link rel="prefetch" href="/articles/next.html" as="document">

作用 :以 极低优先级 在浏览器空闲时下载资源到缓存中,为将来导航做准备。

只下载,不解析执行。当用户真的导航到下一页面时,CSS/JS/图片等可以直接从缓存读取,显著加快页面打开速度。

区分于 preload

  • preload 是告诉浏览器"当前页面马上要",优先级高。
  • prefetch 是"下个页面可能用",优先级低,随时可能被中断。

典型场景:单页应用中,对用户可能访问的路由组件进行预获取;电商列表页,对每个商品详情页的 JS/CSS 预获取。

1.5.5. scriptasyncdefer --- 经典但永远重要

xml 复制代码
<script src="app.js" defer></script>
<script src="analytics.js" async></script>
  • defer:异步下载,HTML 解析完后、DOMContentLoaded 之前顺序执行。适合依赖 DOM 的脚本。
  • async:异步下载,下载完立即执行,无关顺序。适合独立第三方脚本(统计、广告)

二、CSS 优化

2.1. CSS 性能优化有哪些方法?

常见优化点:

  • 选择器优化:避免过深嵌套和复杂选择器
  • 压缩 CSS:移除空格、注释、重复规则
  • 避免 @import:优先使用 link
  • 清理无用 CSS:如 PurgeCSS
  • 合理拆分样式,减少首屏阻塞
  • 避免触发布局抖动的写法

2.2. 如何优化 CSS 动画性能?

建议:

  • 优先使用 transformopacity
  • 避免动画作用在 widthheightmargin 等布局属性上
  • 适度使用 will-change
  • 优先用 CSS 动画,减少 JS 频繁操作 DOM
  • 硬件加速要适度,避免显存占用过高
css 复制代码
.card {
  will-change: transform, opacity;
  transition: transform 0.3s ease, opacity 0.3s ease;
}

.card:hover {
  transform: translateY(-4px);
  opacity: 0.95;
}

三、JavaScript 优化

3.1. JavaScript 性能优化策略有哪些?

常见方法:

  • 代码分割:按页面、路由、功能拆包
  • 动态导入:按需加载模块
  • Tree Shaking:移除未使用代码
  • 压缩混淆:降低文件体积
  • 使用 asyncdefer:避免脚本阻塞渲染
  • 使用 Web Workers:处理计算密集型任务
  • 优化算法和数据结构
  • 避免内存泄漏,清理监听器和定时器, 清理闭包
  • 防抖和节流和Web Worker
javascript 复制代码
const loadModule = async () => {
  const module = await import('./heavy-module.js');
  module.init();
};

3.2. 什么是 Tree Shaking?如何配置?

Tree Shaking 是基于 ES Module 的静态分析能力,移除项目中未被使用的代码。

核心原理:

  • 分析依赖关系
  • 标记实际使用的导出
  • 删除未引用代码
java 复制代码
// webpack.config.js
module.exports = {
  mode: 'production',
  optimization: {
    usedExports: true,
    sideEffects: false
  }
};
json 复制代码
{
  "sideEffects": [
    "*.css",
    "*.scss",
    "./src/polyfills.js"
  ]
}

3.3. 如何实现代码分割(Code Splitting)?

代码分割是把一个大 bundle 拆成多个小 bundle,按需加载。

常见方式:

  • 入口分割
  • 动态导入 import()
  • 第三方依赖单独拆分
  • 路由级分包
javascript 复制代码
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

3.4. 如何优化 JavaScript 执行性能?

重点是减少主线程长任务:

  • 使用时间切片或 requestIdleCallback
  • 把大计算放到 Web Worker
  • 避免频繁操作 DOM
  • 降低重复渲染
  • 拆分大型任务,避免页面卡顿

四、图片与资源优化

4.1. 图片优化有哪些技术?

常见方法:

  • 格式优化:优先 WebPAVIF

  • 尺寸优化:按实际展示尺寸输出

  • 响应式图片:使用 srcset

  • 图片压缩:有损或无损压缩

  • 图片懒加载:

    • 第一: 使用 html5 loading="lazy"首屏外图片延迟加载

    • 第二: Intersection Observer API(推荐)

      现代浏览器原生提供的异步观察元素与视口交叉状态的 API,性能优于滚动事件监听。

      ini 复制代码
      <img class="lazy" data-src="real-image.jpg" src="placeholder.jpg" alt="">
      ini 复制代码
      const lazyImages = document.querySelectorAll('.lazy');
      
      const observer = new IntersectionObserver((entries, obs) => {
        entries.forEach(entry => {
          if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;   // 设置真实图片
            img.classList.add('loaded');
            obs.unobserve(img);           // 加载后停止观察
          }
        });
      }, {
        rootMargin: '0px 0px 200px 0px', // 提前200px开始加载
        threshold: 0.01                  // 元素露出1%即触发
      });
      
      lazyImages.forEach(img => observer.observe(img));
  • 小图标可考虑雪碧图或 SVG

  • 图片异步解码:decoding="async" 告诉浏览器可以在后台异步解码图片,避免解码过程阻塞主线程渲染其他内容 参数:

    • sync:同步解码(默认),可能延迟呈现。
    • async:异步解码,允许先显示其他内容。
    • auto:浏览器决定。
ini 复制代码
<img
  src="small.jpg"
  srcset="small.jpg 480w, medium.jpg 800w, large.jpg 1200w"
  sizes="(max-width: 600px) 480px, 800px"
  loading="lazy"
  alt="example"
  decoding="async" 
/>

4.2. 如何实现资源的预加载和懒加载?

4.2.1 预加载

适用于字体、首屏图片、关键样式、关键脚本等资源。

ini 复制代码
<link rel="preload" href="/fonts/main.woff2" as="font" crossorigin>
<link rel="preload" href="/images/hero.jpg" as="image">

4.2.2 懒加载

适用于图片、组件、列表项、路由页面等非首屏内容。

ini 复制代码
<img src="/images/demo.jpg" loading="lazy" alt="demo">
ini 复制代码
const DetailPage = React.lazy(() => import('./DetailPage'));

五、长列表与运行时优化

5.1. 什么是虚拟滚动?如何实现?

虚拟滚动是只渲染可视区域内的列表项,从而减少 DOM 数量、提升长列表性能。

实现原理:

  • 计算可视区域可以显示多少项
  • 根据滚动位置决定当前需要渲染的区间
  • 动态更新列表内容

适用场景:

  • 商品列表
  • 聊天记录
  • 日志表格
  • 大数据表单

5.2. 如何优化长列表渲染性能?

常见方法:

  • 虚拟滚动
  • 分页加载 / 无限滚动
  • 滚动事件防抖节流
  • 正确使用 key
  • 避免在列表项里创建过多内联函数
  • 减少不必要的重新渲染

六、离线与应用级优化

6.1. 什么是 Service Worker?如何用于性能优化?

Service Worker 是运行在浏览器后台的脚本,能拦截网络请求,实现缓存和离线能力。

性能优化用途:

  • 静态资源缓存
  • 离线访问
  • 预缓存关键资源
  • 缓存优先 / 网络优先等策略切换
ini 复制代码
self.addEventListener('fetch', event => {
  if (event.request.destination === 'image') {
    event.respondWith(
      caches.match(event.request).then(response => {
        return response || fetch(event.request).then(fetchResponse => {
          const responseClone = fetchResponse.clone();
          caches.open('images').then(cache => {
            cache.put(event.request, responseClone);
          });
          return fetchResponse;
        });
      })
    );
  }
});

6.2. 什么是 PWA?如何提升性能?

PWA(渐进式 Web 应用)结合了 Web 与原生应用的优势。

与性能相关的能力:

  • Service Worker 缓存
  • App Shell 快速加载
  • 预缓存关键资源
  • 离线访问
  • 后台同步

七、移动端性能优化

7.1. 如何优化移动端性能?

移动端更受网络、CPU、电量和屏幕尺寸影响。

常见优化点:

  • 正确设置 viewport
  • 优化触摸响应
  • 适配弱网环境
  • 使用合适图片尺寸和格式
  • 减少高耗电、高 CPU 操作
  • 控制动画与频繁重绘
ini 复制代码
<meta name="viewport" content="width=device-width, initial-scale=1.0">
css 复制代码
.touch-element {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

八、框架专项优化

React 专项优化

8.1. 避免无意义的渲染 ------ React.memo / PureComponent

  • 原理:组件渲染前进行 props 浅比较,无变化则跳过渲染。
  • 陷阱 :如果传入了对象、数组、函数等引用类型,父组件每次渲染都会创建新引用,导致浅比较失效。必须配合 useMemo / useCallback 稳定引用
  • 面试扩展点 :可以手写 shouldComponentUpdate 或自定义比较函数作为第二个参数。

8.2. 缓存计算与回调引用 ------ useMemo / useCallback

  • useMemo:缓存计算结果,避免每次渲染重复执行昂贵计算,或保持对象/数组引用稳定。
  • useCallback :缓存函数引用,用于传递给已用 React.memo 的子组件,防止不必要的子渲染。
  • 原则:不要无差别包裹,因为记忆化本身也有开销。通常在传递引用给子组件,且子组件已优化时才用。

8.3. 列表渲染中的稳定 key

  • 为什么不能用 index 作为 key:当列表重新排序、增删时,index 会变,导致错误的就地复用、状态错乱或不必要的 DOM 重建。
  • 必须使用唯一且稳定的标识符(如数据 ID)。

8.4. 代码分割与懒加载 ------ React.lazy + Suspense

javascript 复制代码
const Chart = React.lazy(() => import('./Chart'));
<Suspense fallback={<Spinner />}><Chart /></Suspense>
  • 将非首屏组件单独打成 chunk,按需加载,减小首屏 JS 体积。
  • 可配合 Suspense 展示 loading 状态,错误边界处理加载失败。

8.5. 并发特性(React 18)------ 标记非紧急更新

  • useTransition:将某个状态更新标记为低优先级的"过渡",会让出主线程给用户输入等紧急更新。

    scss 复制代码
    const [isPending, startTransition] = useTransition();
    startTransition(() => { setQuery(input); });
  • useDeferredValue:延迟一个值的更新,使 UI 保持响应。

  • 面试重点:解释"可中断渲染"的意义,如何解决之前同步渲染导致的长任务掉帧。

8.6. React Fiber 架构 ------ 实现时间切片与优先级调度

  • Fiber 将组件树从递归的调用栈转为链表结构的 fiber 节点,渲染可以异步、可中断。
  • 工作循环:浏览器空闲时执行一个个小任务(fiber 单元),每执行一段时间检查是否有更高优先级任务插入(如用户点击),若有则暂停,交还主线程。
  • 效果:避免了长时间同步渲染阻塞动画/输入。

8.7. 处理长列表 ------ 虚拟列表

  • 只渲染可视区域内的元素,大幅减少 DOM 节点。
  • 常用库:react-window@tanstack/react-virtual
  • 面试常手写简易虚拟列表核心思路:根据容器高度、行高、滚动偏移计算起始索引和结束索引,用 paddingtransform 撑开列表高度。

8.8. 合理使用 Context,避免不必要的更新

  • Context 值变化会导致所有用 useContext 的组件重渲染,不管它们是否用到变化的部分。
  • 优化:拆分 Context(主题、用户信息分离开),或用 useMemo 包裹 value 对象引用,或使用第三方库(如 zustand)进行细粒度订阅。

Vue 性能优化专项

8.1. 利用响应式系统的粒度优化

  • Vue 3 的 Proxy 响应式可以追踪到具体属性变化,组件渲染粒度默认就很细,但也要注意:

    • 避免将不需要响应的大数据对象用 reactive 包裹,可使用 shallowRef / shallowReactive 跳过深层响应式。
    • 对于不变数据用 markRaw 永久标记为非响应式。

8.2. 计算属性 computed 与方法的区别

  • computed 会缓存结果,只有依赖变化才重新计算;methods 每次重新渲染都会执行。
  • 衍生数据必须使用 computed,避免模板内执行开销。

8.3. 组件级别的静态标记与优化

  • v-once:只渲染一次,后续不随响应式数据变化更新,适合纯静态内容。

  • v-memo (Vue 3.2+):类似 React.memo,接收依赖数组,只有依赖变化时才重新渲染。

    css 复制代码
    <div v-memo="[valueA]">{{ expensiveComputation(valueA) }}</div>

8.4. 异步组件与代码分割

javascript 复制代码
const AsyncComp = defineAsyncComponent(() => import('./Heavy.vue'))
// 带 loading 和 error 处理
const AsyncComp = defineAsyncComponent({
  loader: () => import('./Heavy.vue'),
  loadingComponent: LoadingComp,
  delay: 200,
  errorComponent: ErrorComp
})

配合路由懒加载 () => import('./views/About.vue') 分割路由级代码。

8.5. 组件缓存 ------ <KeepAlive>

  • 包裹动态组件,保留不活动组件的状态和 DOM,避免反复创建销毁。
  • 适用场景:Tab 切换时保持表单填写状态或滚动位置。

8.6. 列表渲染中的 key

  • 与 React 同理,必须用唯一的 ID ,不能使用 index,否则列表变动可能导致输入框等状态错乱。

8.7. 模板编译优化(Vue 内部,但面试可提及)

  • 静态节点提升:模板中的纯静态节点会被提升到渲染函数外,多次渲染复用。
  • 预字符串化:大量静态节点会直接编译成字符串通过 innerHTML 渲染。
  • 动态节点标记与 Block Tree:只追踪可能变化的动态节点,更新时跳过静态内容。

8.8. 事件与组件销毁清理

  • 非必要的事件监听、定时器、第三方库引用在 beforeUnmount / unmounted 中清除,防止内存泄漏。

8.9. 虚拟列表

  • 与 React 同理,Vue 社区方案:vue-virtual-scroller,核心原理一致。

九、性能监控与测试

9.1. 什么是 Web Vitals?如何监控?

Web Vitals 是 Google 提出的用户体验指标集合。

核心关注:

  • LCP
  • FID
  • CLS

监控方式:

  • 使用 web-vitals 库采集
  • 接入埋点平台进行上报
  • 结合真实用户监控(RUM)持续观察
javascript 复制代码
import { getCLS, getFID, getFCP, getLCP, getTTFB } from 'web-vitals';

9.2. 如何进行前端性能监控?

可以从 3 类指标入手:

  • 加载性能:FCPLCPTTFBTTI
  • 运行时性能:FPS、内存、CPU、长任务
  • 用户体验:FIDCLS、错误率

可使用:

  • Performance Observer
  • web-vitals
  • 浏览器 Performance API
  • 自研埋点系统

9.3. 如何进行前端性能测试?

常用工具:

  • Lighthouse
  • WebPageTest
  • Chrome DevTools
  • GTmetrix

测试建议:

  • 建立性能基线
  • 在不同网络环境下测试
  • 设置性能预算
  • 持续跟踪版本变化
ini 复制代码
const lighthouse = require('lighthouse');
const chromeLauncher = require('chrome-launcher');

async function runLighthouse(url) {
  const chrome = await chromeLauncher.launch({ chromeFlags: ['--headless'] });
  const options = { logLevel: 'info', output: 'html', port: chrome.port };
  const runnerResult = await lighthouse(url, options);

  console.log(
    'Performance score:',
    runnerResult.lhr.categories.performance.score * 100
  );

  await chrome.kill();
}

10、首屏与渲染优化

10.1. 什么是关键渲染路径?如何优化?

关键渲染路径是浏览器把 HTML、CSS、JavaScript 转换为屏幕像素的过程。

优化目标:

  • 减少关键资源数量
  • 减少关键资源体积
  • 缩短关键路径长度

常见方法:

  • 内联首屏关键 CSS
  • 异步加载非关键 CSS/JS
  • 压缩 HTML、CSS、JS
  • 移除未使用代码
  • 优化资源加载顺序
xml 复制代码
<!-- 内联关键 CSS -->
<style>
  .header { display: flex; }
</style>

<!-- 异步加载非关键 CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="styles.css"></noscript>

10.2. 什么是关键 CSS?如何提取和使用?

关键 CSS 指的是首屏渲染必须用到的最小样式集合。

提取方式:

  • 工具提取:CriticalPenthouse
  • 手动分析首屏模块样式
  • 在构建流程中自动化提取

使用方式:

  • 首屏关键 CSS 内联
  • 完整 CSS 异步加载
xml 复制代码
<style>
  .header { display: flex; height: 60px; }
  .hero { min-height: 400px; }
</style>

<link rel="preload" href="/styles/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles/main.css"></noscript>

10.3. 如何优化首屏加载时间?

常见策略:

  • 关键资源优先加载
  • 首屏关键 CSS 内联
  • 代码分割,只加载首页需要的代码
  • 使用 SSR 或 SSG,减少首屏等待
  • 使用骨架屏提升感知速度
  • 预加载首屏关键图片、字体、样式
javascript 复制代码
const HomePage = lazy(() => import('./HomePage'));
const ProductPage = lazy(() => import('./ProductPage'));

function App() {
  return (
    <Suspense fallback={<SkeletonLoader />}>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="/product" element={<ProductPage />} />
      </Routes>
    </Suspense>
  );
}

十一、前端性能优化最佳实践总结

11. 前端性能优化最佳实践

11.1 加载优化

  • 减少 HTTP 请求数量
  • 启用 Gzip / Brotli 压缩
  • 使用 CDN
  • 配置合理缓存策略
  • 优化关键渲染路径
  • 提前加载关键资源

11.2 渲染优化

  • 提取关键 CSS
  • 减少阻塞渲染资源
  • 避免频繁重排重绘
  • 优化动画属性使用

11.3 JavaScript 优化

  • 代码分割与懒加载
  • Tree Shaking
  • 避免长任务阻塞主线程
  • 使用 Web Workers 处理重计算
  • 及时清理事件和定时器

11.4 列表与交互优化

  • 长列表使用虚拟滚动
  • 滚动事件防抖节流
  • 避免不必要的重复渲染

11.5 图片与静态资源优化

  • 使用现代图片格式
  • 控制资源体积
  • 按需加载非首屏资源
  • 优化字体加载策略

11.6 监控与工程化

  • 建立性能监控体系

  • 设置性能预算

  • 定期进行性能测试

  • 持续关注 Core Web Vitals

  • 在开发流程中贯彻性能优先理念

相关推荐
不爱说话郭德纲7 小时前
出门在外收到任务,我用 TRAE SOLO 把电脑“叫醒”干活
前端·ai编程
前端Hardy7 小时前
这个前端动画库,火了!
前端·javascript
小林攻城狮7 小时前
Vite项目使用@turbodocx/html-to-docx报错问题排查与解决方案
前端·ai编程
Asmewill7 小时前
LangGraph学习笔记六(Stream流式输出)
前端
Asmewill7 小时前
LangGraph学习笔记七(checkpointer)
前端
前端小木屋7 小时前
uniapp与蓝牙设备连接详细步骤
前端·微信小程序
yingyima7 小时前
Go 语言定时任务速查手册:实现延迟与周期任务的高效方法
前端
卷帘依旧8 小时前
npm包发布和管理流程(AI生成)
前端
小小小小宇8 小时前
前端端内H5调试方法与原理
前端