你的应用太慢了,给我司带来了巨额损失,该怎么办

2023-12-04 05:40

本文主要是介绍你的应用太慢了,给我司带来了巨额损失,该怎么办,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

记得很久之前看过谷歌官方有这么样的声明:如果一个页面的加载时间从 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" ' 属性做两件事:

  1. 通知浏览器不处理脚本。通过给脚本一个浏览器无法识别的 type 属性:“嵌入的内容被视为一个数据块,浏览器不会处理它。”
  2. 提供一个 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 中运行,从而消除主线程的性能成本。如果感兴趣,可以用一用。

这篇关于你的应用太慢了,给我司带来了巨额损失,该怎么办的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/452323

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

zoj3820(树的直径的应用)

题意:在一颗树上找两个点,使得所有点到选择与其更近的一个点的距离的最大值最小。 思路:如果是选择一个点的话,那么点就是直径的中点。现在考虑两个点的情况,先求树的直径,再把直径最中间的边去掉,再求剩下的两个子树中直径的中点。 代码如下: #include <stdio.h>#include <string.h>#include <algorithm>#include <map>#

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

【区块链 + 人才服务】区块链集成开发平台 | FISCO BCOS应用案例

随着区块链技术的快速发展,越来越多的企业开始将其应用于实际业务中。然而,区块链技术的专业性使得其集成开发成为一项挑战。针对此,广东中创智慧科技有限公司基于国产开源联盟链 FISCO BCOS 推出了区块链集成开发平台。该平台基于区块链技术,提供一套全面的区块链开发工具和开发环境,支持开发者快速开发和部署区块链应用。此外,该平台还可以提供一套全面的区块链开发教程和文档,帮助开发者快速上手区块链开发。

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景