首页IT科技你的软件非官网怎么办(你的应用太慢了,给我司带来了巨额损失,该怎么办)

你的软件非官网怎么办(你的应用太慢了,给我司带来了巨额损失,该怎么办)

时间2025-08-05 07:49:58分类IT科技浏览4861
导读:记得很久之前看过谷歌官方有这么样的声明:如果一个页面的加载时间从 1 秒增加到3 秒,那么用户跳出的概率将增加 32%。...

记得很久之前看过谷歌官方有这么样的声明:如果一个页面的加载时间从 1 秒增加到3 秒             ,那么用户跳出的概率将增加 32%              。

但是早在 2012 年                      ,亚马逊就计算出了      ,页面加载速度一旦下降一秒钟         ,每年就会损失 16 亿美元的销售额                   。于是                      ,这篇文章就想聊聊有没有方法来解决这种问题        。

什么?没赚到钱         ,是我的锅?

那么      ,是什么影响了页面的加载速度                      ,导致用户跳出?

其中有一个大的因素就是我们的应用用到了很多的第三方库           。

那么             ,有没有一种一举两得的方法   ,我即可以保留使用的第三方脚本                     ,又可以保证页面的加载速度?

其实                 ,我们知道 JavaScript 本质上是一种单线程语言,只运行一个事件循环                  。这意味着一次只执行一条语句           。由于这一限制                 ,当试图运行自己的代码以及任何第三方脚本时                     ,它们必须在同一线程中执行        。这意味着由于处理能力的限制   ,它们会减慢主线程和彼此的速度             ,也会减慢彼此的速度                   。

根据谷歌的说法                      ,添加第三方脚本后      ,有一些潜在的问题会产生         ,我列举了以下几点:

会向多个服务器发出过多的网络请求              。一个网站的请求越多                      ,它的加载时间就越长    。 发送太多的 JavaScript 会让主线程很忙                    。过多的 JavaScript 会阻碍 DOM 的构建         ,延迟页面呈现的速度                 。 cpu 密集型脚本解析和执行可能会延迟用户交互      ,并会导致电池电量消耗的更快。 不小心加载的第三方脚本可能会产生单点故障(SPOF)                 。 HTTP 缓存不足                      ,迫使经常直接从网络获取资源                    。 脚本中使用遗留 api(例如 document.write() )             ,对用户体验是有害的    。 脚本中包含过多的 DOM 元素或昂贵的 CSS 选择器              。 包括多个第三方嵌入   ,可能导致多个框架和库被多次拉入                     ,这加剧了性能问题                   。 第三方脚本也经常使用嵌入技术导致阻塞 window.onload 的执行                 ,例如使用 async或 defer        。

这些问题都可以通过谷歌浏览器的 Analytics 工具检测出来           。

现在,有一个改善第三方脚本的工具                 ,能帮助我们的应用减少大量的第三方脚本                     ,也是本篇文章要说的主角—— Partytown                  。

Partytown

Partytown 是一个 JavaScript 库   ,可以让你的第三方脚本交给 web worker 来处理             ,以消除他们可能对你的网站产生的性能影响           。为了抵消上述第三方脚本的负面影响                      ,Partytown 打算做以下事情:

释放主线程资源      ,仅用于主要 web 应用程序的执行        。 将第三方脚本放到沙箱         ,允许或拒绝它们访问主线程 api                   。 在 web worker 线程中隔离长时间运行的任务              。 通过将 DOM setter /getter 批处理到组更新中                      ,减少来自第三方脚本的布局抖动    。 限制第三方脚本对主线程的访问                    。 允许第三方脚本完全按照它们的编码方式运行         ,无需任何更改                 。 在 web worker 中同步读写主线程 DOM 操作      ,允许在 web worker 中运行的脚本按预期执行。

Partywork 运行方式

简单地说                      ,Partytown 添加了一个 worker 线程来允许在主线程和 worker 线程中执行                 。

要理解 Partytown             ,首先要了解现代网络浏览器使用的一些技术:

Web Workers API: 这使得在与 Web 应用程序的主执行线程分离的后台线程中运行脚本操作成为可能                    。Partytown 的理念是主线程应该专门用于你的第一方代码   ,任何不需要在关键路径上的脚本都应该移动到 web worker上    。因为主线程的性能比 web worker 线程的性能更重要              。 XMLHttpRequest (XHR): 对象用于与服务器交互                   。可以从URL检索数据                     ,而不必进行整个页面刷新        。这使得网页只更新页面的一部分                 ,而不会中断用户正在做的事情           。 Service Worker API: Service Worker 本质上充当了位于 web 应用程序             、浏览器和网络之间的代理服务器                  。它们主要用于创建有效的脱机体验,拦截网络请求                 ,并根据网络是否可用采取适当的操作                     ,以及更新驻留在服务器上的资源           。它们还允许访问推送通知和后台同步 api        。 Javascript 代理:代理对象允许你创建一个可以用来代替原始对象的对象   ,但它可能会重新定义基本的对象操作             ,如 get                      、set 和 define 属性                   。代理对象通常用于记录属性访问      、验证         、格式化或清除输入等              。

