Skip to content

性能优化-LCP

性能优化- 提升 LCP(Largest Contentful Paint 最大内容绘制)

简介

LCP 就是网页中最大的一部分加载完成的时间(从用户感知页面到基本加载完成的时间,也称为最大内容绘制)

LCP 是 Core Web Vitals 的三个关键指标之一,Core Web Vitals 是 Google 用于评估网页用户体验的标准之一。为了获得良好的用户体验,Google 建议 LCP 时间在 2.5 秒以内。如果 LCP 超过 4 秒,则需要进行优化

Google将LCP看做提高搜索引擎排名的参数之一

测量方式

Lighthouse

LCP通常在Google浏览器的这个部分可以看到 image.png

代码测量

👉纯html页面

接下来我们就手写代码手动测量一下网页的LCP部分

javascript
// 初始化 LCP 存储
let lcp = 0;

// 使用 PerformanceObserver 来监听 largest-contentful-paint
const observer=new PerformanceObserver((entryList) => {
    const entries=entryList.getEntries();
    console.log(entries,'entries');
    entries.forEach((entry) => {
       if (entry.entryType === 'largest-contentful-paint') {
           if(entry.startTime > lcp){
            lcp = entry.startTime;
            console.log('LCP值为+'+lcp);
            document.getElementById('lcp').textContent = lcp.toFixed(2) + 'ms';
           } 
        }
    })
})

// 观察 largest-contentful-paint 事件
observer.observe({ type: 'largest-contentful-paint', buffered: true });

👉在vue2之中使用

javascript
<template>
  <div>
    <p>LCP: {{ lcp }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      lcp: 0, // 用于存储 LCP 的最大值
    };
  },
  mounted() {
    // 使用 PerformanceObserver 来观察 LCP
    const observer = new PerformanceObserver((entryList) => {
      const entries = entryList.getEntries();
      entries.forEach((entry) => {
        if (entry.entryType === 'largest-contentful-paint') {
          // 更新 LCP 值为最大的 LCP
          if (entry.startTime > this.lcp) {
            this.lcp = entry.startTime;
            console.log(`LCP: ${this.lcp}`);
          }
        }
      });
    });

    // 观察 largest-contentful-paint 事件
    observer.observe({ type: 'largest-contentful-paint', buffered: true });
  },
};
</script>

其他方式

  • Google PageSpeed Insights:提供对 LCP 的详细分析,并提出优化建议。
  • Web Vitals 扩展:Google Chrome 浏览器的 Web Vitals 扩展可以实时监控 LCP。
  • Lighthouse:Lighthouse 是一个开源工具,用于分析网页性能,包含对 LCP 的评估。
  • Web.dev:这是一个由 Google 提供的在线工具,用于测试网页性能,并生成优化建议。

触发元素

LCP最常见的容易触发的包含以下部分:

  • 图像 (<img> 元素)
  • 图片背景 (<image> 或 CSS background-image)
  • 块级文本元素(如 <div>, <p>, <h1> 等)
  • 视频海报 (<video> 元素内的 poster 属性)

这些元素在视口内加载时,浏览器会记录它们的渲染时间,并将其中加载时间最长的元素作为 LCP

优化 LCP

优化LCP也是从上面的元素入手进行优化

CSS 和 JavaScript

避免使用阻塞渲染的 CSS 和 JavaScript,我们可以将 CSS 放在 <head>,js放入底部同时使用使用 asyncdefer 属性

简化DOM 和 CSSOM 树

减少不必要的 HTML 和 CSS,避免深层嵌套结构

利用浏览器缓存

缓存静态资源,如 CSS 和 JavaScript 文件,减少重新加载时间

优化图片和其他资源

使用现代格式的压缩图片,减少图片大小,使用懒加载技术避免加载不在视口中的图片

LCP实际使用

静态资源处理

图像和媒体处理

图像通常是影响 LCP 的主要因素,因为它们往往是页面中最大的内容。优化图像可以显著提升 LCP

👉 图片压缩

