如何消除第三方脚本带来的网站臃肿问题

746 阅读9分钟

派对镇如何消除第三方脚本带来的网站臃肿现象

良好的用户体验始于即时加载的页面。普通用户不会花太多时间等待网页加载或与网页互动。根据谷歌的数据,如果一个页面的加载时间从1秒上升到3秒,用户跳出的概率会增加32%。然而,要保持网站的高性能并不容易。而缓慢的网站在某种程度上是一种歧视。世界上大多数人都没有机会使用高速互联网或快速的CPU。即使你的网站在设计时考虑到了可用性,这些因素也阻碍了用户充分受益于网站的功能。

这就是为什么在建设网站时,性能是至关重要的。性能需要从代码层面开始建立,而以用户为中心的指标,如交互时间(TTI)、总阻塞时间(TBT)和首次输入延迟(FID),有助于你衡量一个网站的速度。但是,现代的网页是沉重的,而且大小不断增加(被亲切地称为 "网站膨胀")。普通的网页超过2兆字节大,有超过200个请求。庞大、笨重的网站,嵌入了几个第三方脚本,其背后通常是令人沮丧的用户体验。当你的网站需要这些第三方脚本来运行你的业务时,就像大多数网站一样,你的手上有一个巨大的挑战。

你如何在不影响重要功能的情况下提高你的关键性能指标并让你的用户满意?

JavaScript税

众所周知,JavaScript是网站臃肿的主要罪魁祸首之一。提供丰富的、互动的网站体验需要增加资产,消耗你的用户资源,从CPU和GPU到内存和网络。抛开大型图片和视频,第三方脚本,如像素跟踪器、A/B测试、广告、小工具、CDN等,通常是性能拼图中最大的一块。第三方脚本是嵌入在你的网站中的代码,不直接由你的开发人员控制,它们与网站自己的代码竞争浏览器的主线程,这就延迟了内容的渲染,使网站感觉迟缓。

同样重要的是要记住,你的终端用户的移动设备远没有你的网站建立时那么复杂。你的网站上所有的JavaScript都是导致网页在移动端平均需要超过14秒的时间来加载和互动的原因。这导致了对Lighthouse评分Core Web Vitals搜索排名的负面影响,并降低了用户参与度。

根据谷歌网络基础知识,第三方脚本会导致几个问题,包括:

  • 向多个服务器发出过多的网络请求。
  • 发送过多的JavaScript
  • 资源密集型的脚本解析和执行。
  • 没有足够的HTTP缓存
  • 缺少足够的服务器压缩资源。
  • 阻止内容显示,直到它们完成处理。
  • 使用已知对用户体验有害的传统API(如document.write())。
  • 过多的DOM元素或昂贵的CSS选择器。

当你的网页上有很多第三方脚本时,它们会阻止你自己的JavaScript。这对于需要这些第三方脚本来运行其业务的电子商务网站和在线市场来说变得尤为关键,而时间真的就是金钱。

将第三方脚本卸载到在后台线程中运行的网络工作者是一个潜在的解决方案,允许用户保留他们的脚本,同时提高性能。网络工作者同步执行,但只能与主线程进行异步通信。Web工作者也不能直接访问DOM,只有主线程可以。因此,关键的挑战是为在 Web Worker 内运行的 JavaScript 代码提供对 DOM 的某种访问,并使这种访问具有同步性(即使与主线程的通信必须保持异步)。

Partytown介绍

Partytown是一个轻量级的开源解决方案,它通过将第三方脚本卸载到在后台线程中运行的Web工作者,减少了第三方JavaScript的执行延迟。这就释放了浏览器的主线程来运行你自己的代码。它由Builder.io维护,目前处于测试阶段。

Builder.io也是Qwik的所在地,Qwik是一个开源的HTML优先、可恢复的网络应用程序框架,它使交互式网站只用HTML和CSS就能快速加载,只在需要时拉动JavaScript。

虽然Partytown不能解决由第三方脚本造成的所有瓶颈(在上述部分列出),但它确实通过以下方式解决了构建高性能网站的最大挑战:

  • 释放主线程资源,只用于主要网络应用的执行。
  • 对第三方脚本进行沙盒化处理,允许或拒绝它们对主线程API的访问。
  • 在网络工作者线程中隔离长期运行的任务。
  • 通过将DOM设置器/获取器批处理成组更新,减少来自第三方脚本的布局抖动。
  • 节制第三方脚本对主线程的访问。
  • 允许第三方脚本完全按照它们的代码运行,不做任何改动。
  • 从Web Worker内部同步读写主线程DOM操作,允许从Web Worker运行的脚本按预期执行。

Partytown背后的架构

尽管有一些创新技术加快了我们向浏览器交付JavaScript的速度(最小化、压缩、分发、代码分割、异步、延迟),但一旦代码进入浏览器,就会受到JavaScript是单线程语言这一事实的限制--一次只能运行一个脚本。

