你的应用太慢了,给我司带来了巨额损失,该怎么办
记得很久之前看过谷歌官方有这么样的声明:如果一个页面的加载时间从 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 中运行,从而消除主线程的性能成本。如果感兴趣,可以用一用。
相关文章:
![](https://img-blog.csdnimg.cn/0f0c332b2cd74f26951c81d61c1b4178.png)
你的应用太慢了,给我司带来了巨额损失,该怎么办
记得很久之前看过谷歌官方有这么样的声明:如果一个页面的加载时间从 1 秒增加到3 秒,那么用户跳出的概率将增加 32%。 但是早在 2012 年,亚马逊就计算出了,页面加载速度一旦下降一秒钟,每年就会损失 16 亿美元的销售额…...
![](https://img-blog.csdnimg.cn/38c4f0da6fb24917b3ddf471f737b6fe.png)
第十四届蓝桥杯三月真题刷题训练——第 22 天
目录 第 1 题:受伤的皇后_dfs 题目描述 输入描述 输出描述 输入输出样例 运行限制 代码: 思路: 第 2 题:完全平方数 问题描述 输入格式 输出格式 样例输入 1 样例输出 1 样例输入 2 样例输出 2 评测用例规模与约…...
![](https://img-blog.csdnimg.cn/61687de608d14c6a86ceb44f9d4a5267.png)
机器学习:朴素贝叶斯模型算法原理(含实战案例)
机器学习:朴素贝叶斯模型算法原理 作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏&…...
![](https://img-blog.csdnimg.cn/2308796d12a443db92648b553295f9ee.jpeg#pic_center)
Linux 多线程:理解线程
目录一、理解线程的思想二、Linux中的线程与进程1.Linux中的进程2.Linux中的线程三、线程的工作方式四、线程的独有数据与共享数据1.独有数据2.共享数据一、理解线程的思想 线程就是把一个进程分成多个执行部分,一个部分就是一个线程,比如可以让一个线程…...
![](https://img-blog.csdnimg.cn/7bac8ab8cbdf45aa8abd100b0c4f1109.png)
Web前端学习:章四 -- JavaScript初级(四)-- BOM
138:Object数据格式简介 1、object对象 JS中独有 的一种数据格式 名字可以随便取,值一般就那几种数据格式 139:BOM - JS跳转页面 BOM Browser Object Model:浏览器对象模型 使用JavaScript控制浏览器交互 控制浏览器里面的内…...
![](https://img-blog.csdnimg.cn/5c716e0eefac420cbe6cd59c5fd4bebd.png)
Lesson9.网络基础1
网络协议初识 所谓的协议就是人们为了通信的一种约定 操作系统要进行协议管理,必然会先描述,再组织协议本质就是软件,软件是可以"分层"协议在设计的时候,就是被层状的划分的, 为什么要划分成为层状结构 场景复杂功能解耦(便于人们进行各种维护)OSI七层模型 局域网中…...
![](https://img-blog.csdnimg.cn/img_convert/4f756c61770e11cf1f68e2df1c66c07c.png)
这几个SQL语法的坑,你踩过吗
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~ Github地址:https://github.com/…...
![](https://img-blog.csdnimg.cn/793b977f158f4247b66b06fc4ca78c78.png)
算法基础——复杂度
前言 算法是解决问题的一系列操作的集合。著名的计算机科学家Niklaus Wirth曾提出:算法数据结构程序,由此可见算法在编程中的重要地位。本篇主要讨论算法性能好坏的标准之一——复杂度。 1 复杂度概述 1.1 什么是复杂度 本文所讨论的复杂度是指通过事先…...
![](https://img-blog.csdnimg.cn/cba59e324f264c95be49b790b85ca4d7.jpeg)
基类与派生类对象的关系 派生类的构造函数
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...
![](https://img-blog.csdnimg.cn/a9118c6035a3446cae62fd6e54bd51bb.png)
【算法】生成分布式 ID 的雪花算法
ID 是数据的唯一、不变且不重复的标识,在查询数据库的数据时必须通过 ID 查询,在分布式环境下生成全局唯一的 ID 是一个重要问题。 雪花算法(snowflake)是一种生成分布式环境下全局唯一 ID 的算法,该算法由 Twitter 发…...
![](https://img-blog.csdnimg.cn/a6fce92223d74f9ba34e4ddb10797179.png)
Linux系统编程 - 基础IO(IO操作)
目录 预备知识 复习C文件IO相关操作 printf相关函数 fprintf snprintf 读取文件 系统文件IO操作 open函数 umask()函数 open函数返回值 预备知识 1.你真的理解文件原理和操作了吗?不是语言问题,是系统问题2.是不是只有C/C有文件操作呢&#x…...
![](https://www.ngui.cc/images/no-images.jpg)
基于 Avue 的 CRUD 表格组件封装
在 components 文件夹中,创建一个新的 .vue 文件,例如:AvueCrudTable.vue。 透传父组件传递的属性和事件 : 1、利用v-bind=“ a t t r s " 支持所有 a v u e 的使用方法并在其基础上进行封装 2 、使用 v − o n = " attrs"支持所有 avue 的使用方法并在其基…...
![](https://www.ngui.cc/images/no-images.jpg)
树莓派学习笔记(十三)基于框架编写驱动代码
文章目录一、代码分析:二、源码一、代码分析: 在内核中由于代码文件多,避免函数名重复,使用static将函数的作用域限制在该文件内 内核的打印函数printk和printf类似 file_operations结构体使用符号“ . ”指定参数,省…...
![](https://img-blog.csdnimg.cn/4bd9154e7d8c448680dd959fc1e79571.png)
vue事件修饰符之.prevent
.prevent 事件修饰符只是阻止默认事件,不会自动触发任何事件处理函数。因此,在使用 .prevent 事件修饰符时,需要自己编写相应的事件处理函数来处理事件。 例如,在上面的例子中,我们通过在表单上绑定 submit.prevent&q…...
![](https://img-blog.csdnimg.cn/c63ba5597c8d42faa4a0af1e3a88739c.png)
【SpringCloud AlibabaSentinel实现熔断与限流】
本笔记内容为尚硅谷SpringCloud AlibabaSentinel部分 目录 一、Sentinel 1、官网 2、Sentinel是什么 3、下载 4、特性 5、使用 二、安装Sentinel控制台 1、sentinel组件由2部分构成 2、安装步骤 1.下载 2.运行命令 3.访问sentinel管理界面 三、初始化演示工程 …...
![](https://img-blog.csdnimg.cn/img_convert/53b1b800084538ef3cc30d1040291475.png)
类与对象-封装
一、封装的意义封装是C面向对象三大特性之一语法: class name { 访问权限:属性行为 };注意:类中的属性和行为 统称为成员属性 又称 成员属性 / 成员变量行为 又称 成员函数 / 成员方法封装将属性和行为作为一个整体,表现生活中的事物例①&…...
![](https://img-blog.csdnimg.cn/e936faf2f1d149e9afe56aa1af71d3ba.png)
【回忆杀】2012年拥有第一台电脑【致逝去的青春】
高中说起 在2012年的时候吧,高考过后,那个时候一门心思的想当一名体育老师【现在居然还有这个想法,哈哈】,最后没有考上自己希望的大学我记得好像是2012年7月的时候就去重庆投靠朋友,他教我做模具,2012年做…...
![](https://img-blog.csdnimg.cn/511aae8d579240cd888d3287238baa16.png)
PointNeXt: Revisiting PointNet++ with Improved Training and Scaling Strategies
Abstract PointNet 是点云理解领域最有影响力的神经网络架构之一。虽然近期出现了 PointMLP 和 Point Transformer 等新型网络,它们的精度已经大大超过了 PointNet,但我们发现大部分性能提升是由于改进的训练策略,例如数据增强和优化技术以及…...
![](https://img-blog.csdnimg.cn/2901148a5531422d889fdca7f042d9f3.png)
打印九九乘法表-课后程序(JavaScript前端开发案例教程-黑马程序员编著-第2章-课后作业)
【案例2-9】打印九九乘法表 一、案例描述 考核知识点 for双重循环 练习目标 掌握for循环应用。实现九九乘法表。 需求分析 九九乘法表相信大家一点也不陌生,之前见到的乘法表是印刷在课程本之上的。而在本案例中我们将用JavaScript代码来实现九九乘法表。 案例分…...
![](https://img-blog.csdnimg.cn/60e3a6028436421990ad737ca37d4375.png#pic_center)
【Linux】基于阻塞队列的生产者消费者模型
🌠 作者:阿亮joy. 🎆专栏:《学会Linux》 🎇 座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根 目录👉为何要使用…...
![](https://www.ngui.cc/images/no-images.jpg)
【华为OD机试 2023最新 】 真正的密码(C++)
文章目录 题目描述输入描述输出描述用例题目解析C++题目描述 在一行中输入一个字符串数组,如果其中一个字符串的所有以索引0开头的子串在数组中都有,那么这个字符串就是潜在密码, 在所有潜在密码中最长的是真正的密码,如果有多个长度相同的真正的密码,那么取字典序最大的…...
![](https://www.ngui.cc/images/no-images.jpg)
差分算法(蓝桥杯复习+例题讲解+模板c++)
文章目录差分介绍差分应用区间加区间求和总结3729. 改变数组元素100. 增减序列文章首发于:My Blog 欢迎大佬们前来逛逛 差分介绍 差分是一种常见的算法,用于快速修改数组中某一段区间的值。 差分的思想就是预处理出数组的差分数组,然后修改…...
![](https://img-blog.csdnimg.cn/e01885404c2345fcb97311ce9fd4ce9f.png)
CSS+ JS 实现手电筒效果
前言概述 JavaScript 结合 CSS 打造的一款图片特效,当鼠标拖拽滑块时,让本该置灰的图片局部恢复本来的颜色。且该效果随着你的鼠标的按下时的移动而移动。 核心功能 图片置灰 拖拽功能 让滑块位置处的图片恢复本来的颜色 实现原理 这个的实现原理并不…...
![](https://img-blog.csdnimg.cn/img_convert/c792566ef75d518c12d0dd22acdf27cb.png)
2021地理设计组二等奖:基于InSAR和指数分析的地面沉降风
作品简介 一、作品背景 地面沉降是指地面高程的降低, 又称地面下沉或地沉, 是以缓慢、难以察觉的向下垂直运动为主, 是指在自然和人为因素作用下, 由于地壳表层土体压缩而导致区域性地面标高降低的一种环境现象。目前, 地面沉降己成为城市化进程中普遍存在的生态环境问题, 成为…...
![](https://img-blog.csdnimg.cn/69ac8716cc054587a1eb4b52977118dd.png)
计算机操作系统(第四版)第二章进程的描述与控制—课后习题答案
1.什么是前趋图?为什么要引入前趋图? 前趋图是一个有向无循环图,记为DAG,用于描述进程之间执行的先后关系。 2.试画出下面四条语句的前趋图: S1:axy; S2:bz1; S3:ca-b; S4:wc1; 3.为什么程序并发执行会产生间断性特征&…...
![](https://img-blog.csdnimg.cn/81dd03aa3ac84129826f7d9495382df7.png)
CAN通信----电路图
CAN通信----基本原理 一、CAN总线网络连接 1.闭环总线网络----ISO11898 闭环总线网络高速、短距离,它的总线最大长度为 40m,通信速度最高为 1Mbps,总线的两端各要求有一个120 欧的电阻。 2.开环总线网络----ISO11519 开环总线网络低速、…...
![](https://img-blog.csdnimg.cn/img_convert/47e451fdfc22576035a46d4f978714b8.png)
Windows系统安装ElasticSearch(一)
一 ES介绍Elasticsearch 是一个分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎.当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以进行以下工作:分布式实时文件存储&#…...
![](https://www.ngui.cc/images/no-images.jpg)
linux 产生随机数 并遍历
1、产生随机数 varRANDOMvarRANDOM varRANDOMvar[ $var % 150 ] 2、产生不重复的随机数 $ entries($(shuf -i 0-149 -n 15)) $ echo “${entries[]}” 3、对随机数排序 $ entries($(shuf -i 0-149 -n 15 | sort -n)) $ echo “entries[]"12224549546678798393118119124140…...
![](https://www.ngui.cc/images/no-images.jpg)
【3.24】Mybatis常见面试题
Mybatis常见面试题 #{}和¥{}的区别是什么? 【#】:底层执行SQL使用PreparedStatement对象,预编译SQL,相对安全。入参使用占位符的方式。 【$】:底层执行SQL使用Statement对象,入参使用SQL拼接的…...
![](https://img-blog.csdnimg.cn/img_convert/28421c67df734404ab8f6e8d6b7086c0.png)
IDEA 热部署,修改代码不用重启项目
热部署指在修改项目代码的时候不重启服务器让修改生效。安装JRebel and XRebelFile->Settings,然后Plugins-> Marketplace,输入JRebel,安装如下插件——JRebel and XRebel ,重启idea激活JRebel and XRebel第一行输入网址&am…...
![](https://img-blog.csdnimg.cn/20200111113225791.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzMTYyNQ==,size_16,color_FFFFFF,t_70)
网络网站建设办公/如何做宣传推广营销
elasticsearch kibana使用说明 kibana是一个开源的可视化分析平台,常用于处理elasticsearch中的数据,可用图表等形式直观地展现数据 **************************** 配置文件 server.name: kibana server.port: 5601#连接的elasticsearch信息 elasticsea…...
![](/images/no-images.jpg)
百度提交网站收录/seo排名推广工具
在C的类的数据成员的访问权限分为三种:public、protect和private。private表示自己本类私有,不允许其它类的直接访问;protected表示自己及子孙可以访问,其它族类不允许直接访问,我们可以把它比作是本家族的共同财富&am…...
![](https://img-blog.csdnimg.cn/e01f608394564e2f8c5067209cb50a9f.jpeg#pic_center)
实事热点新闻事件/网站建设优化
DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…...
![](/images/no-images.jpg)
台州千寻网站建设公司/深圳网络营销推广中心
使用tree命令导出windows的文件夹/文件的目录树 TREE [drive:][path] [/F] [/A] /F 显示每个文件夹中文件的名称。(带扩展名) /A 使用 ASCII 字符,而不使用扩展字符。 tree /f > list.txt -- 将带扩展名的文件目录输出到list.txt…...
![](https://img-blog.csdnimg.cn/img_convert/00857bb40ba09a157c5e89aa432f02f2.png)
ps个人主页设计/百度搜索引擎优化方式
一、在canvas画布中如何加载图片---用drawImage( )方法drawImage用法的三种情况:1、在画布指定位置定义图像ctx.drawImage(img,x,y);注:此时画布上显示的图片大小是图片的默认大小2、在画布上定位图像,并规定图像的宽度和高度:ctx…...
![](/images/no-images.jpg)
数字营销证书/高级seo
因为看到很多公司招聘需要有linux平台下的开发经验,所以今天在笔记本上装了一个Kubuntu作为以后学习的平台。本文采用的是win7Kubuntu双系统的模式,尽管最后安装成功了,但是中间有很多波折在此记下来以备以后再次发生同样的事情。首先&#x…...