阐述 `First Contentful Paint (FCP)` 和 `Largest Contentful Paint (LCP)` 优化策略,以及 `Critical CSS` 的提取。

各位靓仔靓女,晚上好!我是今晚的讲师,老码农一枚。今天咱聊聊前端性能优化里两个重要的指标:First Contentful Paint (FCP) 和 Largest Contentful Paint (LCP),以及优化它们的关键技术:Critical CSS。 保证讲得通俗易懂,干货满满,希望大家听完能有所收获。

开场白:性能,用户体验的基石

各位,咱们做前端的,说白了就是给用户提供服务的。用户体验好不好,直接关系到产品的生死存亡。你想啊,如果一个网站打开慢得像蜗牛爬,谁还有耐心等你?用户分分钟就跑去竞争对手那里了。而FCP和LCP,就是衡量用户体验的重要指标,直接影响用户的第一印象。

第一部分:FCP (First Contentful Paint) – 你的网站有多快“露脸”

1. 什么是FCP?

FCP,顾名思义,指的是浏览器首次渲染任何文本、图像、非白色canvas或SVG的时间点。简单来说,就是用户第一次看到页面内容的时间。这个时间越短,用户感觉你的网站加载越快。

2. 为什么FCP很重要?

想象一下,你打开一个网站,一片空白,啥也没有,你会不会觉得很焦虑?FCP就是用来衡量这种“焦虑”程度的。一个好的FCP能让用户知道“嘿,网站在加载了,不是死机了”,从而降低他们的焦虑感,提高用户留存率。

3. 如何测量FCP?

测量FCP的方法有很多,最常用的是通过浏览器的Performance API。

// 在浏览器控制台中运行
new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntriesByName('first-contentful-paint')) {
    console.log('FCP:', entry.startTime);
  }
}).observe({ type: 'paint', buffered: true });

这段代码会在浏览器控制台中输出FCP的时间。也可以使用Lighthouse、PageSpeed Insights等工具来测量FCP。

4. FCP优化策略

  • 减少HTTP请求:

    • 合并文件: 将多个CSS和JavaScript文件合并成一个,减少HTTP请求的数量。可以使用Webpack、Parcel等打包工具来实现。

      // webpack.config.js
      module.exports = {
      // ...
      optimization: {
      splitChunks: {
        cacheGroups: {
          vendor: {
            test: /[\/]node_modules[\/]/,
            name: 'vendors',
            chunks: 'all',
          },
        },
      },
      },
      };
    • 使用CSS Sprites: 将多个小图标合并成一张大图,减少HTTP请求的数量。可以使用像gulp-spritesmith 这样的工具。

    • Inline critical resources: 嵌入关键CSS到HTML中,避免额外的HTTP请求。这个我们稍后会详细讲到Critical CSS。

  • 优化服务器响应时间 (TTFB):

    • 使用CDN: 将静态资源分发到全球各地的CDN节点,让用户从离他们最近的节点获取资源。
    • 优化后端代码: 检查数据库查询、缓存策略等,确保服务器能快速响应请求。
    • 启用Gzip压缩: 压缩HTML、CSS、JavaScript等资源,减少传输体积。

    在你的服务器配置里(比如Nginx):

    gzip on;
    gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/xml+rss image/svg+xml;
    gzip_comp_level 6;
    gzip_vary on;
    gzip_disable "msie6";
  • 优化资源加载顺序:

    • 优先加载关键资源: 将首屏需要的CSS和JavaScript放在<head>中,尽快加载。
    • 延迟加载非关键资源: 使用asyncdefer属性延迟加载非关键JavaScript文件。
      <script src="script.js" async></script>
      <script src="script.js" defer></script>

      async 会异步加载脚本并在加载完成后立即执行,不阻塞HTML解析。
      defer 会异步加载脚本,但会等到HTML解析完成后再执行,保证执行顺序。

  • 使用浏览器缓存:

    • 设置正确的Cache-Control头: 告诉浏览器哪些资源可以缓存,以及缓存的时间。
      Cache-Control: public, max-age=31536000
  • 避免阻塞渲染的JavaScript和CSS:

    • 移除无用的CSS和JavaScript: 减少不必要的代码,减少浏览器解析和执行的时间。
    • Code Splitting: 使用Webpack等工具将代码分割成多个小块,按需加载。

第二部分:LCP (Largest Contentful Paint) – 你的网站有多快“画完”

1. 什么是LCP?

LCP,指的是在viewport中最大的可见元素完成渲染的时间点。这个元素可以是图像、视频、background-image、块级文本元素等。简单来说,就是用户看到页面上最大的内容的时间。

2. 为什么LCP很重要?

LCP比FCP更贴近用户体验。一个好的FCP能让用户知道网站在加载,但如果LCP很慢,用户可能会觉得“等了半天,就加载了这么点东西”。LCP直接影响用户对页面加载速度的感知。

3. 如何测量LCP?

和FCP一样,可以使用Performance API来测量LCP。

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP:', entry.startTime, entry.url, entry.size);
  }
}).observe({ type: 'largest-contentful-paint', buffered: true });

这段代码会在浏览器控制台中输出LCP的时间、URL和大小。同样也可以使用Lighthouse、PageSpeed Insights等工具来测量LCP。