传统上                      ,主线程和 worker 线程之间的通信必须是异步的:因为为了让两个线程通信      ,它们不能使用阻塞调用    。Partytown 则不同                    。它允许从 web worker 执行的代码同步访问 DOM                 。这样做的好处是第三方脚本可以继续按照它们的编码方式工作。

如下图所示         ,运行在代理全局变量的 web worker 中的代码使用同步 XHR 使异步操作同步化                 。这将被 service worker 拦截                      ,主线程值将通过 postMessage 检索并发送回来                    。

如何集成 Partytown

你可以很容易地将它添加到任何站点         ,并使用 type="text/partytown" 标记任何你想要加载在 web worker 中的脚本    。

需要注意的是      ,Partytown 并不会自动将所有脚本转移到 web worker上                      ,而是采用了一种可选择的方法              。最好的情况是             ,开发人员可以准确地选择哪些脚本应该使用Partytown   ,而所有其他脚本将保持不变                   。

Partytown可以使用任何 HTML 页面                     ,不需要特定的框架        。然而                 ,为了让它更容易在各种框架或服务中使用,可以为它们的生态系统制作插件/包装器           。

只有当特定脚本具有 type="text/ Partytown " 属性时                 ,才会启用 Partytown                  。

<script type="text/partytown" src="third-parth.js"></script>

上面这段脚本执行时会产生几个事件:

通过使用 <script/>标签上的 type="text/partytown" 属性                     ,脚本不能在主线程上运行           。 Service worker 创建一个 “onfetch             ” 处理程序来拦截特定的请求        。 Web worker 会处理在 worker 线程中执行的脚本                   。 Web worker 创建 JavaScript 代理来复制和转发对主线程 api 的调用(比如DOM操作)              。 任何对JavaScript 代理的调用都使用同步XHR请求    。 Service worker 拦截请求   ,然后能够与主线程进行异步通信                    。 当 Service worker 从主线程接收到结果时             ,它会响应 web worker 的请求                 。 从在 web worker 上执行代码的角度来看                      ,一切都是同步的      ,对 document 的每次调用都是阻塞的。

执行步骤

任何你添加 type="text/partytown" 的脚本都会在默认情况下加载到 web worker 中         ,但是可以完全访问全局变量                 。 type="text/partytown" 属性做两件事:

通知浏览器不处理脚本                    。通过给脚本一个浏览器无法识别的 type 属性:“嵌入的内容被视为一个数据块                      ,浏览器不会处理它    。                      ” 提供一个 query 选择器         ,这样 Partytown 就可以找到所有要在web worker中运行的脚本              。当 document 准备好并且 Partytown 已经初始化时      ,Partytown 将查询所有脚本属性中含有 [type="text/ Partytown "] 属性的元素                   。你会注意到                      ,当一个脚本在web worker中执行后             ,它会得到一个更新的 type 属性: type="text/partytown-x"        。 // run in the worker fetch(/track, { body: JSON.stringify({ url: window.location.href // run on the main thread }) })

我们使用 JavaScript Proxy 向 worker 线程提供主线程全局变量   ,拦截它们并转发给主线程:

self.window = new Proxy({ get(key) { return getFromMainThread(key) } })

这里是最好的部分是: 使用一个同步 XHR 请求来阻塞 worker 线程                     ,并从主线程检索所需的值:

function getFromMainThread(prop) { request.open(POST, /proxytown, false) request.send(null) request.send(JSON.stringify({prop})) return JSON.parse(request.reponseText) }

现在我们可以使用 service worker 来拦截 /proxytown 请求                 ,向主线程异步postMessage 以获取所需的值并返回它:

self.addEventListener(fetch, event=>{ if(request.url === /proxytown) { event.respondWith(new Promise(async resolve=>{ resolve(await getFromMainThread(event.request.json())) })) } })

好了!你现在可以无缝地将一系列第三方脚本放到 web worker 中运行,从而消除主线程的性能成本           。如果感兴趣                 ,可以用一用                  。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python类的继承机制(Python中类的继承是什么)