LCP 结果与性能 API 完全相反,而不是 pagespeed insights 或 webpagetest

LCP result is totally opposite from performance API than the pagespeed insights or webpagetest

我正在尝试优化 LCP for this page。我阅读了一篇关于 LCP 优化的文章,其中我还找到了一个脚本,它可以帮助确定 LCP 的哪一部分花费了最多的时间。脚本:

const LCP_SUB_PARTS = [
  'Time to first byte',
  'Resource load delay',
  'Resource load time',
  'Element render delay',
];

new PerformanceObserver((list) => {
  const lcpEntry = list.getEntries().at(-1);
  const navEntry = performance.getEntriesByType('navigation')[0];
  const lcpResEntry = performance
    .getEntriesByType('resource')
    .filter((e) => e.name === lcpEntry.url)[0];

  // Ignore LCP entries that aren't images to reduce DevTools noise.
  // Comment this line out if you want to include text entries.
  if (!lcpEntry.url) return;

  // Compute the start and end times of each LCP sub-part.
  // WARNING! If your LCP resource is loaded cross-origin, make sure to add
  // the `Timing-Allow-Origin` (TAO) header to get the most accurate results.
  const ttfb = navEntry.responseStart;
  const lcpRequestStart = Math.max(
    ttfb,
    // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
    lcpResEntry ? lcpResEntry.requestStart || lcpResEntry.startTime : 0
  );
  const lcpResponseEnd = Math.max(
    lcpRequestStart,
    lcpResEntry ? lcpResEntry.responseEnd : 0
  );
  const lcpRenderTime = Math.max(
    lcpResponseEnd,
    // Prefer `renderTime` (if TOA is set), otherwise use `loadTime`.
    lcpEntry ? lcpEntry.renderTime || lcpEntry.loadTime : 0
  );

  // Clear previous measures before making new ones.
  // Note: due to a bug this does not work in Chrome DevTools.
  // LCP_SUB_PARTS.forEach(performance.clearMeasures);

  // Create measures for each LCP sub-part for easier
  // visualization in the Chrome DevTools Performance panel.
  const lcpSubPartMeasures = [
    performance.measure(LCP_SUB_PARTS[0], {
      start: 0,
      end: ttfb,
    }),
    performance.measure(LCP_SUB_PARTS[1], {
      start: ttfb,
      end: lcpRequestStart,
    }),
    performance.measure(LCP_SUB_PARTS[2], {
      start: lcpRequestStart,
      end: lcpResponseEnd,
    }),
    performance.measure(LCP_SUB_PARTS[3], {
      start: lcpResponseEnd,
      end: lcpRenderTime,
    }),
  ];

  // Log helpful debug information to the console.
  console.log('LCP value: ', lcpRenderTime);
  console.log('LCP element: ', lcpEntry.element);
  console.table(
    lcpSubPartMeasures.map((measure) => ({
      'LCP sub-part': measure.name,
      'Time (ms)': measure.duration,
      '% of LCP': `${
        Math.round((1000 * measure.duration) / lcpRenderTime) / 10
      }%`,
    }))
  );
}).observe({type: 'largest-contentful-paint', buffered: true});

对我来说,这是开始时 4 倍 CPU 减速和 Fast3G 连接的结果。

在那之后,由于渲染延迟是我应该关注的领域,我将一些脚本移到了页脚,并将“延迟”脚本设为“异步”。这是结果:

我们可以看到更改后 LCP 有明显的改进,但是,当我使用灯塔进行测试时,结果有所不同。

之前:

之后:

我现在对采取什么步骤感到进退两难。请推荐!!

我 运行 您在问题中链接的 URL 的痕迹,我注意到的第一件事是您的 LCP 资源在页面中很早就完成加载,但事实并非如此能够呈现,直到名为 mirage2.min.js 的文件完成加载。

这解释了为什么 LCP 的“元素呈现延迟”部分如此长,将脚本移至页面底部或查看其中的 defer 并不能解决该问题。解决方案是让您的 LCP 图像可以渲染,而无需等到 JavaScript 文件完成加载。

我注意到的另一件事是这个 mirage2.min.js 文件是从 ajax.cloudflare.com 加载的,这让我认为这是 Cloudflare 提供的“功能”,而不是您自己设置的东西。

根据我在这里看到的内容,我假设这是真的: https://support.cloudflare.com/hc/en-us/articles/219178057

所以我建议您关闭此功能,因为它显然对您的 LCP 没有帮助,正如您在此跟踪中看到的那样:

你说的还有一件事我认为值得澄清:

After that, since render delay was the area where I should focus on, I moved some of the scripts to the footer and also made the "deferred" scripts "async". This is the result:

当我查看您的“结果”屏幕截图时,我仍然看到“元素渲染延迟”部分仍然 > 50%,所以当您说“渲染延迟是我应该的区域”时您是正确的专注于”,事实上在您进行更改后它仍然很高(例如移动脚本并使用 defer/async)表明您尝试的更改没有解决问题。

在这种情况下,我相信如果您关闭 Cloudflare 仪表板中的“Mirage”功能,您应该会看到很大的改进。


哦,还有一件事,我注意到您在图片上使用了 importance="high"。这是不再有效的旧语法。您应该将其替换为 fetchpriority="high" 。有关详细信息,请参阅此 post:https://web.dev/priority-hints/