4. LCP优化策略

  • 优化服务器响应时间 (TTFB): 和FCP一样,TTFB是LCP的关键因素。

  • 优化资源加载时间:

    • 优化图片:

      • 选择合适的图片格式: 使用WebP格式,它可以提供更好的压缩率和质量。
      • 压缩图片: 使用工具如TinyPNG、ImageOptim等压缩图片,减小文件大小。
      • 使用响应式图片: 根据用户的设备屏幕大小加载不同尺寸的图片。
        <img
        srcset="small.jpg 480w,
              medium.jpg 800w,
              large.jpg 1200w"
        sizes="(max-width: 480px) 480px,
             (max-width: 800px) 800px,
             1200px"
        src="large.jpg"
        alt="My Image">
      • 使用CDN: 将图片分发到全球各地的CDN节点,让用户从离他们最近的节点获取图片。
    • 优化视频:

      • 压缩视频: 使用工具如FFmpeg等压缩视频,减小文件大小。
      • 使用流媒体: 使用HLS、DASH等流媒体协议,根据用户的网络状况动态调整视频质量。
      • 使用CDN: 将视频分发到全球各地的CDN节点,让用户从离他们最近的节点获取视频。
  • 优化渲染阻塞资源:

    • Critical CSS: 这个我们接下来会详细讲到。
    • 预加载关键资源: 使用<link rel="preload">预加载LCP元素所需的资源。
      <link rel="preload" href="image.jpg" as="image">
  • 避免客户端渲染:

    • 使用服务端渲染 (SSR): 在服务器端渲染HTML,将完整的HTML发送给浏览器,避免客户端渲染的延迟。可以使用Next.js、Nuxt.js等框架来实现SSR。
    • 预渲染 (Prerendering): 在构建时生成HTML,将静态HTML发送给浏览器。可以使用预渲染工具如prerender-spa-plugin

第三部分:Critical CSS – 优先加载“骨架”

1. 什么是Critical CSS?

Critical CSS,也叫Above-the-Fold CSS,指的是渲染首屏内容所需的最小CSS集合。简单来说,就是让用户在第一时间看到页面“骨架”的CSS。

2. 为什么Critical CSS很重要?

如果没有Critical CSS,浏览器需要加载完整的CSS文件才能开始渲染页面。这会导致页面出现“白屏”现象,用户体验很差。有了Critical CSS,浏览器可以先加载Critical CSS,渲染出页面的“骨架”,然后再加载完整的CSS文件,从而提高用户的感知速度。

3. 如何提取Critical CSS?

提取Critical CSS的方法有很多,最常用的是使用工具。

  • 在线工具: 像CriticalCSS.com这样的在线工具,可以输入URL,自动提取Critical CSS。
  • npm包: 有很多npm包可以用来提取Critical CSS,如criticalpenthouse等。

    critical为例:

    npm install critical --save-dev
    // 使用critical
    const critical = require('critical');
    
    critical.generate({
      inline: false, // 是否将critical CSS内联到HTML中
      base: 'dist/', // 你的网站的根目录
      src: 'index.html', // HTML文件路径
      target: {
        css: 'critical.css', // 输出的critical CSS文件路径
        html: 'index.html' // 修改后的HTML文件路径
      },
      minify: true, // 是否压缩CSS
      extract: false, // 是否提取所有CSS规则
      width: 1300, // 屏幕宽度
      height: 900 // 屏幕高度
    }).then(output => {
      console.log("Critical CSS generated!");
    }).catch(err => {
      console.error(err);
    });

4. 如何使用Critical CSS?

提取Critical CSS后,需要将它内联到HTML的<head>中,并使用media="print"onload="this.removeAttribute('media');"异步加载完整的CSS文件。

<head>
  <style>
    /* Critical CSS */
    body {
      font-family: sans-serif;
      margin: 0;
    }
    /* ... 其他关键CSS ... */
  </style>
  <link rel="stylesheet" href="style.css" onload="this.removeAttribute('media');" media="print">
  <noscript><link rel="stylesheet" href="style.css"></noscript>
</head>
  • onload="this.removeAttribute('media');": 这种方法会在完整的CSS文件加载完成后,将media属性移除,从而应用CSS样式。
  • <noscript><link rel="stylesheet" href="style.css"></noscript>: 如果用户禁用了JavaScript,则会加载完整的CSS文件。

总结:优化FCP和LCP,打造极速体验

指标 含义 优化策略
FCP 浏览器首次渲染任何文本、图像、非白色canvas或SVG的时间点。 1. 减少HTTP请求 2. 优化服务器响应时间 (TTFB) 3. 优化资源加载顺序 4. 使用浏览器缓存 5. 避免阻塞渲染的JavaScript和CSS
LCP 在viewport中最大的可见元素完成渲染的时间点。 1. 优化服务器响应时间 (TTFB) 2. 优化资源加载时间 (图片/视频) 3. 优化渲染阻塞资源 (Critical CSS, 预加载) 4. 避免客户端渲染 (SSR, 预渲染)
Critical CSS 渲染首屏内容所需的最小CSS集合。 1. 使用工具提取Critical CSS 2. 将Critical CSS内联到HTML的<head>中 3. 使用media="print"onload="this.removeAttribute('media');"异步加载完整的CSS文件。 4. <noscript><link rel="stylesheet" href="style.css"></noscript>防止JS禁用。

总而言之,优化FCP和LCP是一个系统工程,需要从服务器端到客户端进行全方位的优化。希望今天的分享能帮助大家更好地理解和优化FCP和LCP,打造极速的用户体验。

结束语:性能优化,永无止境

各位,性能优化是一个持续不断的过程,没有最好,只有更好。希望大家在实际项目中不断尝试、总结,找到最适合自己的优化方案。

今天的讲座就到这里,谢谢大家!如果大家有什么问题,欢迎提问。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注