当前位置: 首页 > news >正文

瞒不住了,Prefetch 就是一个大谎言

本文正在参加「金石计划」

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 为什么不能如你所愿呢? 原因主要由几点:

  1. Modulepreload 不能在大多数浏览器中使用。
  2. Firefox 有 network.dns.disablePrefetchFromHTTPS 选项,默认设置为 true。默认情况下,Firefox 不会在 HTTPS 上 prefetch 任何内容。考虑到现在大多数东西都是 HTTPS,这有效地禁用了Firefox上的预取。
  3. 一些移动浏览器忽略 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 过程。这个结果对我们来说非常有用,因为它允许我们消除由于延迟加载代码而导致的交互延迟。

相关文章:

瞒不住了,Prefetch 就是一个大谎言

本文正在参加「金石计划」 Prefetch 是一个谎言 我们知道&#xff0c;现在的应用程序已经发展到可以拆分为多个 JavaScript包了&#xff0c;为了获得更好的用户体验&#xff0c;这些 bundle 包通常需要预获取&#xff0c;即 prefetch! 但是现在的prefetch 效果有多糟糕我想你…...

这个时候了,你还不会不知道JavaMail API吧

一、概述 1.1 简述 JavaMail API 顾名思义&#xff0c;提供给开发者处理电子邮件相关的编程接口&#xff0c;它是Sun发布的用来处理email的API&#xff0c;其提供独立于平台且与协议无关的框架来构建邮件和消息传递应用。JavaMail API 提供了一组抽象类&#xff0c;用于定义组…...

JavaScript var let区别

文章目录JavaScript var & let区别变量作用域变量提升变量重复声明全局对象属性for循环中的作用域JavaScript var & let区别 var和let都是用来声明变量的关键字。 变量作用域 var声明的变量作用域是函数作用域或全局作用域&#xff0c;而let声明的变量作用域是块级作…...

Thinkphp 6.0容器和依赖注入

本节课我们来学习一下依赖注入的用法&#xff0c;以及容器的用法。 一&#xff0e;依赖注入 1. 手册对依赖注入比较严谨的说明&#xff0c;具体如下&#xff1a; 依赖注入其实本质上是指对类的依赖通过构造器完成自动注入&#xff0c;例如在控制器架构方法和操作 方法中一旦对参…...

Type javax.servlet.http.HttpServletRequest not present

运行环境 Swagger 3.0.0、springboot 3.0.0 产生原因&#xff1a; Swagger 3.0.0不支持spring3.0.0 两个解决方案&#xff1a; 1.降低springboot版本为2.x 2.放弃Swagger&#xff0c;使用 springdoc-openapi-starter-webmvc-ui 第二种解决方案&#xff1a; <dependen…...

一键配置Ubuntu的OpenHarmony基础编译环境

一键配置Ubuntu的OpenHarmony基础编译环境 一、配置前说明 该更新源仅适用于Ubuntu以下系列 Ubuntu18.04 Ubuntu20.04 Ubuntu22.04 强烈推荐Ubuntu20.04&#xff0c;本人使用的一直都是Ubuntu20.04 wsl的配置参见 如果使用的window wsl安装&#xff0c;则关于wsl配置可参考&a…...

ASP网络求职招聘系统的设计与实现

本文主要介绍了ASP&#xff0c;数据库等相关知识&#xff0c;同时较为详尽的阐述了网络求职招聘系统的实现。本系统是使用基于HTML语言&#xff0c;嵌套JavaScript源代码的ASP编程技术来开发&#xff0c;并以IIS为服务平台实现网络求职招聘系统的构建。后台数据库选用的是ACCES…...

面试—C++《智能指针》常考点

目录 1.为什么需要智能指针 2. 内存泄漏 2.1 什么是内存泄漏&#xff0c;内存泄漏的危害 2.2 内存泄漏分类 2.3 如何检测内存泄漏 2.4如何避免内存泄漏 3.智能指针的使用及原理 3.3 std::auto_ptr 3.4 std::unique_ptr 3.5 std::shared_ptr 1.为什么需要智能指针 下…...

自动化测试方案编写思路

澄清问题: 目标&#xff1a;完成项目的自动化测试&#xff0c;设计一个方案&#xff0c;告诉领导打算怎么做&#xff1f;有哪些流程&#xff1f;花多长时间&#xff1f;需要哪些资源帮助&#xff1f;达到什么样的效果&#xff1f; 现状&#xff1a;需求分析-是个什么样的项目&a…...

【爬虫】案例04:某小说网多线程小说下载