Partytown是一个懒惰的JavaScript库,帮助将资源密集型脚本重定向到网络工作者。为了确保各种规模的应用程序都能继续使用第三方脚本,而不会遇到性能障碍,Partytown将这些第三方脚本卸载到Web Worker中,并让你允许或拒绝它们对主线程API的访问。换句话说,不需要进入关键渲染路径的第三方脚本会在后台线程中执行。这就释放了浏览器的主线程来执行第一方的JavaScript,后者通常负责处理用户输入或绘制屏幕。

考虑到谷歌分析,它使用navigator.sendBeacon() 收集和发送跟踪数据。一方面,它是一个后台任务,可以异步运行。另一方面,Google Analytics在从documentwindow 读取数值时仍然需要同步的DOM API访问。Partytown允许从后台执行Google Analytics等脚本,同时像在主线程中一样访问DOM。

A picture showing how the code works with Partytown and without Partytown

Partytown如何工作

网络工作者的主要挑战是,它不能直接访问主线程访问的DOM API,如window, document,localStorage 。虽然可以在两个线程之间创建一个消息传递系统来代理DOM操作,但用于网络工作者/主线程通信的postMessage API是异步的。这意味着依赖同步DOM操作的第三方脚本将直接失败。

Partytown使用JavaScript代理、服务工作者和同步XHR请求,从Web工作者内部提供对DOM API的同步访问。Web Worker内对DOM API的访问是代理的,用被访问的方法和值创建同步XHR请求(例如,document.titlewindow.screen.width )。

这些请求被服务工作者拦截,服务工作者使用postMessage ,将API请求异步地转发给主线程。然而,通过将每个DOM API请求映射到一个同步的XHR,网络工作者会暂停执行,直到服务工作者做出回应。最终的结果是,从 Web Worker 中的第三方脚本的角度来看,这一切都是同步的。

这种方法的好处是,您不需要重写或重构您的第三方脚本,使其在 Web Worker 中工作。它们完全按照编码执行;它们只是在后台线程中工作。

此外,通过代理所有的DOM API访问,Partytown可以记录每一次读和写,甚至限制对某些DOM API的访问。

设置Partytown

Partytown不会自动将所有第三方脚本转移到网络工作者。要开始使用,开发人员需要 "选择加入"--也就是说,他们必须选择通过Partytown加载和执行哪些脚本。在命令行中使用npm来安装Partytown。

npm install @builder.io/partytown

接下来,将type="text/partytown" 属性添加到你想从网络工作者运行的每个第三方脚本中。

- <script>...</script>
+ <script type="text/partytown">...</script>

只有当特定脚本具有type="text/partytown" 属性时,Partytown才会被启用。这有两方面的作用:

  1. 防止主线程执行该脚本。
  2. 提供一个选择器供Partytown查询,如document.querySelectorAll('script[type="text/partytown"]')

下一步是在<head> 中内联Partytown片段。如果你使用React,我们建议使用<Partytown/> React 组件。

下面是一个在Next.js页面中包含<Partytown/> 组件的例子:

import Head from "next/head";
import { Partytown } from "@builder.io/partytown/react";

const Home = () => {
  return (
    <>
      <Head>
        <title>My App</title>
        <script type="text/partytown" src="https://example.com/analytics.js"></script>
        <Partytown />
      </Head>
      <main>...</main>
    </>
  );
};

export default Home;

对于特殊情况,可能需要进行少量的配置。Partytown适用于任何HTML页面,不需要特定的框架,但有一些集成(插件/包装器)可用,包括Next.js、Nuxt.js、React和Shopify Hydrogen。Partytown还为一些第三方服务,如Facebook Pixel、Adobe Launch和Google Tag Manager提供文档和演练

在设置Partytown时,重要的是先在几个页面上试用,并使用谷歌PageSpeed Insights测量改进情况。一旦你确认你的所有脚本都在工作,你就可以为网站的所有页面打开它。

行动中的Partytown

Builder.io网站使用Partytown和Qwik的组合,成功削减了99%的JavaScript。这极大地提高了性能,即使在移动端,PageSpeed Insights上的Google Lighthouse得分也达到100 分。总阻塞时间(TBT)和交互时间(TTI)也有大幅下降,这些指标衡量了第三方脚本对第一方JavaScript执行的延迟时间。

在线鞋类商店Atoms目前在其营销页面上使用Partytown(特别是在Why Atoms关于新闻礼品卡上)。他们目前正在努力在全站启用Partytown。

与建设者一起聚会

Partytown仍处于测试阶段,因此并非每个脚本都能发挥作用。Builder.io积极邀请人们测试Partytown并与团队分享他们的想法。用户可以在Partytown的GitHub上报告问题,要求集成和演练,或者贡献代码。Partytown还有一个活跃的Discord社区,在那里你可以帮助我们测试Partytown并加入对话。

Builder.io的目标是使高性能成为网站的默认功能。一个具有最佳性能的快速网站应该不需要任何配置就可以实现。Builder已经通过他们的开源解决方案Partytown和Qwik向这一理想迈出了第一步,这两个解决方案在使任何人都能实现近乎零的JavaScript网站方面起了关键作用。