图片压缩模块这里我使用的是熊猫压缩(https://tinypng.com/

使用现代图像格式(如 WebP 或 AVIF),应用适当的压缩技术,减少图像文件大小。

👉 设置正确的图像尺寸

使用响应式图像 (**srcset**** 和 **sizes** 属性) 根据设备尺寸加载合适的图像**

👉 非关键图像懒加载

使用 loading="lazy" 属性延迟加载页面中不可见的图像,减少初始页面加载时间。

服务器响应时间优化

服务器响应时间直接影响 LCP值,服务器需要在页面开始加载之前发送初始 HTML 文档。为了优化服务器响应时间,可以:

  • 使用CDN (内容分发网络) :利用CDN 缓存网站内容,将其分发到用户最近的服务器,减少延迟。
  • 优化服务器配置:提高服务器处理请求的性能,使用快速的 Web 服务器(如 Nginx 或 Apache)。
  • 减少后端处理时间:优化数据库查询,减少不必要的处理,使用缓存技术(如 Redis 或 Memcached)。

优先加载关键资源

关键资源(如 CSS 和大块的主要内容)第一步加载,避免阻塞页面的渲染

👉延迟加载非关键资源

将非关键的 JavaScript 和样式表设置为异步加载或延迟加载,以确保关键内容优先加载。

👉使用 HTTP/2

HTTP/2 可以并行加载多个资源,有效减少加载时间。

👉内联关键 CSS

将页面折叠部分(above-the-fold)的关键 CSS 直接内联到 HTML 文档中,以减少首次渲染所需的时间。

👉使用 **preload** 指令

对关键资源(如字体、重要图片)使用 <link rel="preload"> 标签预加载让资源快速加载和呈现

使用 Preload指令 和 Prefetch 预加载关键资源

减少第三方脚本

第三方脚本(如广告、社交媒体小部件、分析工具)会显著拖慢页面加载速度

👉异步加载脚本:使用 asyncdefer 属性,避免脚本阻塞页面渲染

👉减少不必要的第三方脚本:只加载必要的第三方服务,去除不必要的脚本

javascript
vue 项目中使用 splitChunks 配置处理import 动态加载组件的方式
减少初始化项目时的 js 资源体积。

// 懒加载非初始化必须的组件
const CopyrightMeta = import('./components/CopyrightMeta')

类似 element-ui 和 lodash 之类第三方库按需加载

使用浏览器缓存

利用浏览器缓存可以减少重复请求,提高页面速度

👉设置适当的缓存头

不同静态资源(如图像、CSS 和 JavaScript 文件)具有合适的缓存策略,用户在后续访问时可以直接从缓存中加载资源。

👉利用Service Workers (服务工作线程)

Service Workers可以在用户的浏览器中缓存资源,减少后续访问时的加载时间。

优化 CSS 和字体加载

👉最小化和压缩 CSS:删除不必要的空格、注释和代码,并压缩 CSS 文件,减少文件大小。

👉字体显示策略:使用 font-display 属性来控制自定义字体的加载行为,避免阻塞文本渲染。

字体显示策略

为了提升视觉效果和品牌一致性,许多网站使用自定义字体。然而,自定义字体的使用也会引发一些性能问题,比如增加网页的加载时间,导致文本闪烁或不可见。这些问题会对用户体验产生负面影响。

为了更好地控制字体加载行为,CSS 提供了 font-display 属性,它允许开发者指定在字体加载时,浏览器如何处理文本的显示。通过合理使用字体显示策略,可以优化网页的加载体验,确保在字体加载过程中为用户提供最佳的视觉体验。

font-display 的值

font-display 属性有多个可能的值,每个值代表一种不同的字体显示策略:

javascript
// font-display:'auto',  // 默认值
浏览器将根据字体的加载情况决定显示方式。通常遵循浏览器的默认行为


// font-display:'block',
在字体加载完成之前,文本不可见
字体加载完成后,文本会立即显示
这种方式会造成内容的“闪烁”(FOIT,Flash of Invisible Text)。


// font-display:'swap',
在字体加载完成之前,使用系统字体或备用字体展示文本
字体加载完成后,立即切换为目标字体
这种方式通常用于避免文本的闪烁,提升用户体验。


// font-display:'fallback',
在字体加载完成之前,使用系统字体或备用字体展示文本
如果字体加载时间超过一定的延迟(通常是 3 秒),则继续使用备用字体
直到页面关闭或刷新。能减少字体加载时间对页面表现的影响


// font-display:'optional',
在字体加载完成之前,使用系统字体或备用字体展示文本。
如果字体加载的延迟很高,甚至浏览器可能放弃加载目标字体,直接使用备用字体
用于优化页面性能和响应速度。

使用 font-display 策略

  • 快速显示文本:如果优先考虑页面内容的快速展示,可以使用 swapoptional,确保在字体加载过程中文本总是可见。
  • 确保一致的视觉效果:如果视觉一致性和自定义字体的使用是优先考虑的,可以选择 blockfallback,在字体加载后呈现自定义字体。
  • 性能优先:在移动端或性能敏感的应用中,使用 optional 可以减少字体加载对性能的影响。

针对 LCP 指标具体来说就是使用 font-display: swap; 使浏览器在加载字体的同时立即使用后备字体呈现文本。当自定义字体加载完成后,后备字体将被替换为自定义字体,这种策略被称为“闪烁的无样式文本”(Flash of Unstyled Text, FOUT)

plain
@font-face {
  font-family: 'IconFont';
  src: url('iconfont.woff2') format('woff2');
  font-display: swap;
}

优点: 文本始终可见,避免了空白文本的问题,提高了可读性。
缺点: 字体切换可能导致短暂的视觉不一致。

Released under the MIT License.