时光轮回&#xff0c;冬去春来&#xff0c;转眼时间来到了2023年4月。天空沥沥淅淅下着小雨&#xff0c;逐渐拉上了幕布。此刻&#xff0c;正值魔都的下班高峰&#xff0c;从地铁站出来的女孩子纷纷躲到一边&#xff0c;手指飞快的划过手机屏幕&#xff0c;似乎在等待男朋友送来…...

海外独立站创业,Shopify网站如何引流

上一期给大家科普了如何快速创建自己的独立站 但往往独立站的难点在于站外引流 今天就给大家分享可以通过哪些渠道给独立站引流 - ⚡SEO排名&#xff1a;Google SEO的重要性不必多说&#xff0c;尽快注册歌账号&#xff0c;并开通Google Ad和Google Merchant Center&#…...

基于51单片机的室内湿度加湿温度声光报警智能自动控制装置设计

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;单片机湿度 获取完整无水印论文报告&#xff08;内含电路原理图和源程序代码&#xff09; 在日常生活中加湿器得到了广泛的应用&#xff0c;但是现有的加湿器都需要手工控制开启和关闭并且不具备对室内空气温湿度的监测&am…...

解决:github爆 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

目录1. 背景2. 解决办法3. 原因&#xff0c;感兴趣的可以看看1. 背景 在拉取github上一个新项目的时候爆出 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 第一反应是电脑被黑了&#xff0c;传说中的中间人攻击(题外话一下&#xff0c;其实所有的代理软件都算是中间人哦~…...

【django开发手册】如何使用select_related进行一次连表查询

前言 Django是一款Python Web框架&#xff0c;致力于充分利用Python的简洁语法和语言特性来提高Web开发的效率。其中一个强大的特性是ORM&#xff08;Object-Relational Mapping&#xff09;&#xff0c;它使开发者可以使用Python代码而不是SQL查询语言来访问数据库。ORM不仅使…...

二、MySQL 基础

二、MySQL 基础 2.1 MySQL 简介 MySQL 是一款流行的开源数据库&#xff0c;也是一个关系型数据库管理系统 在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System&#xff1a;关系数据库管理系统)应用软件之一 2.1.1 MySQL 发展历史 时间里程碑1996…...

项目中常用写法(前端)

项目中常用写法&#xff08;前端&#xff09;vue等待某个方法执行结束后&#xff0c;在执行判断js是不是undefined类型父组件传值到子组件state的值在标签中直接使用读取html&#xff0c;去掉字符串中的html标签字符串去掉中括号去掉双引号判断数组中是否包含某个值在某个ui框架…...

【面试】Java并发编程面试题

文章目录基础知识为什么要使用并发编程多线程应用场景并发编程有什么缺点并发编程三个必要因素是什么&#xff1f;在 Java 程序中怎么保证多线程的运行安全&#xff1f;并行和并发有什么区别&#xff1f;什么是多线程多线程的好处多线程的劣势&#xff1a;线程和进程区别什么是…...

HAProxy和Nginx搭建负载均衡器

负载均衡器是一个常用于分布式计算和网络应用中的系统组件&#xff0c;主要用于将客户端的请求分发到多个后端服务器上&#xff0c;以实现高可用性、高性能和可扩展性。常见的负载均衡器软件包括HAProxy和Nginx。 本文将介绍负载均衡器的原理和应用&#xff0c;以及使用HAProx…...

【集大成篇】数据类型( C、C++、Java )对比

1、C 语言数据类型关键字取值范围内存占用字符型char -128~1271整 型short-32768~327672int-2147483648~2147483647 (10位数&#xff09;4long (int)-2147483648~2147483647 (10位数&#xff09;4/8long long (int)-9223372036854775808~-9223372036854775807 (19位数&#xff…...

python编程:从键盘输入一个正整数n(n>2),请编程求解并输出大小最接近n的素数(n本身除外)

python编程实现&#xff1a;从键盘输入一个正整数n(n>2),请编程求解并输出大小最接近n的素数(n本身除外) 一、编程题目 从键盘输入一个正整数n(n>2)&#xff0c;请编程求解并输出大小最接近n的素数(n本身除外)。 (温馨提示&#xff0c;结果可能是2个哦) 二、输入输出样例…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

腾讯云V3签名

想要接入腾讯云的Api&#xff0c;必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口&#xff0c;但总是卡在签名这一步&#xff0c;最后放弃选择SDK&#xff0c;这次终于自己代码实现。 可能腾讯云翻新了接口文档&#xff0c;现在阅读起来&#xff0c;清晰了很多&…...

Golang——6、指针和结构体

指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...

Caliper 配置文件解析:fisco-bcos.json

config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...