本文正在参加「金石计划」
Prefetch 是一个谎言
我们知道,现在的应用程序已经发展到可以拆分为多个 JavaScript包了,为了获得更好的用户体验,这些 bundle 包通常需要预获取,即 prefetch
! 但是现在的prefetch
效果有多糟糕我想你也知道。
例如,为了让应用程序拆解成多个包,在你的代码的某些地方,你会进行动态导入,比如 import('./some-dependency.js')
。但是作为开发人员,你或许也会在代码片段中插入额外的动态导入。下面这段代码中,假设你将代码放在惰性加载块后面的 Buy 按钮后面,看起来像这样:
export default () => {return (<div><button onClick={async () => {// 惰性加载点击“购买”按钮背后的逻辑。(await import('./buy.js')).default();}}>Buy</button></div>);
};
但是这样做,现在你就会有一个新的问题要解决!当用户单击 Buy 按钮时,浏览器会惰性加载 buy.js
包。根据 bundle 的大小和网络的速度,这可能会引入一个显著的、明显的延迟。那我们能做些什么来改善呢?
Prefetch
幸运的是,浏览器自带 Prefetch 支持!所以你会把这样的东西放到头部部分。这个时候,你可能认为你已经解决上面提到问题。
<head><link rel="prefetch" href="buy.js"/><!-- 或选择一个可替代的策略<link rel="preload" href="buy.js"/><link rel="modulepreload" href="buy.js"/>-->
</head>
但是这段代码真的会如你所愿吗? 你也不太确定,因此接着,你在 Chrome 中测试它,发现一切都能正常工作。
但是很快,你就会得到反馈,在许多情况下,用户必须等待 Buy 按钮执行其操作。这种额外的等待正是损害用户体验的底线。那 prefetch 为什么不能如你所愿呢? 原因主要由几点:
Modulepreload
不能在大多数浏览器中使用。- Firefox 有
network.dns.disablePrefetchFromHTTPS
选项,默认设置为true
。默认情况下,Firefox 不会在HTTPS
上 prefetch 任何内容。考虑到现在大多数东西都是 HTTPS,这有效地禁用了Firefox上的预取。 - 一些移动浏览器忽略 prefetch,因为移动浏览器认为这是在移动网络上,并试图节省带宽。
在闲置的时候加载
因此,大多数浏览器只在 network 空闲时才处理 prefetch。这是有意义的,但是为了让应用程序具有交互性,需要确保在出现次要事物(如高分辨率图像)之前出现交互性。如果等到页面上的所有东西都加载后才开始获取JavaScript,通常为时已晚。
你可以想象一个网站向你展示照片的时候。如果照片很大,需要下载一段时间。但你想在所有照片下载之前就开始与网站互动。但在所有图像都被解析之后再来获取 JavaScript 可能不是你想要的,因为这样会耗费你的耐心。
这个问题实际上说明了缺乏对浏览器中“何时”解析 Prefetch 的控制。
重复加载
prefetch 本应改善交互性,但在某些情况下,它可能会恶化交互性。
例如下面这段代码:
// 1. prefetch 开始
<link rel="prefetch" href="buy.js"/>// 2. 用户交互需要执行code,但是 prefetch 没有生效,于是重新 prefetch
<button onClick={async () => {// 惰性加载点击“购买”按钮背后的逻辑。(await import('./buy.js')).default();
}}>Buy</button>
想象一下如果你的连接速度很慢的时候,开始 Prefetch 并开始下载JavaScript。在JavaScript完全下载之前,用户与应用程序进行交互。现在,import('./buy.js')
被执行,但是 buy.js
不在缓存中。正在运行的 buy.js
请求尚未完成。但是由于请求是不完整的,浏览器不知道缓存头是什么,所以它不知道重用请求是否安全。所以浏览器做了安全的事情,发出另一个 buy.js
资源请求。现在,对同一资源的两个请求正在运行。
更糟糕的是,原始资源被解析,buy.js
被插入到浏览器缓存中,但是资源的解析并没有解除用户交互的阻塞。相反,UI 必须等待第二个 buy.js
返回,然后才能解除阻塞。
因此,prefetch 在某些情况下,可能导致多次请求相同的资源。
来自 Console 的警告
最后,如果某些浏览器检测到给定的预取资源在 x 秒内未被使用,则会发出控制台警告。因为浏览器会认为,你没有使用到它,就不应该预取它。
该怎么做
我觉得真正的 prefetch 是一种提示,告诉浏览器你将需要一些东西,因此浏览器应该在下载时有一个良好的开端,但我们想要的是用 用户可能需要的交互代码预填充缓存。
理想情况下,我们希望控制缓存,以便:
- 控制何时填充缓存。
- 理解 chunk 的依赖关系图,这样我们也可以 prefetch 合成的 bundle。
- 控制请求,以便在请求尚未在 bundle 中时可以解除请求。
简单而言,我们希望从一个被动的执行预取转变为一个主动控制预取。
事实证明,service worker
能做到。Service worker 可以拦截请求并控制缓存中的内容。使用 service worker,我们可以对流程进行正确的控制,还可以了解 chunk 依赖关系图,并可以加载相关代码。
但是创建这样一个service worker并不容易,所以大多数开发人员都不这么做。
结论
你或许经常看到是“专家”给出的常见的性能优化建议中包含了 prefetch,以确保惰性加载的块不会对用户交互造成延迟。但事实证明,现实从来没有这么简单,使用 prefetch 在实践中并不像你所希望的那样有效。
相反,我们建议使用 service worker
来完全控制 prefetch 过程。这个结果对我们来说非常有用,因为它允许我们消除由于延迟加载代码而导致的交互延迟。
查看全文
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.dgrt.cn/a/2173391.html
如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!
相关文章:
瞒不住了,Prefetch 就是一个大谎言
本文正在参加「金石计划」
Prefetch 是一个谎言
我们知道,现在的应用程序已经发展到可以拆分为多个 JavaScript包了,为了获得更好的用户体验,这些 bundle 包通常需要预获取,即 prefetch! 但是现在的prefetch 效果有多糟糕我想你……
Sigrity仿真之Power SI走线阻抗及耦合(串扰)分析
1.打开Power SI: 2. 导入板卡.spd文件: 3.进行板卡层叠参数设置: (1)、板卡层厚和介质要根据制版说明文件进行实际调整,否则仿真结果偏差很大,不具有参考意义:(填写厚度的时候注意单位的换算(表层0.5+镀铜的话,按大概值1.5mil,内层1OZ的按1.25mil)) (2)PAD属……
蓝桥杯每日一真题——[蓝桥杯 2018 省 AB] 全球变暖
文章目录[蓝桥杯 2018 省 AB] 全球变暖题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示思路:全部代码:[蓝桥杯 2018 省 AB] 全球变暖
题目描述
你有一张某海域 NNN \times NNN 像素的照片,. 表示海洋、 # 表示陆地,……
大数据技术之Spark(五)——RDD持久化
一、什么是RDD持久化
以wordCount为例,我们希望实现两个功能,最后一步不需要聚合操作,将mapRDD的结果放在不同的组中。
object Spark01_RDD_Persist {def main(args: Array[String]): Unit {val conf new SparkConf().setAppName("W……
数组–二分查找 专题训练
目录一、数组1.1 二分查找1.2 其他语言版本一、数组
1.1 二分查找
704. 二分查找 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标……
[BJDCTF2020]Cookie is so stable(PHP|Twig|SSTI)
目录
信息收集
hint页面
flag页面
命令执行
reference 信息收集
hint页面
<!– Why not take a closer look at cookies? –>
flag页面
输入任意内容(这里输入admin) 这里第一反应是cookie类的SQL注入?但是发现这里其实并没……
有趣!深挖推特开源算法;ChatGPT封号对策汇总;ControlNet最全教程;搭建ChatGPT应用;构建开源项目阅读工作流 | ShowMeAI日报
👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 『推特开源了推荐算法源码』大佬分析出了11条有意思的规律…… 3月31日,Twitter 对其推荐算法进行了开源。Steven Tey 持续……
LeetCode 1641. 统计字典序元音字符串的数目 / 1637. 两点之间不包含任何点的最宽垂直区域 / 1053. 交换一次的先前排列
1641. 统计字典序元音字符串的数目
2023.3.29 每日一题
题目描述
给你一个整数 n,请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。
字符串 s 按 字典序排列 需要满足:对于所有有效的 i,s[i] 在字母表中的……
解决:github爆 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
目录1. 背景2. 解决办法3. 原因,感兴趣的可以看看1. 背景
在拉取github上一个新项目的时候爆出 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 第一反应是电脑被黑了,传说中的中间人攻击(题外话一下,其实所有的代理软件都算是中间人哦~……
jvm复习: invokevirtual的执行流程
找到操作数栈顶的第一个元素所指向的对象的实际类型,如果它包含invokevirtual指令后跟随的符号引用中的方法名,则调用操作数栈顶元素的实际类型的那个方法。如果没有找到,则沿着类继承的层次继续向上查找。如果最终没有找到,则会抛……
【Java开发】设计模式 12:解释器模式
1 解释器模式介绍
解释器模式是一种行为型设计模式,它提供了一种方法来解释语言、表达式或符号。
在该模式中,定义了一个表达式接口,并实现了对应的表达式类,这些类可以解释不同的符号组成的表达式,从而实现对语言的……
反序列化渗透与攻防(五)之shiro反序列化漏洞
Shiro反序列化漏洞
Shiro介绍
Apache Shiro是一款开源安全框架,提供身份验证、授权、密码学和会话管理。Shiro框架直观、易用,同时也能提供健壮的安全性
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默……
vue2+vue3
vue2vue3尚硅谷vue2vue2 课程简介【02:24】vue2 Vue简介【17:59】vue2 Vue官网使用指南【14:07】vue2 搭建Vue开发环境【13:54】vue2 Hello小案例【22:25】了解: 不常用常用:id 更常用 简单class差值总结vue 实例vue 模板 : 先 取 ࿰……
【hello Linux】环境变量
目录 1. 环境变量的概念 2. 常见的环境变量 3. 查看环境变量 4. 和环境变量相关的命令 5. 环境变量的组织方式 6. 通过代码获取环境变量 7. 通过系统调用获取环境变量 Linux🌷 在开始今天的内容之前,先来看一幅图片吧! 不知道你们是否和我一……
【Linux基础】常用命令整理
ls命令
-a选项,可以展示隐藏的文件和文件夹-l选项,以列表形式展示内容-h,需要和-l搭配使用,可以展示文件的大小单位ls -lah等同于la -a -l -h
cd命令(change directory)
语法:cd [Linux路径]……
客快物流大数据项目(一百一十二):初识Spring Cloud
文章目录
初识Spring Cloud
一、Spring Cloud简介
二、SpringCloud 基础架构图…
C和C++中的struct有什么区别
区别一: C语言中: Struct是用户自定义数据类型(UDT)。 C语言中: Struct是抽象数据类型(ADT),支持成员函数的定义。
区别二:
C中的struct是没有权限设置的,……
docker的数据卷详解
数据卷 数据卷是宿主机中的一个目录或文件,当容器目录和数据卷目录绑定后,对方修改会立即同步
一个数据卷可以同时被多个容器同时挂载,一个容器也可以被挂载多个数据卷
数据卷作用:容器数据持久化 /外部机器和容器间接通信 /容器……
13、Qt生成dll-QLibrary方式使用
Qt创建dll,使用QLibrary类方式调用dll
一、创建项目
1、新建项目->其他项目->Empty qmake Project->Choose 2、输入项目名,选择项目位置,下一步 3、选择MinGW,下一步 4、完成 5、.pro中添加TEMPLATE subdirsÿ……
基于mapreduce 的 minHash 矩阵压缩
Minhash作用: 对大矩阵进行降维处理,在进行计算俩个用户之间的相似度。
比如: 俩个用户手机下载的APP的相似度,在一个矩阵中会有很多很多的用户要比较没俩个用户之间的相似度是一个很大的计算任务 如果首先对这个矩阵降维处理&am……
编程日记2023/4/16 14:50:37