如何在移动设备上获得 Google PageSpeed Insights 100 分

2025-06-04

如何在移动设备上获得 Google PageSpeed Insights 100 分

Google PageSpeed Insights是一款用于测量网站感知延迟的工具。获得良好的评分至关重要,因为 Google 已宣布将把这些评分作为其搜索排名算法的输入。

我们着手研究如何在移动设备上获得 PageSpeed Insights 100 分。开始这项工作时,我们在桌面端的得分已经达到了 100 分,但现代商务是移动商务,而我们的得分只有 65 分左右。在这篇博文中,我们将分享一些方法,让您的网站在移动设备上也能获得 100 分。许多公司都声称在桌面端能达到 100 分,但在移动设备上达到 100 分则有些难以实现。让我们深入探讨一下。

Builder.io 是一个标准的 Next.js 网站。由于该网站本身运行在 Builder 内容平台上,因此内容已经遵循了图像大小、预加载等方面的所有最佳实践。然而,它的得分仍然只有 60 多分。为什么呢?

替代文本

它有助于查看构成分数的细目分类。

替代文本

该问题可以分解为:

  • TBT/TTI:JavaScript 导致页面阻塞时间过长。
  • FCP/LCP:页面内容太多,无法在移动浏览器上呈现。

因此,我们的目标是:

  1. 减少 JavaScript 的数量。
  2. 减少初始渲染的内容量。

为什么有这么多 JavaScript?

我们的主页本质上是一个静态页面。为什么它需要 JavaScript?因为主页是一个 Next.js 网站,这意味着它是一个 React 应用程序(我们使用Mitosis将拖放编辑器的输出转换为 React 格式)。虽然网站的绝大部分内容都是静态的,但有三项需要 JavaScript:

  1. 导航系统:菜单需要交互性,因此需要 JavaScript。此外,桌面设备和移动设备使用的菜单也有所不同。
  2. 我们需要加载一个聊天小部件
  3. 我们需要谷歌分析。

让我们分别深入探讨每一个。

应用程序引导

尽管这主要是一个静态网站,但它仍然是一个应用程序。为了使菜单正常工作,应用程序需要引导。具体来说,它需要运行 rehydration,框架会将模板与 DOM 进行比较,并安装所有 DOM 监听器。此过程使现有框架具有可重放性。换句话说,即使页面 95% 的内容是静态的,框架也必须下载所有模板并重新执行它们以确定监听器是否存在。这意味着该网站被下载了两次,一次以 HTML 格式,另一次以 JavaScript 中的 JSX 格式。

更糟糕的是,rehydration 过程非常缓慢。框架必须访问每个 DOM 节点并将其与 VDOM 进行协调,这需要时间。而且 rehydration 过程不能延迟,因为它与安装 DOM 监听器的过程相同。延迟 rehydration 会导致菜单无法正常工作。

我们上面描述的是所有现有框架的根本限制。你看,它们都是可重放的。这也意味着,没有一个现有框架能让你在真实网站的移动端跑出 100 分。HTML 和 JavaScript 的数量实在太多,无法塞进 PageSpeed 为移动端分配的极小空间里。

我们需要从根本上重新思考这个问题。由于网站的大部分内容都是静态的,我们不应该用 JavaScript 重新下载这部分内容,也不应该为不需要的内容付费。这正是Qwik真正闪耀的地方。Qwik 是可续播的,而不是可重播的,这正是它与众不同之处。因此,Qwik 无需:

  1. 在页面加载时进行引导
  2. 遍历 DOM 来确定监听器的位置
  3. 急切地下载并执行 JavaScript 以使菜单正常工作

以上所有内容意味着实际上不需要 JavaScript 来执行站点加载,但我们可以保留站点的所有交互性。

对讲机

替代文本

Intercom 是我们网站上运行的第三方小部件,它使我们能够与客户互动。安装它的标准方法是将一段 JavaScript 代码放入 HTML 中,如下所示:



<script type="text/javascript" async="" src="https://widget.intercom.io/widget/abcd1234"></script>
<script async defer>
Intercom('boot', {app_id: 'abcd1234'}
</script>


Enter fullscreen mode Exit fullscreen mode

但是,上述情况存在两个问题:

  1. 它添加了需要下载和执行的 JavaScript。这将计入我们的 TBT/TTI。
  2. 这可能会导致布局偏移,从而违反 CLS。这是因为 UI 最初渲染时没有使用 Widget,而随着 JavaScript 的下载和执行,再次渲染时会使用 Widget。

Qwik 同时解决了这两个问题。

首先,它抓取 Intercom 用于渲染小部件的 DOM。接下来,将 DOM 插入到实际页面中,如下所示:



<div class="intercom-lightweight-app" aria-live="polite">
  <div
    class="intercom-lightweight-app-launcher intercom-launcher"
    role="button"
    tabIndex={0}
    arial-abel="Open Intercom Messenger"
    on:click='ui:boot_intercom'
  >
    ...
 </div>
 <style id="intercom-lightweight-app-style" type="text/css">...</style>
</div>


Enter fullscreen mode Exit fullscreen mode

这样做的好处是,小部件可以与应用程序的其他部分即时渲染。浏览器下载 Intercom JavaScript 并执行小部件创建时,不会出现任何延迟或闪烁。这会带来更好的用户体验和更快的网站启动速度。(它还能节省移动设备的带宽。)

然而,我们仍然需要一种方法来检测对 Widget 的点击,以及一些代码,以便在用户与 Widget 交互时将模拟 Widget 替换为实际的 Intercom Widget。这可以通过属性实现。该属性指示 Qwik在用户点击模拟 Widget 时on:click="ui:boot_intercom"进行下载。boot_intercom.js

内容:boot_intercom.js



export default async function(element) {
 await import('https://widget.intercom.io/widget/abcd1234');
 const container = element.parentElement;
 const body = container.parentElement;
 body.removeChild(container);
 Intercom('boot', { app_id: 'abcd1234' });
 Intercom('show');
}


Enter fullscreen mode Exit fullscreen mode

上面的文件会下载真正的 Intercom 小部件,移除模拟文件,并启动 Intercom。所有这一切自然发生,用户甚至不会察觉到切换。

谷歌分析

到目前为止,我们在延迟 JavaScript 执行方面取得了显著成效,从而提升了网站的性能。但分析功能则不同,因为我们无法延迟它,必须立即启动它。单靠启动分析功能,我们无法在移动版 PageSpeed Insights 上获得 100 分。为了解决这个问题,我们将使用PartyTown在 Web Worker 中运行 GoogleAnalytics 。稍后我会详细介绍。

JavaScript 延迟

上述工作将网站需要下载和执行的 JavaScript 数量降低到约 1KB,执行时间仅为 1 毫秒。本质上,几乎无需等待。如此少的 JavaScript 代码量使我们能够在 TBT/TTI 测试中获得满分。

HTML 延迟

然而,即使基本上没有 JavaScript,如果我们不解决发送到客户端用于首屏渲染的 HTML 数量问题,我们仍然无法在移动端获得 100 分。为了改进 FCP/LCP,我们必须将其缩减到最低限度。这可以通过仅发送首屏渲染的 HTML 来实现。

这并非新想法,但执行起来却颇为艰难。现有的框架让这变得困难,因为没有简单的方法将应用程序拆分成首屏上方和下方的部分。VDOM 在这方面毫无用处,因为即使只投影了其中的一部分,应用程序也会生成整个 VDOM。如果部分 VDOM 缺失,框架会在 rehydration 时重新创建整个网站,这会导致初始引导工作量进一步增加。

理想情况下,我们希望不发布首屏以下的 HTML,同时在首屏以上保持一个完全交互的菜单系统。但实际上,这很难做到,因为目前这类最佳实践的缺乏就足以证明这一点。这太难了,所以没人这么做。

Qwik 以 DOM 为中心,这让它与众不同。整个页面在服务器上渲染。然后,页面中不需要加载的部分会被定位并移除。随着用户滚动,缺失的部分会被延迟下载并插入。Qwik 不介意这类 DOM 操作,因为它是无状态的,并且以 DOM 为中心。

以下是我们服务器上的实际代码,可实现网站首屏以下的延迟加载:



  async render(): Promise<void> {
    await (this.vmSandbox.require('./server-index') as ServerIndexModule).serverIndex(this);
    const lazyNode = this.document.querySelector('section[lazyload=true]');
    if (lazyNode) {
      const lazyHTML = lazyNode.innerHTML;
      lazyNode.innerHTML = '';
      (lazyNode as HTMLElement).style.height = '999em';
      lazyNode.setAttribute('on:document:scroll', 'ui:/lazy');
      this.transpiledEsmFiles['lazy.js'] = `
        export default (element) => {
          element.removeAttribute('on:document:scroll');
          element.style.height = null;
          element.innerHTML = ${JSON.stringify(lazyHTML)};
        };`;
    }
  }


Enter fullscreen mode Exit fullscreen mode

代码简单明了,但使用任何现有框架都很难实现。

查看下面的折叠延迟加载的实际操作:

替代文本

请注意,页面首次加载时,首屏以下内容尚未加载;用户滚动页面后,内容便会填充。由于无需执行任何复杂的代码,因此加载过程几乎是即时的。只需一个快速而直接的innerHTML

尝试一下

您可以在此处亲自体验该页面:https://www.builder.io/? render=qwik 。(并查看PageSpeed上的分数)我们仍然缺少分析功能,但很快就会推出。

喜欢吗?我们计划让每一位 Builder.io 用户都能使用 Qwik,让他们的网站开箱即用,速度飞快。你从未见过如此快速的平台。

替代文本

替代文本

替代文本

以上内容让你兴奋不已?那就加入我们的团队,帮助我们加速网络吧!

文章来源:https://dev.to/builderio/how-to-score-100-on-google-pagespeed-insights-on-mobile-2e0i
PREV
现代 JavaScript 中的安全数据获取
NEXT
30 多个免费 CRUD 应用程序模板,帮助加快开发速度